mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 16:29:51 +03:00
Merge pull request #199 from kstaniek:MM100
MM100 EMS+ Status Message support added
This commit is contained in:
@@ -458,10 +458,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(" %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_getBoilerEnabled() ? "enabled" : "disabled"),
|
||||||
(ems_getThermostatEnabled() ? "enabled" : "disabled"),
|
(ems_getThermostatEnabled() ? "enabled" : "disabled"),
|
||||||
(ems_getSolarModuleEnabled() ? "enabled" : "disabled"),
|
(ems_getSolarModuleEnabled() ? "enabled" : "disabled"),
|
||||||
|
(ems_getMixingDeviceEnabled() ? "enabled" : "disabled"),
|
||||||
((EMSESP_Settings.shower_timer) ? "enabled" : "disabled"),
|
((EMSESP_Settings.shower_timer) ? "enabled" : "disabled"),
|
||||||
((EMSESP_Settings.shower_alert) ? "enabled" : "disabled"));
|
((EMSESP_Settings.shower_alert) ? "enabled" : "disabled"));
|
||||||
|
|
||||||
@@ -530,7 +531,6 @@ void showInfo() {
|
|||||||
_renderIntValue("Selected flow temperature", "C", EMS_Boiler.selFlowTemp);
|
_renderIntValue("Selected flow temperature", "C", EMS_Boiler.selFlowTemp);
|
||||||
_renderUShortValue("Current flow temperature", "C", EMS_Boiler.curFlowTemp);
|
_renderUShortValue("Current flow temperature", "C", EMS_Boiler.curFlowTemp);
|
||||||
_renderUShortValue("Return temperature", "C", EMS_Boiler.retTemp);
|
_renderUShortValue("Return temperature", "C", EMS_Boiler.retTemp);
|
||||||
_renderUShortValue("Switch temperature", "C", EMS_Boiler.switchTemp);
|
|
||||||
_renderBoolValue("Gas", EMS_Boiler.burnGas);
|
_renderBoolValue("Gas", EMS_Boiler.burnGas);
|
||||||
_renderBoolValue("Boiler pump", EMS_Boiler.heatPmp);
|
_renderBoolValue("Boiler pump", EMS_Boiler.heatPmp);
|
||||||
_renderBoolValue("Fan", EMS_Boiler.fanWork);
|
_renderBoolValue("Fan", EMS_Boiler.fanWork);
|
||||||
@@ -675,6 +675,20 @@ 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);
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dallas external temp sensors
|
// Dallas external temp sensors
|
||||||
if (EMSESP_Settings.dallas_sensors != 0) {
|
if (EMSESP_Settings.dallas_sensors != 0) {
|
||||||
myDebug_P(PSTR("")); // newline
|
myDebug_P(PSTR("")); // newline
|
||||||
|
|||||||
61
src/ems.cpp
61
src/ems.cpp
@@ -99,6 +99,9 @@ void _process_RCPLUSStatusMode(_EMS_RxTelegram * EMS_RxTelegram);
|
|||||||
// Junkers FR10 & FW100
|
// Junkers FR10 & FW100
|
||||||
void _process_JunkersStatusMessage(_EMS_RxTelegram * EMS_RxTelegram);
|
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
|
* Recognized EMS types and the functions they call to process the telegrams
|
||||||
* Format: MODEL ID, TYPE ID, Description, function, emsplus
|
* 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},
|
{EMS_MODEL_ALL, EMS_TYPE_RCPLUSStatusMode, "RCPLUSStatusMode", _process_RCPLUSStatusMode},
|
||||||
|
|
||||||
// Junkers FR10
|
// 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 _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 _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 _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
|
// these structs contain the data we store from the specific EMS devices
|
||||||
_EMS_Boiler EMS_Boiler; // for boiler
|
_EMS_Boiler EMS_Boiler; // for boiler
|
||||||
_EMS_Thermostat EMS_Thermostat; // for thermostat
|
_EMS_Thermostat EMS_Thermostat; // for thermostat
|
||||||
_EMS_SolarModule EMS_SolarModule; // for solar modules
|
_EMS_SolarModule EMS_SolarModule; // for solar modules
|
||||||
_EMS_HeatPump EMS_HeatPump; // for heatpumps
|
_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
|
// 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,
|
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_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
|
// UBAParameterWW
|
||||||
EMS_Boiler.wWActivated = EMS_VALUE_INT_NOTSET; // Warm Water activated
|
EMS_Boiler.wWActivated = EMS_VALUE_INT_NOTSET; // Warm Water activated
|
||||||
EMS_Boiler.wWSelTemp = EMS_VALUE_INT_NOTSET; // Warm Water selected temperature
|
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);
|
return (EMS_Thermostat.device_id != EMS_ID_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ems_getMixingDeviceEnabled() {
|
||||||
|
return EMS_Mixing.detected;
|
||||||
|
}
|
||||||
|
|
||||||
bool ems_getSolarModuleEnabled() {
|
bool ems_getSolarModuleEnabled() {
|
||||||
return (EMS_SolarModule.device_id != EMS_ID_NONE);
|
return (EMS_SolarModule.device_id != EMS_ID_NONE);
|
||||||
}
|
}
|
||||||
@@ -1465,6 +1487,20 @@ void _process_EasyStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) {
|
|||||||
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT
|
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) {
|
||||||
|
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
|
* 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
|
* EMS+ messages may come in with different offsets so handle them here
|
||||||
@@ -1888,6 +1924,10 @@ void _addDevice(uint8_t model_type, uint8_t src, uint8_t product_id, char * vers
|
|||||||
strlcat(device_type, "Heat Pump", sizeof(device_type));
|
strlcat(device_type, "Heat Pump", sizeof(device_type));
|
||||||
strlcpy(device.model_string, HeatPump_Devices[i].model_string, sizeof(device.model_string));
|
strlcpy(device.model_string, HeatPump_Devices[i].model_string, sizeof(device.model_string));
|
||||||
break;
|
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:
|
case EMS_MODELTYPE_OTHER:
|
||||||
strlcat(device_type, "Other", sizeof(device_type));
|
strlcat(device_type, "Other", sizeof(device_type));
|
||||||
strlcpy(device.model_string, Other_Devices[i].model_string, sizeof(device.model_string));
|
strlcpy(device.model_string, Other_Devices[i].model_string, sizeof(device.model_string));
|
||||||
@@ -2127,6 +2167,23 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) {
|
|||||||
return;
|
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
|
// finally look for the other EMS devices
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < _Other_Devices_max) {
|
while (i < _Other_Devices_max) {
|
||||||
|
|||||||
27
src/ems.h
27
src/ems.h
@@ -132,6 +132,7 @@
|
|||||||
#define EMS_MODELTYPE_HP 4 // success color
|
#define EMS_MODELTYPE_HP 4 // success color
|
||||||
#define EMS_MODELTYPE_OTHER 5 // no color
|
#define EMS_MODELTYPE_OTHER 5 // no color
|
||||||
#define EMS_MODELTYPE_UNKNOWN 6 // 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
|
#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;
|
bool write_supported;
|
||||||
} _Thermostat_Device;
|
} _Thermostat_Device;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t product_id;
|
||||||
|
uint8_t device_id;
|
||||||
|
char model_string[50];
|
||||||
|
} _Mixing_Device;
|
||||||
|
|
||||||
// for consolidating all types
|
// for consolidating all types
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t model_type; // 1=boiler, 2=thermostat, 3=sm, 4=other, 5=unknown
|
uint8_t model_type; // 1=boiler, 2=thermostat, 3=sm, 4=other, 5=unknown
|
||||||
@@ -282,6 +289,7 @@ typedef struct {
|
|||||||
char model_string[50];
|
char model_string[50];
|
||||||
} _Generic_Device;
|
} _Generic_Device;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Telegram package defintions
|
* Telegram package defintions
|
||||||
*/
|
*/
|
||||||
@@ -365,6 +373,23 @@ typedef struct {
|
|||||||
char version[10];
|
char version[10];
|
||||||
} _EMS_Other;
|
} _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
|
// SM Solar Module - SM10/SM100/ISM1
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t device_id; // the device ID of the Solar Module
|
uint8_t device_id; // the device ID of the Solar Module
|
||||||
@@ -464,6 +489,7 @@ void ems_getSolarModuleValues();
|
|||||||
bool ems_getPoll();
|
bool ems_getPoll();
|
||||||
bool ems_getTxEnabled();
|
bool ems_getTxEnabled();
|
||||||
bool ems_getThermostatEnabled();
|
bool ems_getThermostatEnabled();
|
||||||
|
bool ems_getMixingDeviceEnabled();
|
||||||
bool ems_getBoilerEnabled();
|
bool ems_getBoilerEnabled();
|
||||||
bool ems_getSolarModuleEnabled();
|
bool ems_getSolarModuleEnabled();
|
||||||
bool ems_getHeatPumpEnabled();
|
bool ems_getHeatPumpEnabled();
|
||||||
@@ -492,5 +518,6 @@ extern _EMS_Thermostat EMS_Thermostat;
|
|||||||
extern _EMS_SolarModule EMS_SolarModule;
|
extern _EMS_SolarModule EMS_SolarModule;
|
||||||
extern _EMS_HeatPump EMS_HeatPump;
|
extern _EMS_HeatPump EMS_HeatPump;
|
||||||
extern _EMS_Other EMS_Other;
|
extern _EMS_Other EMS_Other;
|
||||||
|
extern _EMS_Mixing EMS_Mixing;
|
||||||
|
|
||||||
extern std::list<_Generic_Device> Devices;
|
extern std::list<_Generic_Device> Devices;
|
||||||
|
|||||||
@@ -144,6 +144,13 @@
|
|||||||
#define EMS_OFFSET_JunkersStatusMessage_setpoint 2 // setpoint temp
|
#define EMS_OFFSET_JunkersStatusMessage_setpoint 2 // setpoint temp
|
||||||
#define EMS_OFFSET_JunkersStatusMessage_curr 4 // current 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
|
// Known EMS devices
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -175,7 +182,10 @@ typedef enum {
|
|||||||
EMS_MODEL_FR10,
|
EMS_MODEL_FR10,
|
||||||
EMS_MODEL_FR100,
|
EMS_MODEL_FR100,
|
||||||
EMS_MODEL_FR110,
|
EMS_MODEL_FR110,
|
||||||
EMS_MODEL_FW120
|
EMS_MODEL_FW120,
|
||||||
|
|
||||||
|
// mixing devices
|
||||||
|
EMS_MODEL_MM100
|
||||||
|
|
||||||
} _EMS_MODEL_ID;
|
} _EMS_MODEL_ID;
|
||||||
|
|
||||||
@@ -210,6 +220,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
|
// Other EMS devices which are not considered boilers, thermostats or solar modules
|
||||||
// format is PRODUCT ID, DEVICE ID, DESCRIPTION
|
// format is PRODUCT ID, DEVICE ID, DESCRIPTION
|
||||||
const _Other_Device Other_Devices[] = {
|
const _Other_Device Other_Devices[] = {
|
||||||
@@ -217,8 +232,6 @@ const _Other_Device Other_Devices[] = {
|
|||||||
{71, 0x11, "WM10 Switch Module"},
|
{71, 0x11, "WM10 Switch Module"},
|
||||||
|
|
||||||
{69, 0x21, "MM10 Mixer Module"},
|
{69, 0x21, "MM10 Mixer Module"},
|
||||||
{160, 0x20, "MM100 Mixing Module"},
|
|
||||||
{160, 0x21, "MM100 Mixing Module"},
|
|
||||||
{159, 0x21, "MM50 Mixing Module"},
|
{159, 0x21, "MM50 Mixing Module"},
|
||||||
|
|
||||||
{68, 0x09, "BC10/RFM20 Receiver"},
|
{68, 0x09, "BC10/RFM20 Receiver"},
|
||||||
|
|||||||
Reference in New Issue
Block a user