diff --git a/src/ems.cpp b/src/ems.cpp index 3b1422e4b..0d4d6c486 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -9,7 +9,6 @@ #include "ems.h" #include "ems_devices.h" #include "emsuart.h" -#include #include // https://github.com/rlogiacco/CircularBuffer #include #include // std::list @@ -28,7 +27,7 @@ _EMS_Sys_Status EMS_Sys_Status; // EMS Status CircularBuffer<_EMS_TxTelegram, EMS_TX_TELEGRAM_QUEUE_MAX> EMS_TxQueue; // FIFO queue for Tx send buffer // for storing all detected EMS devices -std::list<_Generic_Type> Devices; +std::list<_Generic_Device> Devices; // macros used in the _process* functions #define _toByte(i) (EMS_RxTelegram->data[i]) @@ -95,8 +94,6 @@ void _process_EasyStatusMessage(_EMS_RxTelegram * EMS_RxTelegram); // RC1010, RC300, RC310 void _process_RCPLUSStatusMessage(_EMS_RxTelegram * EMS_RxTelegram); void _process_RCPLUSSetMessage(_EMS_RxTelegram * EMS_RxTelegram); -void _process_RCPLUSStatusHeating(_EMS_RxTelegram * EMS_RxTelegram); -void _process_RCPLUSStatusHeating(_EMS_RxTelegram * EMS_RxTelegram); void _process_RCPLUSStatusMode(_EMS_RxTelegram * EMS_RxTelegram); // Junkers FR10 & FW100 @@ -176,7 +173,6 @@ const _EMS_Type EMS_Types[] = { // Nefit 1010, RC300, RC310 (EMS Plus) {EMS_MODEL_ALL, EMS_TYPE_RCPLUSStatusMessage, "RCPLUSStatusMessage", _process_RCPLUSStatusMessage}, {EMS_MODEL_ALL, EMS_TYPE_RCPLUSSet, "RCPLUSSetMessage", _process_RCPLUSSetMessage}, - {EMS_MODEL_ALL, EMS_TYPE_RCPLUSStatusHeating, "RCPLUSStatusHeating", _process_RCPLUSStatusHeating}, {EMS_MODEL_ALL, EMS_TYPE_RCPLUSStatusMode, "RCPLUSStatusMode", _process_RCPLUSStatusMode}, // Junkers FR10 @@ -186,12 +182,12 @@ const _EMS_Type EMS_Types[] = { }; // 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 boiler models -uint8_t _Solar_Module_Types_max = ArraySize(SolarModule_Types); // number of solar module types -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 -uint8_t _HeatPump_Types_max = ArraySize(HeatPump_Types); // number of defined heatpuimp types +uint8_t _EMS_Types_max = ArraySize(EMS_Types); // number of defined types +uint8_t _Boiler_Devices_max = ArraySize(Boiler_Devices); // number of boiler models +uint8_t _SolarModule_Types_max = ArraySize(SolarModule_Devices); // number of solar module types +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 heatpuimp types // these structs contain the data we store from the specific EMS devices _EMS_Boiler EMS_Boiler; // for boiler @@ -1396,7 +1392,7 @@ void _process_EasyStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) { } /** - * type 0x01A5 - data from the Nefit RC1010 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 */ void _process_RCPLUSStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) { @@ -1432,14 +1428,6 @@ void _process_RCPLUSStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) { } } -/** - * type 0x01B9 - heating data from the Nefit RC1010 thermostat (0x18) and RC300/310s on 0x10 - */ -void _process_RCPLUSStatusHeating(_EMS_RxTelegram * EMS_RxTelegram) { - // see wiki - // operation mode, comfort levels 1,2,3, eco level -} - /** * type 0x01AF - summer/winter mode from the Nefit RC1010 thermostat (0x18) and RC300/310s on 0x10 */ @@ -1460,10 +1448,14 @@ void _process_JunkersStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) { } /** - * to complete.... + * type 0x01B9 EMS+ for reading the mode from RC300/RC310 thermostat */ void _process_RCPLUSSetMessage(_EMS_RxTelegram * EMS_RxTelegram) { - // to complete + EMS_Thermostat.mode = _toByte(EMS_OFFSET_RCPLUSSet_mode); + EMS_Thermostat.daytemp = _toByte(EMS_OFFSET_RCPLUSSet_temp_comfort2); // is * 2 + EMS_Thermostat.nighttemp = _toByte(EMS_OFFSET_RCPLUSSet_temp_eco); // is * 2 + + EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT } /** @@ -1690,10 +1682,10 @@ void ems_clearDeviceList() { * add an EMS device to our list of detected devices */ void _addDevice(uint8_t product_id, uint8_t device_id, char * version, const char * model_string) { - _Generic_Type device; + _Generic_Device device; // if its a duplicate don't add bool found = false; - for (std::list<_Generic_Type>::iterator it = Devices.begin(); it != Devices.end(); it++) { + for (std::list<_Generic_Device>::iterator it = Devices.begin(); it != Devices.end(); it++) { if (((it)->product_id == product_id) && ((it)->device_id == device_id)) { found = true; } @@ -1725,8 +1717,8 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { // see if its a known boiler int i = 0; bool typeFound = false; - while (i < _Boiler_Types_max) { - if ((Boiler_Types[i].product_id == product_id) && ((EMS_RxTelegram->src & 0x7F) == EMS_ID_BOILER)) { + while (i < _Boiler_Devices_max) { + if ((Boiler_Devices[i].product_id == product_id) && ((EMS_RxTelegram->src & 0x7F) == EMS_ID_BOILER)) { typeFound = true; // we have a matching product id. i is the index. break; } @@ -1735,22 +1727,22 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { if (typeFound) { // its a boiler - myDebug_P(PSTR("Boiler found: %s (DeviceID:0x%02X ProductID:%d Version:%s)"), Boiler_Types[i].model_string, EMS_ID_BOILER, product_id, version); + myDebug_P(PSTR("Boiler found: %s (DeviceID:0x%02X ProductID:%d Version:%s)"), Boiler_Devices[i].model_string, EMS_ID_BOILER, product_id, version); // add to list - _addDevice(product_id, EMS_ID_BOILER, version, Boiler_Types[i].model_string); + _addDevice(product_id, EMS_ID_BOILER, version, Boiler_Devices[i].model_string); // if its a boiler set it, unless it already has been set by checking for a productID // it will take the first one found in the list if ((EMS_Boiler.device_id == EMS_ID_NONE) || ((EMS_Boiler.device_id == EMS_ID_BOILER) && EMS_Boiler.product_id == EMS_ID_NONE)) { myDebug_P(PSTR("* Setting Boiler to model %s (DeviceID:0x%02X ProductID:%d Version:%s)"), - Boiler_Types[i].model_string, + Boiler_Devices[i].model_string, EMS_ID_BOILER, product_id, version); EMS_Boiler.device_id = EMS_ID_BOILER; - EMS_Boiler.product_id = Boiler_Types[i].product_id; + EMS_Boiler.product_id = Boiler_Devices[i].product_id; strlcpy(EMS_Boiler.version, version, sizeof(EMS_Boiler.version)); // check to see if its a Junkers Heatronic3, which has a different poll'ing logic @@ -1768,8 +1760,8 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { // its not a boiler, maybe its a known thermostat? i = 0; - while (i < _Thermostat_Types_max) { - if (Thermostat_Types[i].product_id == product_id) { + while (i < _Thermostat_Devices_max) { + if (Thermostat_Devices[i].product_id == product_id) { typeFound = true; // we have a matching product id. i is the index. break; } @@ -1780,28 +1772,28 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { // its a known thermostat if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { myDebug_P(PSTR("Thermostat found: %s (DeviceID:0x%02X ProductID:%d Version:%s)"), - Thermostat_Types[i].model_string, - Thermostat_Types[i].device_id, + Thermostat_Devices[i].model_string, + Thermostat_Devices[i].device_id, product_id, version); } // add to list - _addDevice(product_id, Thermostat_Types[i].device_id, version, Thermostat_Types[i].model_string); + _addDevice(product_id, Thermostat_Devices[i].device_id, version, Thermostat_Devices[i].model_string); // if we don't have a thermostat set, use this one if (((EMS_Thermostat.device_id == EMS_ID_NONE) || (EMS_Thermostat.model_id == EMS_MODEL_NONE) - || (EMS_Thermostat.device_id == Thermostat_Types[i].device_id)) + || (EMS_Thermostat.device_id == Thermostat_Devices[i].device_id)) && EMS_Thermostat.product_id == EMS_ID_NONE) { myDebug_P(PSTR("* Setting Thermostat to %s (DeviceID:0x%02X ProductID:%d Version:%s)"), - Thermostat_Types[i].model_string, - Thermostat_Types[i].device_id, + Thermostat_Devices[i].model_string, + Thermostat_Devices[i].device_id, product_id, version); - EMS_Thermostat.model_id = Thermostat_Types[i].model_id; - EMS_Thermostat.device_id = Thermostat_Types[i].device_id; - EMS_Thermostat.write_supported = Thermostat_Types[i].write_supported; + EMS_Thermostat.model_id = Thermostat_Devices[i].model_id; + EMS_Thermostat.device_id = Thermostat_Devices[i].device_id; + EMS_Thermostat.write_supported = Thermostat_Devices[i].write_supported; EMS_Thermostat.product_id = product_id; strlcpy(EMS_Thermostat.version, version, sizeof(EMS_Thermostat.version)); @@ -1816,8 +1808,8 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { // look for Solar Modules i = 0; - while (i < _Solar_Module_Types_max) { - if (SolarModule_Types[i].product_id == product_id) { + while (i < _SolarModule_Types_max) { + if (SolarModule_Devices[i].product_id == product_id) { typeFound = true; // we have a matching product id. i is the index. break; } @@ -1826,16 +1818,16 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { if (typeFound) { myDebug_P(PSTR("Solar Module found: %s (DeviceID:0x%02X ProductID:%d Version:%s)"), - SolarModule_Types[i].model_string, - SolarModule_Types[i].device_id, + SolarModule_Devices[i].model_string, + SolarModule_Devices[i].device_id, product_id, version); // add to list - _addDevice(product_id, SolarModule_Types[i].device_id, version, SolarModule_Types[i].model_string); + _addDevice(product_id, SolarModule_Devices[i].device_id, version, SolarModule_Devices[i].model_string); myDebug_P(PSTR("Solar Module support enabled.")); - EMS_SolarModule.device_id = SolarModule_Types[i].device_id; + EMS_SolarModule.device_id = SolarModule_Devices[i].device_id; EMS_SolarModule.product_id = product_id; strlcpy(EMS_SolarModule.version, version, sizeof(EMS_SolarModule.version)); @@ -1846,8 +1838,8 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { // look for heatpumps i = 0; - while (i < _HeatPump_Types_max) { - if (HeatPump_Types[i].product_id == product_id) { + while (i < _HeatPump_Devices_max) { + if (HeatPump_Devices[i].product_id == product_id) { typeFound = true; // we have a matching product id. i is the index. break; } @@ -1856,16 +1848,16 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { if (typeFound) { myDebug_P(PSTR("Heat Pump found: %s (DeviceID:0x%02X ProductID:%d Version:%s)"), - HeatPump_Types[i].model_string, - HeatPump_Types[i].device_id, + HeatPump_Devices[i].model_string, + HeatPump_Devices[i].device_id, product_id, version); // add to list - _addDevice(product_id, HeatPump_Types[i].device_id, version, HeatPump_Types[i].model_string); + _addDevice(product_id, HeatPump_Devices[i].device_id, version, HeatPump_Devices[i].model_string); myDebug_P(PSTR("Heat Pump support enabled.")); - EMS_HeatPump.device_id = SolarModule_Types[i].device_id; + EMS_HeatPump.device_id = SolarModule_Devices[i].device_id; EMS_HeatPump.product_id = product_id; strlcpy(EMS_HeatPump.version, version, sizeof(EMS_HeatPump.version)); return; @@ -1873,8 +1865,8 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { // finally look for the other EMS devices i = 0; - while (i < _Other_Types_max) { - if (Other_Types[i].product_id == product_id) { + while (i < _Other_Devices_max) { + if (Other_Devices[i].product_id == product_id) { typeFound = true; // we have a matching product id. i is the index. break; } @@ -1882,10 +1874,10 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) { } if (typeFound) { - myDebug_P(PSTR("Device found: %s (DeviceID:0x%02X ProductID:%d Version:%s)"), Other_Types[i].model_string, Other_Types[i].device_id, product_id, version); + myDebug_P(PSTR("Device found: %s (DeviceID:0x%02X ProductID:%d Version:%s)"), Other_Devices[i].model_string, Other_Devices[i].device_id, product_id, version); // add to list - _addDevice(product_id, Other_Types[i].device_id, version, Other_Types[i].model_string); + _addDevice(product_id, Other_Devices[i].device_id, version, Other_Devices[i].model_string); return; } else { myDebug_P(PSTR("Unrecognized device found: %s (DeviceID:0x%02X ProductID:%d Version:%s)"), EMS_RxTelegram->src, product_id, version); @@ -1995,39 +1987,39 @@ void ems_getThermostatValues() { return; } - uint8_t model_id = EMS_Thermostat.model_id; - uint8_t type = EMS_Thermostat.device_id; - uint8_t hc = EMS_Thermostat.hc; + uint8_t model_id = EMS_Thermostat.model_id; + uint8_t device_id = EMS_Thermostat.device_id; + uint8_t hc = EMS_Thermostat.hc; switch (model_id) { case EMS_MODEL_RC20: - ems_doReadCommand(EMS_TYPE_RC20StatusMessage, type); // to get the temps - ems_doReadCommand(EMS_TYPE_RC20Set, type); // to get the mode + ems_doReadCommand(EMS_TYPE_RC20StatusMessage, device_id); // to get the temps + ems_doReadCommand(EMS_TYPE_RC20Set, device_id); // to get the mode break; case EMS_MODEL_RC30: - ems_doReadCommand(EMS_TYPE_RC30StatusMessage, type); // to get the temps - ems_doReadCommand(EMS_TYPE_RC30Set, type); // to get the mode + ems_doReadCommand(EMS_TYPE_RC30StatusMessage, device_id); // to get the temps + ems_doReadCommand(EMS_TYPE_RC30Set, device_id); // to get the mode break; case EMS_MODEL_EASY: - ems_doReadCommand(EMS_TYPE_EasyStatusMessage, type); + ems_doReadCommand(EMS_TYPE_EasyStatusMessage, device_id); break; case EMS_MODEL_RC35: case EMS_MODEL_ES73: if (hc == 1) { - ems_doReadCommand(EMS_TYPE_RC35StatusMessage_HC1, type); // to get the temps - ems_doReadCommand(EMS_TYPE_RC35Set_HC1, type); // to get the mode + ems_doReadCommand(EMS_TYPE_RC35StatusMessage_HC1, device_id); // to get the temps + ems_doReadCommand(EMS_TYPE_RC35Set_HC1, device_id); // to get the mode } else if (hc == 2) { - ems_doReadCommand(EMS_TYPE_RC35StatusMessage_HC2, type); // to get the temps - ems_doReadCommand(EMS_TYPE_RC35Set_HC2, type); // to get the mode + ems_doReadCommand(EMS_TYPE_RC35StatusMessage_HC2, device_id); // to get the temps + ems_doReadCommand(EMS_TYPE_RC35Set_HC2, device_id); // to get the mode } break; case EMS_MODEL_RC300: - ems_doReadCommand(EMS_TYPE_RCPLUSStatusMessage, type); + ems_doReadCommand(EMS_TYPE_RCPLUSStatusMessage, device_id); default: break; } - ems_doReadCommand(EMS_TYPE_RCTime, type); // get Thermostat time + ems_doReadCommand(EMS_TYPE_RCTime, device_id); // get Thermostat time } /** @@ -2070,8 +2062,8 @@ char * ems_getThermostatDescription(char * buffer) { char tmp[6] = {0}; // scan through known ID types - while (i < _Thermostat_Types_max) { - if (Thermostat_Types[i].product_id == EMS_Thermostat.product_id) { + while (i < _Thermostat_Devices_max) { + if (Thermostat_Devices[i].product_id == EMS_Thermostat.product_id) { found = true; // we have a match break; } @@ -2079,7 +2071,7 @@ char * ems_getThermostatDescription(char * buffer) { } if (found) { - strlcpy(buffer, Thermostat_Types[i].model_string, size); + strlcpy(buffer, Thermostat_Devices[i].model_string, size); } else { strlcpy(buffer, "DeviceID: 0x", size); strlcat(buffer, _hextoa(EMS_Thermostat.device_id, tmp), size); @@ -2112,15 +2104,15 @@ char * ems_getBoilerDescription(char * buffer) { char tmp[6] = {0}; // scan through known ID types - while (i < _Boiler_Types_max) { - if (Boiler_Types[i].product_id == EMS_Boiler.product_id) { + while (i < _Boiler_Devices_max) { + if (Boiler_Devices[i].product_id == EMS_Boiler.product_id) { found = true; // we have a match break; } i++; } if (found) { - strlcpy(buffer, Boiler_Types[i].model_string, size); + strlcpy(buffer, Boiler_Devices[i].model_string, size); } else { strlcpy(buffer, "DeviceID: 0x", size); strlcat(buffer, _hextoa(EMS_Boiler.device_id, tmp), size); @@ -2153,15 +2145,15 @@ char * ems_getSolarModuleDescription(char * buffer) { char tmp[6] = {0}; // scan through known ID types - while (i < _Solar_Module_Types_max) { - if (SolarModule_Types[i].product_id == EMS_SolarModule.product_id) { + while (i < _SolarModule_Types_max) { + if (SolarModule_Devices[i].product_id == EMS_SolarModule.product_id) { found = true; // we have a match break; } i++; } if (found) { - strlcpy(buffer, SolarModule_Types[i].model_string, size); + strlcpy(buffer, SolarModule_Devices[i].model_string, size); } else { strlcpy(buffer, "DeviceID: 0x", size); strlcat(buffer, _hextoa(EMS_SolarModule.device_id, tmp), size); @@ -2194,15 +2186,15 @@ char * ems_getHeatPumpDescription(char * buffer) { char tmp[6] = {0}; // scan through known ID types - while (i < _HeatPump_Types_max) { - if (HeatPump_Types[i].product_id == EMS_HeatPump.product_id) { + while (i < _HeatPump_Devices_max) { + if (HeatPump_Devices[i].product_id == EMS_HeatPump.product_id) { found = true; // we have a match break; } i++; } if (found) { - strlcpy(buffer, HeatPump_Types[i].model_string, size); + strlcpy(buffer, HeatPump_Devices[i].model_string, size); } else { strlcpy(buffer, "DeviceID: 0x", size); strlcat(buffer, _hextoa(EMS_HeatPump.device_id, tmp), size); @@ -2234,17 +2226,17 @@ void ems_scanDevices() { Device_Ids.push_back(EMS_ID_BOILER); // copy over thermostats - for (_Thermostat_Type tt : Thermostat_Types) { + for (_Thermostat_Device tt : Thermostat_Devices) { Device_Ids.push_back(tt.device_id); } // copy over solar modules - for (_SolarModule_Type sm : SolarModule_Types) { + for (_SolarModule_Device sm : SolarModule_Devices) { Device_Ids.push_back(sm.device_id); } // copy over others - for (_Other_Type ot : Other_Types) { + for (_Other_Device ot : Other_Devices) { Device_Ids.push_back(ot.device_id); } @@ -2268,34 +2260,34 @@ void ems_scanDevices() { void ems_printAllDevices() { uint8_t i; - myDebug_P(PSTR("\nThese %d devices are supported as boiler units:"), _Boiler_Types_max); - for (i = 0; i < _Boiler_Types_max; i++) { + myDebug_P(PSTR("\nThese %d devices are supported as boiler units:"), _Boiler_Devices_max); + for (i = 0; i < _Boiler_Devices_max; i++) { myDebug_P(PSTR(" %s%s%s (DeviceID:0x%02X ProductID:%d)"), COLOR_BOLD_ON, - Boiler_Types[i].model_string, + Boiler_Devices[i].model_string, COLOR_BOLD_OFF, EMS_ID_BOILER, - Boiler_Types[i].product_id); + Boiler_Devices[i].product_id); } - myDebug_P(PSTR("\nThese %d devices are supported as solar module devices:"), _Solar_Module_Types_max); - for (i = 0; i < _Solar_Module_Types_max; i++) { + myDebug_P(PSTR("\nThese %d devices are supported as solar module devices:"), _SolarModule_Types_max); + for (i = 0; i < _SolarModule_Types_max; i++) { myDebug_P(PSTR(" %s%s%s (DeviceID:0x%02X ProductID:%d)"), COLOR_BOLD_ON, - SolarModule_Types[i].model_string, + SolarModule_Devices[i].model_string, COLOR_BOLD_OFF, - SolarModule_Types[i].device_id, - SolarModule_Types[i].product_id); + SolarModule_Devices[i].device_id, + SolarModule_Devices[i].product_id); } - myDebug_P(PSTR("\nThese %d devices are supported as other known EMS devices:"), _Other_Types_max); - for (i = 0; i < _Other_Types_max; i++) { + myDebug_P(PSTR("\nThese %d devices are supported as other known EMS devices:"), _Other_Devices_max); + for (i = 0; i < _Other_Devices_max; i++) { myDebug_P(PSTR(" %s%s%s (DeviceID:0x%02X ProductID:%d)"), COLOR_BOLD_ON, - Other_Types[i].model_string, + Other_Devices[i].model_string, COLOR_BOLD_OFF, - Other_Types[i].device_id, - Other_Types[i].product_id); + Other_Devices[i].device_id, + Other_Devices[i].product_id); } myDebug_P(PSTR("\nThe following telegram type IDs are supported:")); @@ -2305,15 +2297,15 @@ void ems_printAllDevices() { } } - myDebug_P(PSTR("\nThese %d thermostat devices are supported:"), _Thermostat_Types_max); - for (i = 0; i < _Thermostat_Types_max; i++) { + myDebug_P(PSTR("\nThese %d thermostat devices are supported:"), _Thermostat_Devices_max); + for (i = 0; i < _Thermostat_Devices_max; i++) { myDebug_P(PSTR(" %s%s%s (DeviceID:0x%02X ProductID:%d) can write:%c"), COLOR_BOLD_ON, - Thermostat_Types[i].model_string, + Thermostat_Devices[i].model_string, COLOR_BOLD_OFF, - Thermostat_Types[i].device_id, - Thermostat_Types[i].product_id, - (Thermostat_Types[i].write_supported) ? 'y' : 'n'); + Thermostat_Devices[i].device_id, + Thermostat_Devices[i].product_id, + (Thermostat_Devices[i].write_supported) ? 'y' : 'n'); } // print out known devices @@ -2328,7 +2320,7 @@ void ems_printAllDevices() { void ems_printDevices() { if (Devices.size() != 0) { myDebug_P(PSTR("\nThese %d EMS devices were detected:"), Devices.size()); - for (std::list<_Generic_Type>::iterator it = Devices.begin(); it != Devices.end(); it++) { + for (std::list<_Generic_Device>::iterator it = Devices.begin(); it != Devices.end(); it++) { myDebug_P(PSTR(" %s%s%s (DeviceID:0x%02X ProductID:%d Version:%s)"), COLOR_BOLD_ON, (it)->model_string, @@ -2352,7 +2344,7 @@ uint8_t ems_printDevices_s(char * buffer, uint16_t len) { } char s[100]; - for (std::list<_Generic_Type>::iterator it = Devices.begin(); it != Devices.end(); it++) { + for (std::list<_Generic_Device>::iterator it = Devices.begin(); it != Devices.end(); it++) { sprintf(s, "%s (DeviceID:0x%02X ProductID:%d Version:%s)
", (it)->model_string, (it)->device_id, (it)->product_id, (it)->version); strlcat(buffer, s, len); } @@ -2468,7 +2460,7 @@ void ems_setThermostatTemp(float temperature, uint8_t temptype) { } if (!EMS_Thermostat.write_supported) { - myDebug_P(PSTR("Write not supported for this model Thermostat")); + myDebug_P(PSTR("Write not supported for this Thermostat model")); return; } @@ -2476,17 +2468,15 @@ void ems_setThermostatTemp(float temperature, uint8_t temptype) { EMS_TxTelegram.timestamp = millis(); // set timestamp EMS_Sys_Status.txRetryCount = 0; // reset retry counter - uint8_t model_id = EMS_Thermostat.model_id; - uint8_t type = EMS_Thermostat.device_id; - uint8_t hc = EMS_Thermostat.hc; // heating circuit + uint8_t model_id = EMS_Thermostat.model_id; + uint8_t device_id = EMS_Thermostat.device_id; + uint8_t hc = EMS_Thermostat.hc; // heating circuit EMS_TxTelegram.action = EMS_TX_TELEGRAM_WRITE; - EMS_TxTelegram.dest = type; + EMS_TxTelegram.dest = device_id; myDebug_P(PSTR("Setting new thermostat temperature")); - // when doing a comparison to validate the new temperature we call a different type - if (model_id == EMS_MODEL_RC20) { EMS_TxTelegram.type = EMS_TYPE_RC20Set; EMS_TxTelegram.offset = EMS_OFFSET_RC20Set_temp; @@ -2499,6 +2489,15 @@ void ems_setThermostatTemp(float temperature, uint8_t temptype) { EMS_TxTelegram.type = EMS_TYPE_RC30Set; EMS_TxTelegram.offset = EMS_OFFSET_RC30Set_temp; EMS_TxTelegram.comparisonPostRead = EMS_TYPE_RC30StatusMessage; + + } else if (model_id == EMS_MODEL_RC300) { + EMS_TxTelegram.type = EMS_TYPE_RCPLUSSet; // for 3000 and 1010, e.g. 0B 10 FF (0A | 08) 01 89 2B + // check mode + if (EMS_Thermostat.mode == 1) { // auto + EMS_TxTelegram.offset = 0x08; // auto offset + } else if (EMS_Thermostat.mode == 0) { // manuaL + EMS_TxTelegram.offset = 0x0A; // manual offset + } } else if ((model_id == EMS_MODEL_RC35) || (model_id == EMS_MODEL_ES73)) { switch (temptype) { case 1: // change the night temp @@ -2519,7 +2518,6 @@ void ems_setThermostatTemp(float temperature, uint8_t temptype) { } break; } - if (hc == 1) { // heating circuit 1 EMS_TxTelegram.type = EMS_TYPE_RC35Set_HC1; @@ -2532,7 +2530,7 @@ void ems_setThermostatTemp(float temperature, uint8_t temptype) { } EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH; - EMS_TxTelegram.dataValue = (uint8_t)((float)temperature * (float)2); // value + EMS_TxTelegram.dataValue = (uint8_t)((float)temperature * (float)2); // value * 2 EMS_TxTelegram.type_validate = EMS_TxTelegram.type; EMS_TxTelegram.comparisonOffset = EMS_TxTelegram.offset; EMS_TxTelegram.comparisonValue = EMS_TxTelegram.dataValue; @@ -2542,8 +2540,9 @@ void ems_setThermostatTemp(float temperature, uint8_t temptype) { } /** - * Set the thermostat working mode (0=low/night, 1=manual/day, 2=auto/clock) - * 0xA8 on a RC20 and 0xA7 on RC30 + * Set the thermostat working mode + * (0=low/night, 1=manual/day, 2=auto/clock), 0xA8 on a RC20 and 0xA7 on RC30 + * 0x01B9 for EMS+ 300/1000/3000, Auto=0xFF Manual=0x00. See https://github.com/proddy/EMS-ESP/wiki/RC3xx-Thermostats */ void ems_setThermostatMode(uint8_t mode) { if (!ems_getThermostatEnabled()) { @@ -2555,9 +2554,18 @@ void ems_setThermostatMode(uint8_t mode) { return; } - uint8_t model_id = EMS_Thermostat.model_id; - uint8_t type = EMS_Thermostat.device_id; - uint8_t hc = EMS_Thermostat.hc; + uint8_t model_id = EMS_Thermostat.model_id; + uint8_t device_id = EMS_Thermostat.device_id; + uint8_t hc = EMS_Thermostat.hc; + + // RC300/1000/3000 have different settings + if (model_id == EMS_MODEL_RC300) { + if (mode == 1) { + mode = 0; // manual + } else { + mode = 0xFF; // auto + } + } myDebug_P(PSTR("Setting thermostat mode to %d"), mode); @@ -2566,7 +2574,7 @@ void ems_setThermostatMode(uint8_t mode) { EMS_Sys_Status.txRetryCount = 0; // reset retry counter EMS_TxTelegram.action = EMS_TX_TELEGRAM_WRITE; - EMS_TxTelegram.dest = type; + EMS_TxTelegram.dest = device_id; EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH; EMS_TxTelegram.dataValue = mode; @@ -2580,6 +2588,9 @@ void ems_setThermostatMode(uint8_t mode) { } else if ((model_id == EMS_MODEL_RC35) || (model_id == EMS_MODEL_ES73)) { EMS_TxTelegram.type = (hc == 2) ? EMS_TYPE_RC35Set_HC2 : EMS_TYPE_RC35Set_HC1; EMS_TxTelegram.offset = EMS_OFFSET_RC35Set_mode; + } else if (model_id == EMS_MODEL_RC300) { + EMS_TxTelegram.type = EMS_TYPE_RCPLUSSet; // for 3000 and 1010, e.g. 48 10 FF 00 01 B9 00 for manual + EMS_TxTelegram.offset = EMS_OFFSET_RCPLUSSet_mode; } EMS_TxTelegram.type_validate = EMS_TxTelegram.type; // callback to EMS_TYPE_RC30Temperature to fetch temps diff --git a/src/ems.h b/src/ems.h index d06ba7f19..f65a35ccc 100644 --- a/src/ems.h +++ b/src/ems.h @@ -223,25 +223,25 @@ const _EMS_TxTelegram EMS_TX_TELEGRAM_NEW = { typedef struct { uint8_t product_id; char model_string[50]; -} _Boiler_Type; +} _Boiler_Device; typedef struct { uint8_t product_id; uint8_t device_id; char model_string[50]; -} _SolarModule_Type; +} _SolarModule_Device; typedef struct { uint8_t product_id; uint8_t device_id; char model_string[50]; -} _Other_Type; +} _Other_Device; typedef struct { uint8_t product_id; uint8_t device_id; char model_string[50]; -} _HeatPump_Type; +} _HeatPump_Device; typedef struct { uint8_t model_id; @@ -249,7 +249,7 @@ typedef struct { uint8_t device_id; char model_string[50]; bool write_supported; -} _Thermostat_Type; +} _Thermostat_Device; // for consolidating all types typedef struct { @@ -257,7 +257,7 @@ typedef struct { uint8_t device_id; char version[10]; char model_string[50]; -} _Generic_Type; +} _Generic_Device; /* * Telegram package defintions diff --git a/src/ems_devices.h b/src/ems_devices.h index f33a1c88a..c581c0b16 100644 --- a/src/ems_devices.h +++ b/src/ems_devices.h @@ -13,12 +13,12 @@ #include "ems.h" /* - * Common + * Common Type */ #define EMS_TYPE_Version 0x02 /* - * Boiler... + * Boiler Telegram Types... */ #define EMS_TYPE_UBAMonitorFast 0x18 // is an automatic monitor broadcast #define EMS_TYPE_UBAMonitorSlow 0x19 // is an automatic monitor broadcast @@ -40,7 +40,7 @@ #define EMS_OFFSET_UBASetPoints_flowtemp 0 // flow temp -// Other +// SM and HP Types #define EMS_TYPE_SM10Monitor 0x97 // SM10Monitor #define EMS_TYPE_SM100Monitor 0x0262 // SM100Monitor #define EMS_TYPE_SM100Status 0x0264 // SM100Status @@ -54,7 +54,7 @@ #define EMS_OFFSET_ISM1Set_MaxBoilerTemp 6 // position of max boiler temp e.g. 50 in the following example: 90 30 FF 06 00 01 50 (CRC=2C) /* - * Thermostats... + * Thermostat Types */ // Common for all thermostats @@ -106,13 +106,17 @@ // RC1010, RC310 and RC300 specific (EMS Plus) #define EMS_TYPE_RCPLUSStatusMessage 0x01A5 // is an automatic thermostat broadcast giving us temps -#define EMS_TYPE_RCPLUSStatusHeating 0x01B9 // heating mode #define EMS_TYPE_RCPLUSStatusMode 0x1AF // summer/winter mode -#define EMS_TYPE_RCPLUSSet 0x03 // setpoint temp message +#define EMS_TYPE_RCPLUSSet 0x01B9 // setpoint temp message and mode #define EMS_OFFSET_RCPLUSStatusMessage_setpoint 3 // setpoint temp #define EMS_OFFSET_RCPLUSStatusMessage_curr 0 // current temp -#define EMS_OFFSET_RCPLUSGet_mode_day 8 // day/night mode +#define EMS_OFFSET_RCPLUSGet_mode_day 10 // day/night mode +#define EMS_OFFSET_RCPLUSSet_mode 0 // operation mode (Auto=xFF, Manual=x00) #define EMS_OFFSET_RCPLUSStatusMessage_mode 0x0A // thermostat mode (auto, manual) +#define EMS_OFFSET_RCPLUSSet_temp_comfort3 1 // comfort3 level +#define EMS_OFFSET_RCPLUSSet_temp_comfort2 2 // comfort2 level +#define EMS_OFFSET_RCPLUSSet_temp_comfort1 3 // comfort1 level +#define EMS_OFFSET_RCPLUSSet_temp_eco 4 // eco level // Junkers FR10, FW100 (EMS Plus) #define EMS_TYPE_JunkersStatusMessage 0x6F // is an automatic thermostat broadcast giving us temps @@ -120,7 +124,7 @@ #define EMS_OFFSET_JunkersStatusMessage_curr 4 // current temp -// Known EMS types +// Known EMS devices typedef enum { EMS_MODEL_NONE, // unset EMS_MODEL_ALL, // common for all devices @@ -157,7 +161,7 @@ typedef enum { // EMS types for known boilers. This list will be extended when new devices are recognized. // The device_id is always 0x08 // format is PRODUCT ID, DESCRIPTION -const _Boiler_Type Boiler_Types[] = { +const _Boiler_Device Boiler_Devices[] = { {72, "MC10 Module"}, {123, "Buderus GB172/Nefit Trendline/Junkers Cerapur"}, @@ -175,7 +179,7 @@ const _Boiler_Type Boiler_Types[] = { * Known Solar Module types * format is PRODUCT ID, DEVICE ID, DESCRIPTION */ -const _SolarModule_Type SolarModule_Types[] = { +const _SolarModule_Device SolarModule_Devices[] = { {EMS_PRODUCTID_SM10, EMS_ID_SM, "SM10 Solar Module"}, {EMS_PRODUCTID_SM100, EMS_ID_SM, "SM100 Solar Module"}, @@ -185,7 +189,7 @@ const _SolarModule_Type SolarModule_Types[] = { // Other EMS devices which are not considered boilers, thermostats or solar modules // format is PRODUCT ID, DEVICE ID, DESCRIPTION -const _Other_Type Other_Types[] = { +const _Other_Device Other_Devices[] = { {69, 0x21, "MM10 Mixer Module"}, {71, 0x11, "WM10 Switch Module"}, @@ -207,13 +211,13 @@ const _Other_Type Other_Types[] = { // heatpump // format is PRODUCT ID, DEVICE ID, DESCRIPTION -const _HeatPump_Type HeatPump_Types[] = {{252, EMS_ID_HP, "HeatPump Module"}}; +const _HeatPump_Device HeatPump_Devices[] = {{252, EMS_ID_HP, "HeatPump Module"}}; /* * Known thermostat types and their capabilities * format is MODEL_ID, PRODUCT ID, DEVICE ID, DESCRIPTION */ -const _Thermostat_Type Thermostat_Types[] = { +const _Thermostat_Device Thermostat_Devices[] = { // Easy devices - not currently supporting write operations {EMS_MODEL_EASY, 202, 0x18, "Logamatic TC100/Nefit Moduline Easy", EMS_THERMOSTAT_WRITE_NO}, @@ -226,7 +230,7 @@ const _Thermostat_Type Thermostat_Types[] = { {EMS_MODEL_RC20F, 93, 0x18, "RC20F", EMS_THERMOSTAT_WRITE_YES}, {EMS_MODEL_RC30, 78, 0x10, "RC30/Nefit Moduline 400", EMS_THERMOSTAT_WRITE_YES}, {EMS_MODEL_RC35, 86, 0x10, "RC35", EMS_THERMOSTAT_WRITE_YES}, - {EMS_MODEL_RC300, 158, 0x10, "RC300/RC310/Nefit Moduline 3000", EMS_THERMOSTAT_WRITE_NO}, + {EMS_MODEL_RC300, 158, 0x10, "RC300/RC310/Nefit Moduline 3000", EMS_THERMOSTAT_WRITE_YES}, {EMS_MODEL_1010, 165, 0x18, "Nefit Moduline 1010", EMS_THERMOSTAT_WRITE_NO}, // Sieger diff --git a/src/emsuart.cpp b/src/emsuart.cpp index 834718524..fb1713d65 100644 --- a/src/emsuart.cpp +++ b/src/emsuart.cpp @@ -7,7 +7,6 @@ #include "emsuart.h" #include "ems.h" -#include #include _EMSRxBuf * pEMSRxBuf; diff --git a/src/emsuart.h b/src/emsuart.h index 3a4f9da7e..0859aaf2f 100644 --- a/src/emsuart.h +++ b/src/emsuart.h @@ -7,7 +7,6 @@ */ #pragma once -#include #include #define EMSUART_UART 0 // UART 0