From 94844651b9402198be22e6ff01aa87d6e6e4dfeb Mon Sep 17 00:00:00 2001 From: Klaudiusz Staniek Date: Sun, 6 Oct 2019 19:06:01 +0200 Subject: [PATCH 1/3] MM100 EMS_TYPE_MMPLUSStatusMessage added --- src/ems-esp.cpp | 16 +++++++++++- src/ems.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++-- src/ems.h | 27 +++++++++++++++++++++ src/ems_devices.h | 19 ++++++++++++--- 4 files changed, 118 insertions(+), 6 deletions(-) diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index 277dd9c5..dd1489bc 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -449,10 +449,11 @@ void showInfo() { myDebug_P(PSTR(" %d external temperature sensor%s found"), EMSESP_Settings.dallas_sensors, (EMSESP_Settings.dallas_sensors == 1) ? "" : "s"); } - myDebug_P(PSTR(" Boiler is %s, Thermostat is %s, Solar Module is %s, Shower Timer is %s, Shower Alert is %s"), + myDebug_P(PSTR(" Boiler is %s, Thermostat is %s, Solar Module is %s, Mixing Module is %s, Shower Timer is %s, Shower Alert is %s"), (ems_getBoilerEnabled() ? "enabled" : "disabled"), (ems_getThermostatEnabled() ? "enabled" : "disabled"), (ems_getSolarModuleEnabled() ? "enabled" : "disabled"), + (ems_getMixingDeviceEnabled() ? "enabled" : "disabled"), ((EMSESP_Settings.shower_timer) ? "enabled" : "disabled"), ((EMSESP_Settings.shower_alert) ? "enabled" : "disabled")); @@ -666,6 +667,19 @@ void showInfo() { } } + // Mixing modules sensors + if (ems_getMixingDeviceEnabled()) { + myDebug_P(PSTR("")); // newline + myDebug_P(PSTR("%sMixing module stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF); + + for (uint8_t hc_num = 1; hc_num <= EMS_THERMOSTAT_MAXHC; hc_num++) { + if (EMS_Mixing.hc[hc_num - 1].active) { + myDebug_P(PSTR(" Mixing Circuit %d"), hc_num); + _renderShortValue(" Current flow temperature", "C", EMS_Mixing.hc[hc_num - 1].flowTemp); + } + } + } + // Dallas external temp sensors if (EMSESP_Settings.dallas_sensors != 0) { myDebug_P(PSTR("")); // newline diff --git a/src/ems.cpp b/src/ems.cpp index bb2451f3..51a1096d 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -99,6 +99,9 @@ void _process_RCPLUSStatusMode(_EMS_RxTelegram * EMS_RxTelegram); // Junkers FR10 & FW100 void _process_JunkersStatusMessage(_EMS_RxTelegram * EMS_RxTelegram); +// Mixers MM100 +void _process_MMPLUSStatusMessage(_EMS_RxTelegram * EMS_RxTelegram); + /** * Recognized EMS types and the functions they call to process the telegrams * Format: MODEL ID, TYPE ID, Description, function, emsplus @@ -184,8 +187,11 @@ const _EMS_Type EMS_Types[] = { {EMS_MODEL_ALL, EMS_TYPE_RCPLUSStatusMode, "RCPLUSStatusMode", _process_RCPLUSStatusMode}, // Junkers FR10 - {EMS_MODEL_ALL, EMS_TYPE_JunkersStatusMessage, "JunkersStatusMessage", _process_JunkersStatusMessage} + {EMS_MODEL_ALL, EMS_TYPE_JunkersStatusMessage, "JunkersStatusMessage", _process_JunkersStatusMessage}, + // Mixing devices + {EMS_MODEL_MM100, EMS_TYPE_MMPLUSStatusMessage_HC1, "MMPLUSStatusMessage_HC1", _process_MMPLUSStatusMessage}, + {EMS_MODEL_MM100, EMS_TYPE_MMPLUSStatusMessage_HC2, "MMPLUSStatusMessage_HC2", _process_MMPLUSStatusMessage}, }; @@ -196,13 +202,15 @@ uint8_t _SolarModule_Devices_max = ArraySize(SolarModule_Devices); // number of uint8_t _Other_Devices_max = ArraySize(Other_Devices); // number of other ems devices uint8_t _Thermostat_Devices_max = ArraySize(Thermostat_Devices); // number of defined thermostat types uint8_t _HeatPump_Devices_max = ArraySize(HeatPump_Devices); // number of defined heatpump types +uint8_t _Mixing_Devices_max = ArraySize(Mixing_Devices); // number of mixing device types // these structs contain the data we store from the specific EMS devices _EMS_Boiler EMS_Boiler; // for boiler _EMS_Thermostat EMS_Thermostat; // for thermostat _EMS_SolarModule EMS_SolarModule; // for solar modules _EMS_HeatPump EMS_HeatPump; // for heatpumps -_EMS_Other EMS_Other; // for other known EMS devices +_EMS_Mixing EMS_Mixing; // for mixing devices +_EMS_Other EMS_Other; // for other known EMS devices // 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, 0x24, 0x26, @@ -267,6 +275,16 @@ void ems_init() { EMS_Thermostat.hc[i].curr_roomTemp = EMS_VALUE_SHORT_NOTSET; } + EMS_Mixing.detected = false; + // init all mixing modules + for (uint8_t i = 0; i < EMS_THERMOSTAT_MAXHC; i++) { + EMS_Mixing.hc[i].hc = i + 1; + EMS_Mixing.hc[i].flowTemp = EMS_VALUE_SHORT_NOTSET; + EMS_Mixing.hc[i].device_id = EMS_ID_NONE; + EMS_Mixing.hc[i].model_id = EMS_MODEL_NONE; + EMS_Mixing.hc[i].product_id = EMS_ID_NONE; + } + // UBAParameterWW EMS_Boiler.wWActivated = EMS_VALUE_INT_NOTSET; // Warm Water activated EMS_Boiler.wWSelTemp = EMS_VALUE_INT_NOTSET; // Warm Water selected temperature @@ -378,6 +396,10 @@ bool ems_getThermostatEnabled() { return (EMS_Thermostat.device_id != EMS_ID_NONE); } +bool ems_getMixingDeviceEnabled() { + return EMS_Mixing.detected; +} + bool ems_getSolarModuleEnabled() { return (EMS_SolarModule.device_id != EMS_ID_NONE); } @@ -1465,6 +1487,21 @@ void _process_EasyStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) { EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT } +void _process_MMPLUSStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) { + uint8_t hc = (EMS_RxTelegram->type - EMS_TYPE_MMPLUSStatusMessage_HC1); // 0 to 3 + if (hc > 4) { + return; // invalid type + } + EMS_Mixing.hc[hc].active = true; + + if (EMS_RxTelegram->data_length == 1) { + + } else if (EMS_RxTelegram->data_length > 8) { + uint8_t hc_temp = _toShort(3); + EMS_Mixing.hc[hc].flowTemp = _toShort(EMS_OFFSET_MMPLUSStatusMessage_flow_temp); + } +} + /** * type 0x01A5 - data from the Nefit RC1010/3000 thermostat (0x18) and RC300/310s on 0x10 * EMS+ messages may come in with different offsets so handle them here @@ -1885,6 +1922,10 @@ void _addDevice(uint8_t model_type, uint8_t src, uint8_t product_id, char * vers strlcat(device_type, "Heat Pump", sizeof(device_type)); strlcpy(device.model_string, HeatPump_Devices[i].model_string, sizeof(device.model_string)); break; + case EMS_MODELTYPE_MIXING: + strlcat(device_type, "Mixing Device", sizeof(device_type)); + strlcpy(device.model_string, Mixing_Devices[i].model_string, sizeof(device.model_string)); + break; case EMS_MODELTYPE_OTHER: strlcat(device_type, "Other", sizeof(device_type)); strlcpy(device.model_string, Other_Devices[i].model_string, sizeof(device.model_string)); @@ -2124,6 +2165,23 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { return; } + // look for mixing devices + i = 0; + while (i < _Mixing_Devices_max) { + if (Mixing_Devices[i].product_id == product_id) { + typeFound = true; + break; + } + i++; + } + + if (typeFound) { + _addDevice(EMS_MODELTYPE_MIXING, EMS_RxTelegram->src, product_id, version, i); + ems_doReadCommand(EMS_TYPE_MMPLUSStatusMessage_HC1, EMS_RxTelegram->src); + EMS_Mixing.detected = true; + return; + } + // finally look for the other EMS devices i = 0; while (i < _Other_Devices_max) { diff --git a/src/ems.h b/src/ems.h index 057919ee..ae9d6bdf 100644 --- a/src/ems.h +++ b/src/ems.h @@ -132,6 +132,7 @@ #define EMS_MODELTYPE_HP 4 // success color #define EMS_MODELTYPE_OTHER 5 // no color #define EMS_MODELTYPE_UNKNOWN 6 // no color +#define EMS_MODELTYPE_MIXING 7 #define EMS_MODELTYPE_UNKNOWN_STRING "unknown?" // model type text to use when discovering an unknown device @@ -273,6 +274,12 @@ typedef struct { bool write_supported; } _Thermostat_Device; +typedef struct { + uint8_t product_id; + uint8_t device_id; + char model_string[50]; +} _Mixing_Device; + // for consolidating all types typedef struct { uint8_t model_type; // 1=boiler, 2=thermostat, 3=sm, 4=other, 5=unknown @@ -282,6 +289,7 @@ typedef struct { char model_string[50]; } _Generic_Device; + /* * Telegram package defintions */ @@ -365,6 +373,23 @@ typedef struct { char version[10]; } _EMS_Other; +typedef struct { + uint8_t device_id; + uint8_t model_id; + uint8_t product_id; + char version[10]; + uint8_t hc; // heating circuit 1,2, 3 or 4 + bool active; // true if there is data for this HC + + uint8_t flowTemp; +} _EMS_Mixing_HC; + +// Mixer data +typedef struct { + bool detected; + _EMS_Mixing_HC hc[EMS_THERMOSTAT_MAXHC]; // array for the 4 heating circuits +} _EMS_Mixing; + // SM Solar Module - SM10/SM100/ISM1 typedef struct { uint8_t device_id; // the device ID of the Solar Module @@ -464,6 +489,7 @@ void ems_getSolarModuleValues(); bool ems_getPoll(); bool ems_getTxEnabled(); bool ems_getThermostatEnabled(); +bool ems_getMixingDeviceEnabled(); bool ems_getBoilerEnabled(); bool ems_getSolarModuleEnabled(); bool ems_getHeatPumpEnabled(); @@ -492,5 +518,6 @@ extern _EMS_Thermostat EMS_Thermostat; extern _EMS_SolarModule EMS_SolarModule; extern _EMS_HeatPump EMS_HeatPump; extern _EMS_Other EMS_Other; +extern _EMS_Mixing EMS_Mixing; extern std::list<_Generic_Device> Devices; diff --git a/src/ems_devices.h b/src/ems_devices.h index dc5ad4ae..84c8e1a6 100644 --- a/src/ems_devices.h +++ b/src/ems_devices.h @@ -143,6 +143,13 @@ #define EMS_OFFSET_JunkersStatusMessage_setpoint 2 // setpoint temp #define EMS_OFFSET_JunkersStatusMessage_curr 4 // current temp +// MM100 (EMS Plus) +#define EMS_TYPE_MMPLUSStatusMessage_HC1 0x01D7 // mixer status HC1 +#define EMS_TYPE_MMPLUSStatusMessage_HC2 0x01D8 // mixer status HC2 +#define EMS_TYPE_MMPLUSStatusMessage_HC3 0x01D9 // mixer status HC3 +#define EMS_TYPE_MMPLUSStatusMessage_HC4 0x01DA // mixer status HC4 +#define EMS_OFFSET_MMPLUSStatusMessage_flow_temp 3 // flow temperature + // Known EMS devices typedef enum { @@ -174,7 +181,10 @@ typedef enum { EMS_MODEL_FR10, EMS_MODEL_FR100, EMS_MODEL_FR110, - EMS_MODEL_FW120 + EMS_MODEL_FW120, + + // mixing devices + EMS_MODEL_MM100 } _EMS_MODEL_ID; @@ -209,6 +219,11 @@ const _SolarModule_Device SolarModule_Devices[] = { }; +const _Mixing_Device Mixing_Devices[] = { + {160, 0x20, "MM100 Mixing Module"}, + {160, 0x21, "MM100 Mixing Module"}, +}; + // Other EMS devices which are not considered boilers, thermostats or solar modules // format is PRODUCT ID, DEVICE ID, DESCRIPTION const _Other_Device Other_Devices[] = { @@ -216,8 +231,6 @@ const _Other_Device Other_Devices[] = { {71, 0x11, "WM10 Switch Module"}, {69, 0x21, "MM10 Mixer Module"}, - {160, 0x20, "MM100 Mixing Module"}, - {160, 0x21, "MM100 Mixing Module"}, {159, 0x21, "MM50 Mixing Module"}, {68, 0x09, "BC10/RFM20 Receiver"}, From a57b39a9183695fde92a9124c3fcf47d5a4aa465 Mon Sep 17 00:00:00 2001 From: Klaudiusz Staniek Date: Sun, 6 Oct 2019 19:21:03 +0200 Subject: [PATCH 2/3] Removed some leftovers --- src/ems.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ems.cpp b/src/ems.cpp index 51a1096d..2c3f8d2b 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -1497,7 +1497,6 @@ void _process_MMPLUSStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) { if (EMS_RxTelegram->data_length == 1) { } else if (EMS_RxTelegram->data_length > 8) { - uint8_t hc_temp = _toShort(3); EMS_Mixing.hc[hc].flowTemp = _toShort(EMS_OFFSET_MMPLUSStatusMessage_flow_temp); } } From bc0ff3b0014af32c322251b2dc60e97f0563d7e2 Mon Sep 17 00:00:00 2001 From: Klaudiusz Staniek Date: Sun, 6 Oct 2019 19:30:36 +0200 Subject: [PATCH 3/3] Info output updated --- src/ems-esp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index dd1489bc..ea2493d7 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -522,7 +522,6 @@ void showInfo() { _renderIntValue("Selected flow temperature", "C", EMS_Boiler.selFlowTemp); _renderUShortValue("Current flow temperature", "C", EMS_Boiler.curFlowTemp); _renderUShortValue("Return temperature", "C", EMS_Boiler.retTemp); - _renderUShortValue("Switch temperature", "C", EMS_Boiler.switchTemp); _renderBoolValue("Gas", EMS_Boiler.burnGas); _renderBoolValue("Boiler pump", EMS_Boiler.heatPmp); _renderBoolValue("Fan", EMS_Boiler.fanWork); @@ -671,11 +670,12 @@ void showInfo() { if (ems_getMixingDeviceEnabled()) { myDebug_P(PSTR("")); // newline myDebug_P(PSTR("%sMixing module stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF); + _renderUShortValue("Switch temperature", "C", EMS_Boiler.switchTemp); for (uint8_t hc_num = 1; hc_num <= EMS_THERMOSTAT_MAXHC; hc_num++) { if (EMS_Mixing.hc[hc_num - 1].active) { - myDebug_P(PSTR(" Mixing Circuit %d"), hc_num); - _renderShortValue(" Current flow temperature", "C", EMS_Mixing.hc[hc_num - 1].flowTemp); + myDebug_P(PSTR(" Mixing Circuit %d"), hc_num); + _renderShortValue(" Current flow temperature", "C", EMS_Mixing.hc[hc_num - 1].flowTemp); } } }