generic support for EMS+

This commit is contained in:
proddy
2019-04-17 22:59:07 +02:00
parent 9253b7b233
commit 84042e8d59
7 changed files with 309 additions and 333 deletions

View File

@@ -99,8 +99,8 @@ command_t PROGMEM project_cmds[] = {
{true, "led_gpio <gpio>", "set the LED pin. Default is the onboard LED (D1=5)"},
{true, "dallas_gpio <gpio>", "set the pin for external Dallas temperature sensors (D5=14)"},
{true, "dallas_parasite <on | off>", "set to on if powering Dallas via parasite"},
{true, "thermostat_type <type ID>", "set the thermostat type id (e.g. 10 for 0x10)"},
{true, "boiler_type <type ID>", "set the boiler type id (e.g. 8 for 0x08)"},
{true, "thermostat_type <device ID>", "set the thermostat type id (e.g. 10 for 0x10)"},
{true, "boiler_type <device ID>", "set the boiler type id (e.g. 8 for 0x08)"},
{true, "silent_mode <on | off>", "when on all automatic Tx is disabled"},
{true, "shower_timer <on | off>", "notify via MQTT all shower durations"},
{true, "shower_alert <on | off>", "send a warning of cold water after shower time is exceeded"},
@@ -358,7 +358,7 @@ void showInfo() {
myDebug("%sBoiler stats:%s", COLOR_BOLD_ON, COLOR_BOLD_OFF);
// version details
myDebug(" Boiler type: %s", ems_getBoilerDescription(buffer_type));
myDebug(" Boiler: %s", ems_getBoilerDescription(buffer_type));
// active stats
if (ems_getBusConnected()) {
@@ -461,7 +461,7 @@ void showInfo() {
if (ems_getThermostatEnabled()) {
myDebug(""); // newline
myDebug("%sThermostat stats:%s", COLOR_BOLD_ON, COLOR_BOLD_OFF);
myDebug(" Thermostat type: %s", ems_getThermostatDescription(buffer_type));
myDebug(" Thermostat: %s", ems_getThermostatDescription(buffer_type));
if ((ems_getThermostatModel() == EMS_MODEL_EASY) || (ems_getThermostatModel() == EMS_MODEL_BOSCHEASY)) {
// for easy temps are * 100
// also we don't have the time or mode
@@ -796,7 +796,7 @@ void do_ledcheck() {
void do_scanThermostat() {
if ((ems_getBusConnected()) && (!myESP.getUseSerial())) {
myDebug("> Scanning thermostat message type #0x%02X...", scanThermostat_count);
ems_doReadCommand(scanThermostat_count, EMS_Thermostat.type_id);
ems_doReadCommand(scanThermostat_count, EMS_Thermostat.device_id);
scanThermostat_count++;
}
}
@@ -913,13 +913,13 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) {
EMSESP_Status.dallas_parasite = json["dallas_parasite"];
// thermostat_type
if (!(EMS_Thermostat.type_id = json["thermostat_type"])) {
EMS_Thermostat.type_id = EMSESP_THERMOSTAT_TYPE; // set default
if (!(EMS_Thermostat.device_id = json["thermostat_type"])) {
EMS_Thermostat.device_id = EMSESP_THERMOSTAT_TYPE; // set default
}
// boiler_type
if (!(EMS_Boiler.type_id = json["boiler_type"])) {
EMS_Boiler.type_id = EMSESP_BOILER_TYPE; // set default
if (!(EMS_Boiler.device_id = json["boiler_type"])) {
EMS_Boiler.device_id = EMSESP_BOILER_TYPE; // set default
}
// silent mode
@@ -950,8 +950,8 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) {
}
if (action == MYESP_FSACTION_SAVE) {
json["thermostat_type"] = EMS_Thermostat.type_id;
json["boiler_type"] = EMS_Boiler.type_id;
json["thermostat_type"] = EMS_Thermostat.device_id;
json["boiler_type"] = EMS_Boiler.device_id;
json["led"] = EMSESP_Status.led;
json["led_gpio"] = EMSESP_Status.led_gpio;
@@ -1039,13 +1039,13 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
// thermostat_type
if (strcmp(setting, "thermostat_type") == 0) {
EMS_Thermostat.type_id = ((wc == 2) ? (uint8_t)strtol(value, 0, 16) : EMS_ID_NONE);
EMS_Thermostat.device_id = ((wc == 2) ? (uint8_t)strtol(value, 0, 16) : EMS_ID_NONE);
ok = true;
}
// boiler_type
if (strcmp(setting, "boiler_type") == 0) {
EMS_Boiler.type_id = ((wc == 2) ? (uint8_t)strtol(value, 0, 16) : EMS_ID_NONE);
EMS_Boiler.device_id = ((wc == 2) ? (uint8_t)strtol(value, 0, 16) : EMS_ID_NONE);
ok = true;
}
@@ -1113,18 +1113,18 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
myDebug(" dallas_gpio=%d", EMSESP_Status.dallas_gpio);
myDebug(" dallas_parasite=%s", EMSESP_Status.dallas_parasite ? "on" : "off");
if (EMS_Thermostat.type_id == EMS_ID_NONE) {
if (EMS_Thermostat.device_id == EMS_ID_NONE) {
myDebug(" thermostat_type=<not set>");
} else {
myDebug(" thermostat_type=%02X", EMS_Thermostat.type_id);
myDebug(" thermostat_type=%02X", EMS_Thermostat.device_id);
}
myDebug(" heating_circuit=%d", EMSESP_Status.heating_circuit);
if (EMS_Boiler.type_id == EMS_ID_NONE) {
if (EMS_Boiler.device_id == EMS_ID_NONE) {
myDebug(" boiler_type=<not set>");
} else {
myDebug(" boiler_type=%02X", EMS_Boiler.type_id);
myDebug(" boiler_type=%02X", EMS_Boiler.device_id);
}
myDebug(" silent_mode=%s", EMSESP_Status.silent_mode ? "on" : "off");
@@ -1243,7 +1243,7 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
ems_setThermostatMode(_readIntNumber());
ok = true;
} else if (strcmp(second_cmd, "read") == 0) {
ems_doReadCommand(_readHexNumber(), EMS_Thermostat.type_id);
ems_doReadCommand(_readHexNumber(), EMS_Thermostat.device_id);
ok = true;
} else if (strcmp(second_cmd, "scan") == 0) {
startThermostatScan(_readIntNumber());
@@ -1270,7 +1270,7 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
ok = true;
}
} else if (strcmp(second_cmd, "read") == 0) {
ems_doReadCommand(_readHexNumber(), EMS_Boiler.type_id);
ems_doReadCommand(_readHexNumber(), EMS_Boiler.device_id);
ok = true;
} else if (strcmp(second_cmd, "tapwater") == 0) {
char * third_cmd = _readWord();

File diff suppressed because it is too large Load Diff

View File

@@ -13,8 +13,8 @@
#include <Arduino.h>
// EMS IDs
#define EMS_ID_NONE 0x00 // Fixed - used as a dest in broadcast messages and empty type IDs
#define EMS_PLUS_ID_NONE 0x01 // Fixed - used as a dest in broadcast messages and empty type IDs
#define EMS_ID_NONE 0x00 // Fixed - used as a dest in broadcast messages and empty device IDs
#define EMS_PLUS_ID_NONE 0x01 // Fixed - used as a dest in broadcast messages and empty device IDs
#define EMS_ID_ME 0x0B // Fixed - our device, hardcoded as the "Service Key"
#define EMS_ID_DEFAULT_BOILER 0x08
#define EMS_ID_SM 0x30 // Solar Module SM10 and SM100
@@ -102,14 +102,14 @@ typedef struct {
typedef struct {
_EMS_TX_TELEGRAM_ACTION action; // read, write, validate, init
uint8_t dest;
uint8_t type;
uint16_t type;
uint8_t offset;
uint8_t length;
uint8_t dataValue; // value to validate against
uint8_t type_validate; // type to call after a successful Write command
uint16_t type_validate; // type to call after a successful Write command
uint8_t comparisonValue; // value to compare against during a validate
uint8_t comparisonOffset; // offset of where the byte is we want to compare too later
uint8_t comparisonPostRead; // after a successful write call this to read
uint16_t comparisonPostRead; // after a successful write call this to read from this type ID
bool forceRefresh; // should we send to MQTT after a successful Tx?
uint32_t timestamp; // when created
uint8_t data[EMS_MAX_TELEGRAM_LENGTH];
@@ -120,6 +120,12 @@ typedef struct {
uint32_t timestamp; // timestamp from millis()
uint8_t * telegram; // the full data package
uint8_t length; // length in bytes
uint8_t src; // source ID
uint8_t dest; // destination ID
uint16_t type; // type ID as a double byte to support EMS+
uint8_t offset; // offset
uint8_t * data; // pointer to where telegram data starts
bool emsplus; // true if ems+/ems 2.0
} _EMS_RxTelegram;
// default empty Tx
@@ -142,22 +148,22 @@ const _EMS_TxTelegram EMS_TX_TELEGRAM_NEW = {
typedef struct {
uint8_t model_id;
uint8_t product_id;
uint8_t type_id;
uint8_t device_id;
char model_string[50];
} _Boiler_Type;
typedef struct {
uint8_t model_id;
uint8_t product_id;
uint8_t type_id;
uint8_t device_id;
char model_string[50];
} _Other_Type;
// Definition for thermostat type
// Definition for thermostat devices
typedef struct {
uint8_t model_id;
uint8_t product_id;
uint8_t type_id;
uint8_t device_id;
char model_string[50];
bool read_supported;
bool write_supported;
@@ -165,7 +171,7 @@ typedef struct {
typedef struct {
uint8_t product_id;
uint8_t type_id;
uint8_t device_id;
char version[10];
char model_string[50];
} _Generic_Type;
@@ -226,7 +232,7 @@ typedef struct { // UBAParameterWW
// settings
char version[10];
uint8_t type_id; // this is typically always 0x08
uint8_t device_id; // this is typically always 0x08
uint8_t product_id;
} _EMS_Boiler;
@@ -244,8 +250,8 @@ typedef struct {
// Thermostat data
typedef struct {
uint8_t type_id; // the type ID of the thermostat
uint8_t model_id; // which Thermostat type
uint8_t device_id; // the device ID of the thermostat
uint8_t model_id; // thermostat model
uint8_t product_id;
bool read_supported;
bool write_supported;
@@ -269,21 +275,20 @@ typedef struct {
} _EMS_Thermostat;
// call back function signature for processing telegram types
typedef void (*EMS_processType_cb)(uint8_t src, uint8_t * data, uint8_t length);
typedef void (*EMS_processType_cb)(_EMS_RxTelegram * EMS_RxTelegram);
// Definition for each EMS type, including the relative callback function
typedef struct {
uint8_t model_id;
uint8_t type;
uint16_t type; // long to support EMS+
const char typeString[50];
EMS_processType_cb processType_cb;
bool emsplus;
} _EMS_Type;
// function definitions
extern void ems_parseTelegram(uint8_t * telegram, uint8_t len);
void ems_init();
void ems_doReadCommand(uint8_t type, uint8_t dest, bool forceRefresh = false);
void ems_doReadCommand(uint16_t type, uint8_t dest, bool forceRefresh = false);
void ems_sendRawTelegram(char * telegram);
void ems_setThermostatTemp(float temperature, uint8_t temptype = 0);

View File

@@ -12,7 +12,6 @@
#include "ems.h"
/*
* Common
*/
@@ -96,7 +95,7 @@
#define EMS_OFFSET_EasyStatusMessage_curr 8 // current temp
// RC1010 specific
#define EMS_TYPE_RC1010StatusMessage 0x00 // is an automatic thermostat broadcast giving us temps
#define EMS_TYPE_RC1010StatusMessage 0x01A5 // is an automatic thermostat broadcast giving us temps
#define EMS_TYPE_RC1010Set 0x03 // setpoint temp message
#define EMS_OFFSET_RC1010StatusMessage_setpoint 3 // setpoint temp
#define EMS_OFFSET_RC1010StatusMessage_curr 1 // current temp
@@ -129,16 +128,22 @@ typedef enum {
} _EMS_MODEL_ID;
// EMS types for known Buderus/Bosch devices. This list will be extended when new devices are recognized.
// format is MODEL_ID, PRODUCT ID, TYPE_ID, DESCRIPTION
// format is MODEL_ID, PRODUCT ID, TYPE_ID, DESCRIPTION, EMSPLUS
const _Boiler_Type Boiler_Types[] = {
{EMS_MODEL_UBA, 72, 0x08, "MC10 Module"},
{EMS_MODEL_UBA, 123, 0x08, "Buderus GB172/Nefit Trendline"},
{
EMS_MODEL_UBA,
123,
0x08,
"Buderus GB172/Nefit Trendline",
},
{EMS_MODEL_UBA, 115, 0x08, "Nefit Topline Compact"},
{EMS_MODEL_UBA, 203, 0x08, "Buderus Logamax U122"},
{EMS_MODEL_UBA, 208, 0x08, "Buderus Logamax plus"},
{EMS_MODEL_UBA, 64, 0x08, "Sieger BK15 Boiler/Nefit Smartline"},
{EMS_MODEL_UBA, 95, 0x08, "Bosch Condens 2500"}
{EMS_MODEL_UBA, 95, 0x08, "Bosch Condens 2500/Junkers Cerapur Comfort"},
{EMS_MODEL_UBA, 122, 0x08, "Nefit Proline"}
};
@@ -173,7 +178,7 @@ const _Thermostat_Type Thermostat_Types[] = {
{EMS_MODEL_BOSCHEASY, 206, 0x02, "Bosch Easy", EMS_THERMOSTAT_READ_YES, EMS_THERMOSTAT_WRITE_NO},
{EMS_MODEL_RC310, 158, 0x10, "RC310", EMS_THERMOSTAT_READ_NO, EMS_THERMOSTAT_WRITE_NO},
{EMS_MODEL_CW100, 255, 0x18, "Bosch CW100", EMS_THERMOSTAT_READ_NO, EMS_THERMOSTAT_WRITE_NO},
{EMS_MODEL_CW100, 255, 0x18, "Bosch CW100", EMS_THERMOSTAT_READ_NO, EMS_THERMOSTAT_WRITE_NO},
{EMS_MODEL_RC1010, 165, 0x18, "RC1010/Nefit Moduline 1010", EMS_THERMOSTAT_READ_NO, EMS_THERMOSTAT_WRITE_NO}
};

View File

@@ -6,5 +6,5 @@
#pragma once
#define APP_NAME "EMS-ESP"
#define APP_VERSION "1.7.0b6"
#define APP_VERSION "1.7.0b8"
#define APP_HOSTNAME "ems-esp"