From ddcee120ed9029c9acd86ad0cc7f59a42531c57a Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 19 Mar 2019 21:34:13 +0100 Subject: [PATCH] added SM10 support --- src/ems-esp.ino | 14 ++++++++ src/ems.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++-- src/ems.h | 24 ++++++++++++++ src/ems_devices.h | 29 +++++++++++------ src/version.h | 2 +- 5 files changed, 138 insertions(+), 13 deletions(-) diff --git a/src/ems-esp.ino b/src/ems-esp.ino index 330fe775e..b663813ed 100644 --- a/src/ems-esp.ino +++ b/src/ems-esp.ino @@ -389,6 +389,19 @@ void showInfo() { myDebug(""); // newline + // For SM10 Solar Module + if (EMS_Other.SM10) { + _renderIntValue("SM10 modulation pump", "%", EMS_Other.SM10modulationSolarPump); + _renderFloatValue("SM10 collector temperature", "C", EMS_Other.SM10collectorTemp); + _renderBoolValue("SM10 pump", EMS_Other.SM10pumpOn); + myDebug(" SM10 uptime: %d days %d hours %d minutes", + EMS_Other.SM10Uptime / 1440, + (EMS_Other.SM10Uptime % 1440) / 60, + EMS_Other.SM10Uptime % 60); + } + + myDebug(""); // newline + // Thermostat stats if (ems_getThermostatEnabled()) { myDebug("%sThermostat stats:%s", COLOR_BOLD_ON, COLOR_BOLD_OFF); @@ -1217,6 +1230,7 @@ void do_regularUpdates() { myDebugLog("Calling scheduled data refresh from EMS devices.."); ems_getThermostatValues(); ems_getBoilerValues(); + ems_getOtherValues(); } } diff --git a/src/ems.cpp b/src/ems.cpp index 1db816e0b..46cc614f1 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -34,6 +34,7 @@ void _process_UBAParameterWW(uint8_t type, uint8_t * data, uint8_t length); void _process_UBATotalUptimeMessage(uint8_t type, uint8_t * data, uint8_t length); void _process_UBAParametersMessage(uint8_t type, uint8_t * data, uint8_t length); void _process_SetPoints(uint8_t type, uint8_t * data, uint8_t length); +void _process_SM10Monitor(uint8_t type, uint8_t * data, uint8_t length); // Common for most thermostats void _process_RCTime(uint8_t type, uint8_t * data, uint8_t length); @@ -77,6 +78,9 @@ const _EMS_Type EMS_Types[] = { {EMS_MODEL_UBA, EMS_TYPE_UBAParametersMessage, "UBAParametersMessage", _process_UBAParametersMessage}, {EMS_MODEL_UBA, EMS_TYPE_UBASetPoints, "UBASetPoints", _process_SetPoints}, + // Other devices + {EMS_MODEL_OTHER, EMS_TYPE_SM10Monitor, "SM10Monitor", _process_SM10Monitor}, + // RC10 {EMS_MODEL_RC10, EMS_TYPE_RCTime, "RCTime", _process_RCTime}, {EMS_MODEL_RC10, EMS_TYPE_RC10Set, "RC10Set", _process_RC10Set}, @@ -115,17 +119,18 @@ const _EMS_Type EMS_Types[] = { {EMS_MODEL_EASY, EMS_TYPE_EasyStatusMessage, "EasyStatusMessage", _process_EasyStatusMessage}, {EMS_MODEL_BOSCHEASY, EMS_TYPE_EasyStatusMessage, "EasyStatusMessage", _process_EasyStatusMessage}, - }; // calculate sizes of arrays at compile uint8_t _EMS_Types_max = ArraySize(EMS_Types); // number of defined types -uint8_t _Boiler_Types_max = ArraySize(Boiler_Types); // number of models +uint8_t _Boiler_Types_max = ArraySize(Boiler_Types); // number of boiler models +uint8_t _Other_Types_max = ArraySize(Other_Types); // number of other ems devices uint8_t _Thermostat_Types_max = ArraySize(Thermostat_Types); // number of defined thermostat types // these structs contain the data we store from the Boiler and Thermostat _EMS_Boiler EMS_Boiler; _EMS_Thermostat EMS_Thermostat; +_EMS_Other EMS_Other; // CRC lookup table with poly 12 for faster checking const uint8_t ems_crc_table[] = {0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20, 0x22, @@ -229,6 +234,12 @@ void ems_init() { EMS_Boiler.pump_mod_max = EMS_VALUE_INT_NOTSET; // Boiler circuit pump modulation max. power EMS_Boiler.pump_mod_min = EMS_VALUE_INT_NOTSET; // Boiler circuit pump modulation min. power + // Other EMS devices values + EMS_Other.SM10collectorTemp = EMS_VALUE_FLOAT_NOTSET; // collector temp from SM10 + EMS_Other.SM10modulationSolarPump = EMS_VALUE_INT_NOTSET; // modulation solar pump + EMS_Other.SM10pumpOn = EMS_VALUE_INT_NOTSET; // SM10 pump on/off + EMS_Other.SM10Uptime = EMS_VALUE_LONG_NOTSET; // SM10 uptime + // calculated values EMS_Boiler.tapwaterActive = EMS_VALUE_INT_NOTSET; // Hot tap water is on/off EMS_Boiler.heatingActive = EMS_VALUE_INT_NOTSET; // Central heating is on/off @@ -242,6 +253,9 @@ void ems_init() { EMS_Thermostat.product_id = 0; strlcpy(EMS_Thermostat.version, "?", sizeof(EMS_Thermostat.version)); + // set other types + EMS_Other.SM10 = false; + // default logging is none ems_setLogging(EMS_SYS_LOGGING_DEFAULT); } @@ -1219,6 +1233,33 @@ void _process_Version(uint8_t type, uint8_t * data, uint8_t length) { // get Thermostat values (if supported) ems_getThermostatValues(); } + return; + } + + // finally look for the other devices + i = 0; + while (i < _Other_Types_max) { + if (Other_Types[i].product_id == product_id) { + typeFound = true; // we have a matching product id. i is the index. + break; + } + i++; + } + + if (typeFound) { + // its a boiler + myDebug("Device found. Model %s with TypeID 0x%02X, Product ID %d, Version %s", + Other_Types[i].model_string, + Other_Types[i].type_id, + product_id, + version); + + // see if this is a Solar Module SM10 // TODO: tidy up + if (Other_Types[i].type_id == EMS_ID_SM10) { + EMS_Other.SM10 = true; // we have detected a SM10 + } + + return; } else { myDebug("Unrecognized device found. TypeID 0x%02X, Product ID %d, Version %s", type, product_id, version); } @@ -1280,6 +1321,18 @@ void _ems_setThermostatModel(uint8_t thermostat_modelid) { EMS_Thermostat.write_supported = thermostat_type->write_supported; } +/* + * SM10Monitor - type 0x97 + */ +void _process_SM10Monitor(uint8_t type, uint8_t * data, uint8_t length) { + // TODO: polish off + EMS_Other.SM10collectorTemp = _toFloat(2, data); // collector temp from SM10 + EMS_Other.SM10modulationSolarPump = data[4]; // modulation solar pump + EMS_Other.SM10pumpOn = bitRead(data[6], 1); // SM10 pump on/off + EMS_Other.SM10Uptime = _toLong(8, data); // SM10 uptime +} + + /** * UBASetPoint 0x1A */ @@ -1409,6 +1462,15 @@ void ems_getBoilerValues() { ems_doReadCommand(EMS_TYPE_UBATotalUptimeMessage, EMS_Boiler.type_id); // get uptime from boiler } +/* + * Get other values from EMS devices + */ +void ems_getOtherValues() { + if (EMS_Other.SM10) { + ems_doReadCommand(EMS_TYPE_SM10Monitor, EMS_ID_SM10); // fetch all from SM10Monitor, e.g. 0B B0 97 00 16 + } +} + /** * returns current thermostat type as a string */ @@ -1491,7 +1553,7 @@ char * ems_getBoilerDescription(char * buffer) { void ems_scanDevices() { myDebug("Started scan of EMS bus for known devices"); - std::list Device_Ids; // new list + std::list Device_Ids; // create a new list // copy over boilers for (_Boiler_Type bt : Boiler_Types) { @@ -1502,6 +1564,12 @@ void ems_scanDevices() { for (_Thermostat_Type tt : Thermostat_Types) { Device_Ids.push_back(tt.type_id); } + + // copy over others + for (_Other_Type ot : Other_Types) { + Device_Ids.push_back(ot.type_id); + } + // remove duplicates and reserved IDs (like our own device) Device_Ids.sort(); Device_Ids.unique(); @@ -1533,6 +1601,14 @@ void ems_printAllTypes() { } } + myDebug("\nThese telegram type IDs are recognized for other EMS devices:"); + + for (i = 0; i < _EMS_Types_max; i++) { + if (EMS_Types[i].model_id == EMS_MODEL_OTHER) { + myDebug(" type %02X (%s)", EMS_Types[i].type, EMS_Types[i].typeString); + } + } + myDebug("\nThese %d thermostats models are supported:", _Thermostat_Types_max); for (i = 0; i < _Thermostat_Types_max; i++) { myDebug(" %s, type ID:0x%02X Product ID:%d Read/Write support:%c%c", diff --git a/src/ems.h b/src/ems.h index 8fb3caa94..581d297f5 100644 --- a/src/ems.h +++ b/src/ems.h @@ -17,6 +17,8 @@ #define EMS_ID_ME 0x0B // Fixed - our device, hardcoded as the "Service Key" #define EMS_ID_DEFAULT_BOILER 0x08 +#define EMS_ID_SM10 0x30 + #define EMS_MIN_TELEGRAM_LENGTH 6 // minimal length for a validation telegram, including CRC // max length of a telegram, including CRC, for Rx and Tx. Data size is 32, so reserving 40 to be safe @@ -145,6 +147,13 @@ typedef struct { char model_string[50]; } _Boiler_Type; +typedef struct { + uint8_t model_id; + uint8_t product_id; + uint8_t type_id; + char model_string[50]; +} _Other_Type; + // Definition for thermostat type typedef struct { uint8_t model_id; @@ -215,6 +224,18 @@ typedef struct { // UBAParameterWW uint8_t product_id; } _EMS_Boiler; +/* + * Telegram package defintions for Other EMS devices + */ +typedef struct { + // SM10 Solar Module - SM10Monitor + bool SM10; // set true if there is a SM10 available + float SM10collectorTemp; // collector temp from SM10 + uint8_t SM10modulationSolarPump; // modulation solar pump + uint8_t SM10pumpOn; // SM10 pump on/off + uint32_t SM10Uptime; // SM10 uptime +} _EMS_Other; + // Thermostat data typedef struct { uint8_t type_id; // the type ID of the thermostat @@ -267,6 +288,7 @@ void ems_setTxDisabled(bool b); void ems_getThermostatValues(); void ems_getBoilerValues(); +void ems_getOtherValues(); bool ems_getPoll(); bool ems_getTxEnabled(); bool ems_getThermostatEnabled(); @@ -300,3 +322,5 @@ void _removeTxQueue(); extern _EMS_Sys_Status EMS_Sys_Status; extern _EMS_Boiler EMS_Boiler; extern _EMS_Thermostat EMS_Thermostat; +extern _EMS_Other EMS_Other; + diff --git a/src/ems_devices.h b/src/ems_devices.h index 9a27f957a..7159071e7 100644 --- a/src/ems_devices.h +++ b/src/ems_devices.h @@ -39,6 +39,9 @@ #define EMS_VALUE_UBAParameterWW_wwComfort_Eco 0xD8 // the value for eco #define EMS_VALUE_UBAParameterWW_wwComfort_Intelligent 0xEC // the value for intelligent +// Other +#define EMS_TYPE_SM10Monitor 0x97 // SM10Monitor + /* * Thermostats... */ @@ -93,7 +96,10 @@ typedef enum { // generic ID for the boiler EMS_MODEL_UBA, - // thermostats + // generic ID for all the other weird devices + EMS_MODEL_OTHER, + + // and finaly the thermostats EMS_MODEL_ES73, EMS_MODEL_RC10, EMS_MODEL_RC20, @@ -117,14 +123,19 @@ const _Boiler_Type Boiler_Types[] = { {EMS_MODEL_UBA, 115, 0x08, "Nefit Topline Compact"}, {EMS_MODEL_UBA, 203, 0x08, "Buderus Logamax U122"}, {EMS_MODEL_UBA, 64, 0x08, "Sieger BK15 Boiler/Nefit Smartline"}, - {EMS_MODEL_UBA, 190, 0x09, "BC10 Base Controller"}, - {EMS_MODEL_UBA, 114, 0x09, "BC10 Base Controller"}, - {EMS_MODEL_UBA, 125, 0x09, "BC25 Base Controller"}, - {EMS_MODEL_UBA, 205, 0x02, "Nefit Moduline Easy Connect"}, - {EMS_MODEL_UBA, 68, 0x09, "RFM20 Receiver"}, - {EMS_MODEL_UBA, 95, 0x08, "Bosch Condens 2500"}, - {EMS_MODEL_UBA, 251, 0x21, "MM10 Mixer Module"}, // warning, fake product id! - {EMS_MODEL_UBA, 250, 0x11, "WM10 Switch Module"}, // warning, fake product id! + {EMS_MODEL_UBA, 95, 0x08, "Bosch Condens 2500"} + +}; + +// Other EMS devices which are not considered boilers or thermostats +const _Other_Type Other_Types[] = {{EMS_MODEL_OTHER, 251, 0x21, "MM10 Mixer Module"}, // warning, fake product id! + {EMS_MODEL_OTHER, 250, 0x11, "WM10 Switch Module"}, // warning, fake product id! + {EMS_MODEL_OTHER, 68, 0x09, "RFM20 Receiver"}, + {EMS_MODEL_OTHER, 190, 0x09, "BC10 Base Controller"}, + {EMS_MODEL_OTHER, 114, 0x09, "BC10 Base Controller"}, + {EMS_MODEL_OTHER, 125, 0x09, "BC25 Base Controller"}, + {EMS_MODEL_OTHER, 205, 0x02, "Nefit Moduline Easy Connect"}, + {EMS_MODEL_OTHER, 73, 0x02, "SM10 Solar Module"} }; diff --git a/src/version.h b/src/version.h index 366b539e4..c1d9828b5 100644 --- a/src/version.h +++ b/src/version.h @@ -6,5 +6,5 @@ #pragma once #define APP_NAME "EMS-ESP" -#define APP_VERSION "1.6.0b3" +#define APP_VERSION "1.6.0b4" #define APP_HOSTNAME "ems-esp"