From 98a41db973927b0017d45c1e00772eaba83d5bd5 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 3 Mar 2020 22:23:53 +0100 Subject: [PATCH] support writing to FR100 - #335 --- src/ems-esp.cpp | 76 +++++++++++++++++------ src/ems.cpp | 149 +++++++++++++++++++++++++--------------------- src/ems.h | 86 ++++++++++++++------------ src/ems_devices.h | 45 +++++++++----- src/my_config.h | 3 + src/version.h | 2 +- 6 files changed, 220 insertions(+), 141 deletions(-) diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index 8d3d50fb4..bb884411e 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -113,8 +113,8 @@ static const command_t project_cmds[] PROGMEM = { {false, "queue", "show current Tx queue"}, {false, "send XX ...", "send raw telegram data to EMS bus (XX are hex values)"}, {false, "thermostat read ", "send read request to the thermostat for heating circuit hc 1-4"}, - {false, "thermostat temp [hc] ", "set current thermostat temperature"}, - {false, "thermostat mode [hc] ", "set mode (0=off, 1=manual, 2=auto) for heating circuit hc 1-4"}, + {false, "thermostat temp [temp]", "set current thermostat temperature. temp=0-6 (see wiki)"}, + {false, "thermostat mode ", "set mode (0=off, 1=manual, 2=auto) for heating circuit hc 1-4"}, {false, "boiler read ", "send read request to boiler"}, {false, "boiler wwtemp ", "set boiler warm water temperature"}, {false, "boiler wwactive ", "set boiler warm water on/off"}, @@ -144,7 +144,7 @@ _EMS_THERMOSTAT_MODE _getThermostatMode(uint8_t hc_num) { _EMS_THERMOSTAT_MODE thermoMode = EMS_THERMOSTAT_MODE_UNKNOWN; uint8_t mode = EMS_Thermostat.hc[hc_num - 1].mode; - uint8_t model = ems_getThermostatModel(); + uint8_t model = ems_getThermostatFlags(); if (model == EMS_DEVICE_FLAG_RC20) { if (mode == 0) { @@ -184,7 +184,7 @@ _EMS_THERMOSTAT_MODE _getThermostatMode(uint8_t hc_num) { // hc_num is 1 to 4 _EMS_THERMOSTAT_MODE _getThermostatMode2(uint8_t hc_num) { _EMS_THERMOSTAT_MODE thermoMode = EMS_THERMOSTAT_MODE_UNKNOWN; - uint8_t model = ems_getThermostatModel(); + uint8_t model = ems_getThermostatFlags(); uint8_t mode = EMS_Thermostat.hc[hc_num - 1].mode_type; @@ -424,7 +424,7 @@ void showInfo() { myDebug_P(PSTR(" Thermostat: %s"), ems_getDeviceDescription(EMS_DEVICE_TYPE_THERMOSTAT, buffer_type, false)); // Render Thermostat Date & Time - uint8_t model = ems_getThermostatModel(); + uint8_t model = ems_getThermostatFlags(); if ((model != EMS_DEVICE_FLAG_EASY)) { myDebug_P(PSTR(" Thermostat time is %s"), EMS_Thermostat.datetime); } @@ -733,7 +733,7 @@ bool publishEMSValues_boiler() { rootBoiler["wWRecharge"] = _bool_to_char(s, EMS_Boiler.wWRecharging); } if (EMS_Boiler.wWActivated != EMS_VALUE_BOOL_NOTSET) { - rootBoiler["wWTempOK"] = _bool_to_char(s, EMS_Boiler.wWTemperaturOK); + rootBoiler["wWTempOK"] = _bool_to_char(s, EMS_Boiler.wWTemperatureOK); } if (EMS_Boiler.wWCirc != EMS_VALUE_BOOL_NOTSET) { rootBoiler["wWCirc"] = _bool_to_char(s, EMS_Boiler.wWCirc); @@ -814,7 +814,7 @@ bool publishEMSValues_thermostat() { // only send if we have an active Heating Circuit with an actual setpoint temp temperature values if ((thermostat->active) && (thermostat->setpoint_roomTemp > EMS_VALUE_SHORT_NOTSET)) { - uint8_t model = ems_getThermostatModel(); // fetch model flags + uint8_t model = ems_getThermostatFlags(); // fetch model flags has_data = true; if (myESP.mqttUseNestedJson()) { @@ -1603,19 +1603,21 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) { // thermostat commands if ((strcmp(first_cmd, "thermostat") == 0) && (wc >= 3)) { - char * second_cmd = _readWord(); - uint8_t hc = EMS_THERMOSTAT_DEFAULTHC; + char * second_cmd = _readWord(); if (strcmp(second_cmd, "temp") == 0) { - if (wc == 4) { - hc = _readIntNumber(); // next parameter is the heating circuit + uint8_t hc = _readIntNumber(); // next parameter is the heating circuit + float temp = _readFloatNumber(); // read in next param which is the temp + if (wc == 5) { + // we have a temp mode given + _THERMOSTAT_TEMP_MODE temp_mode = (_THERMOSTAT_TEMP_MODE)_readIntNumber(); // next parameter is the temp mode type + ems_setThermostatTemp(temp, hc, temp_mode); + } else { + ems_setThermostatTemp(temp, hc); } - ems_setThermostatTemp(_readFloatNumber(), hc); ok = true; } else if (strcmp(second_cmd, "mode") == 0) { - if (wc == 4) { - hc = _readIntNumber(); // next parameter is the heating circuit - } + uint8_t hc = _readIntNumber(); // next parameter is the heating circuit ems_setThermostatMode(_readIntNumber(), hc); ok = true; } else if (strcmp(second_cmd, "read") == 0) { @@ -2005,7 +2007,7 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) { if (EMS_Thermostat.hc[hc - 1].active) { float f = doc["data"]; if (f) { - ems_setThermostatTemp(f, hc, 1); // night + ems_setThermostatTemp(f, hc, THERMOSTAT_TEMP_MODE_NIGHT); // night return; } } @@ -2017,7 +2019,7 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) { if (EMS_Thermostat.hc[hc - 1].active) { float f = doc["data"]; if (f) { - ems_setThermostatTemp(f, hc, 2); // day + ems_setThermostatTemp(f, hc, THERMOSTAT_TEMP_MODE_DAY); // day } return; } @@ -2029,7 +2031,43 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) { if (EMS_Thermostat.hc[hc - 1].active) { float f = doc["data"]; if (f) { - ems_setThermostatTemp(f, hc, 3); // holiday + ems_setThermostatTemp(f, hc, THERMOSTAT_TEMP_MODE_HOLIDAY); // holiday + } + return; + } + } + + // set eco value + hc = _hasHCspecified(TOPIC_THERMOSTAT_CMD_ECOTEMP, command); + if (hc) { + if (EMS_Thermostat.hc[hc - 1].active) { + float f = doc["data"]; + if (f) { + ems_setThermostatTemp(f, hc, THERMOSTAT_TEMP_MODE_ECO); // holiday + } + return; + } + } + + // set heat value + hc = _hasHCspecified(TOPIC_THERMOSTAT_CMD_HEATTEMP, command); + if (hc) { + if (EMS_Thermostat.hc[hc - 1].active) { + float f = doc["data"]; + if (f) { + ems_setThermostatTemp(f, hc, THERMOSTAT_TEMP_MODE_HEAT); // holiday + } + return; + } + } + + // set nofrost value + hc = _hasHCspecified(TOPIC_THERMOSTAT_CMD_NOFROSTTEMP, command); + if (hc) { + if (EMS_Thermostat.hc[hc - 1].active) { + float f = doc["data"]; + if (f) { + ems_setThermostatTemp(f, hc, THERMOSTAT_TEMP_MODE_NOFROST); // holiday } return; } @@ -2109,7 +2147,7 @@ void WebCallback(JsonObject root) { thermostat["tm"] = ems_getDeviceDescription(EMS_DEVICE_TYPE_THERMOSTAT, buffer, true); uint8_t hc_num = 1; // default to HC1 - uint8_t model = ems_getThermostatModel(); + uint8_t model = ems_getThermostatFlags(); while (hc_num < EMS_THERMOSTAT_MAXHC && !EMS_Thermostat.hc[hc_num - 1].active) hc_num++; // first active hc // Render Current & Setpoint Room Temperature diff --git a/src/ems.cpp b/src/ems.cpp index bfb45634c..60508a276 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -180,14 +180,14 @@ void ems_init() { EMS_Boiler.switchTemp = EMS_VALUE_USHORT_NOTSET; // UBAMonitorWWMessage - EMS_Boiler.wWCurTmp = EMS_VALUE_USHORT_NOTSET; // Warm Water current temperature - EMS_Boiler.wWStarts = EMS_VALUE_LONG_NOTSET; // Warm Water # starts - EMS_Boiler.wWWorkM = EMS_VALUE_LONG_NOTSET; // Warm Water # minutes - EMS_Boiler.wWOneTime = EMS_VALUE_INT_NOTSET; // Warm Water one time function on/off - EMS_Boiler.wWDesinfecting = EMS_VALUE_INT_NOTSET; // Warm Water desinfection on/off - EMS_Boiler.wWReadiness = EMS_VALUE_INT_NOTSET; // Warm Water readiness on/off - EMS_Boiler.wWRecharging = EMS_VALUE_INT_NOTSET; // Warm Water recharge on/off - EMS_Boiler.wWTemperaturOK = EMS_VALUE_INT_NOTSET; // Warm Water temperatur ok on/off + EMS_Boiler.wWCurTmp = EMS_VALUE_USHORT_NOTSET; // Warm Water current temperature + EMS_Boiler.wWStarts = EMS_VALUE_LONG_NOTSET; // Warm Water # starts + EMS_Boiler.wWWorkM = EMS_VALUE_LONG_NOTSET; // Warm Water # minutes + EMS_Boiler.wWOneTime = EMS_VALUE_INT_NOTSET; // Warm Water one time function on/off + EMS_Boiler.wWDesinfecting = EMS_VALUE_INT_NOTSET; // Warm Water desinfection on/off + EMS_Boiler.wWReadiness = EMS_VALUE_INT_NOTSET; // Warm Water readiness on/off + EMS_Boiler.wWRecharging = EMS_VALUE_INT_NOTSET; // Warm Water recharge on/off + EMS_Boiler.wWTemperatureOK = EMS_VALUE_INT_NOTSET; // Warm Water temperature ok on/off EMS_Boiler.wWCurFlow = EMS_VALUE_INT_NOTSET; // WW current flow temp @@ -266,11 +266,11 @@ bool ems_getHeatPumpEnabled() { return (EMS_HeatPump.device_id != EMS_ID_NONE); } -uint8_t ems_getThermostatModel() { - return (EMS_Thermostat.device_flags & 0x7F); // strip 7th bit +uint8_t ems_getThermostatFlags() { + return (EMS_Thermostat.device_flags & 0x7F); // strip 7th bit which is used to show whether Write is supported } -uint8_t ems_getSolarModuleModel() { +uint8_t ems_getSolarModuleFlags() { return (EMS_SolarModule.device_flags); } @@ -995,7 +995,7 @@ void _process_UBAMonitorWWMessage(_EMS_RxTelegram * EMS_RxTelegram) { _setValue(EMS_RxTelegram, &EMS_Boiler.wWDesinfecting, 5, 2); _setValue(EMS_RxTelegram, &EMS_Boiler.wWReadiness, 5, 3); _setValue(EMS_RxTelegram, &EMS_Boiler.wWRecharging, 5, 4); - _setValue(EMS_RxTelegram, &EMS_Boiler.wWTemperaturOK, 5, 5); + _setValue(EMS_RxTelegram, &EMS_Boiler.wWTemperatureOK, 5, 5); _setValue(EMS_RxTelegram, &EMS_Boiler.wWCurFlow, 9); } @@ -1062,7 +1062,7 @@ void _process_UBAMonitorFast(_EMS_RxTelegram * EMS_RxTelegram) { // warm water storage sensors (if present) // wwStorageTemp2 is also used by some brands as the boiler temperature - see https://github.com/proddy/EMS-ESP/issues/206 _setValue(EMS_RxTelegram, &EMS_Boiler.wwStorageTemp1, 9); // 0x8300 if not available - _setValue(EMS_RxTelegram, &EMS_Boiler.wwStorageTemp2, 11); // 0x8000 if not available + _setValue(EMS_RxTelegram, &EMS_Boiler.wwStorageTemp2, 11); // 0x8000 if not available - this is boiler temp _setValue(EMS_RxTelegram, &EMS_Boiler.retTemp, 13); _setValue(EMS_RxTelegram, &EMS_Boiler.flameCurr, 15); @@ -1466,28 +1466,32 @@ int8_t _getHeatingCircuit(_EMS_RxTelegram * EMS_RxTelegram) { case EMS_TYPE_RC35StatusMessage_HC1: case EMS_TYPE_RC35Set_HC1: case EMS_TYPE_JunkersStatusMessage_HC1: - case EMS_TYPE_JunkersSetMessage_HC1: + case EMS_TYPE_JunkersSetMessage1_HC1: + case EMS_TYPE_JunkersSetMessage2_HC1: hc = 0; break; case EMS_TYPE_RC35StatusMessage_HC2: case EMS_TYPE_RC35Set_HC2: case EMS_TYPE_JunkersStatusMessage_HC2: - case EMS_TYPE_JunkersSetMessage_HC2: + case EMS_TYPE_JunkersSetMessage1_HC2: + case EMS_TYPE_JunkersSetMessage2_HC2: hc = 1; break; case EMS_TYPE_RC35StatusMessage_HC3: case EMS_TYPE_RC35Set_HC3: case EMS_TYPE_JunkersStatusMessage_HC3: - case EMS_TYPE_JunkersSetMessage_HC3: + case EMS_TYPE_JunkersSetMessage1_HC3: + case EMS_TYPE_JunkersSetMessage2_HC3: hc = 2; break; case EMS_TYPE_RC35StatusMessage_HC4: case EMS_TYPE_RC35Set_HC4: case EMS_TYPE_JunkersStatusMessage_HC4: - case EMS_TYPE_JunkersSetMessage_HC4: + case EMS_TYPE_JunkersSetMessage1_HC4: + case EMS_TYPE_JunkersSetMessage2_HC4: hc = 3; break; @@ -2323,7 +2327,7 @@ void ems_sendRawTelegram(char * telegram) { * hc_num is 1 to 4 * temptype 0=normal, 1=night temp, 2=day temp, 3=holiday temp */ -void ems_setThermostatTemp(float temperature, uint8_t hc_num, uint8_t temptype) { +void ems_setThermostatTemp(float temperature, uint8_t hc_num, _THERMOSTAT_TEMP_MODE temptype) { if (!ems_getThermostatEnabled()) { myDebug_P(PSTR("Thermostat not online.")); return; @@ -2343,15 +2347,15 @@ void ems_setThermostatTemp(float temperature, uint8_t hc_num, uint8_t temptype) EMS_TxTelegram.timestamp = millis(); // set timestamp EMS_Sys_Status.txRetryCount = 0; // reset retry counter - uint8_t model = ems_getThermostatModel(); + uint8_t model = ems_getThermostatFlags(); uint8_t device_id = EMS_Thermostat.device_id; EMS_TxTelegram.action = EMS_TX_TELEGRAM_WRITE; EMS_TxTelegram.dest = device_id; char s[10] = {0}; - if ((model == EMS_DEVICE_FLAG_RC35) || (model == EMS_DEVICE_FLAG_RC30N)) { - myDebug_P(PSTR("Setting new thermostat temperature to %s for heating circuit %d type %d (0=auto,1=night,2=day,3=holiday)"), + if (temptype != 0) { + myDebug_P(PSTR("Setting new thermostat temperature to %s for heating circuit %d temp mode %d (0=auto,1=night,2=day,3=holiday,4=nofrost,5=eco,6=heat)"), _float_to_char(s, temperature), hc_num, temptype); @@ -2407,17 +2411,17 @@ void ems_setThermostatTemp(float temperature, uint8_t hc_num, uint8_t temptype) else if ((model == EMS_DEVICE_FLAG_RC35) || (model == EMS_DEVICE_FLAG_RC30N)) { switch (temptype) { - case 1: // change the night temp + case THERMOSTAT_TEMP_MODE_NIGHT: // change the night temp EMS_TxTelegram.offset = EMS_OFFSET_RC35Set_temp_night; break; - case 2: // change the day temp + case THERMOSTAT_TEMP_MODE_DAY: // change the day temp EMS_TxTelegram.offset = EMS_OFFSET_RC35Set_temp_day; break; - case 3: // change the holiday temp + case THERMOSTAT_TEMP_MODE_HOLIDAY: // change the holiday temp EMS_TxTelegram.offset = EMS_OFFSET_RC35Set_temp_holiday; break; default: - case 0: // automatic selection, if no type is defined, we use the standard code + case THERMOSTAT_TEMP_MODE_AUTO: // automatic selection, if no type is defined, we use the standard code if (model == EMS_DEVICE_FLAG_RC35) { // https://github.com/proddy/EMS-ESP/issues/310 EMS_TxTelegram.offset = EMS_OFFSET_RC35Set_seltemp; @@ -2448,42 +2452,54 @@ void ems_setThermostatTemp(float temperature, uint8_t hc_num, uint8_t temptype) } else if (model == EMS_DEVICE_FLAG_JUNKERS) { - // All Junkers use EMS+. I think. - EMS_TxTelegram.emsplus = true; - switch (temptype) { - case 1: // change the no frost temp - EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage_no_frost_temp; - break; - case 2: // change the night temp - EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage_night_temp; - break; - case 3: // change the day temp - EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage_day_temp; - break; - default: - case 0: // automatic selection, if no type is defined, we use the standard code - // TODO: not sure if this is correct for Junkers - if (EMS_Thermostat.hc[hc_num - 1].mode_type == 0) { + EMS_TxTelegram.emsplus = true; // Assuming here that all Junkers use EMS+ + + // figure out if we have older or new thermostats + // Heating Circuits on 0x65 or 0x79 (see https://github.com/proddy/EMS-ESP/issues/335#issuecomment-593324716) + // strip 7th (write) and 6th (junkers) bits to leave EMS_DEVICE_FLAG_JUNKERS_CONFIG1 or CONFIG2 + bool newer_junkers = ((model & 0x3F) == EMS_DEVICE_FLAG_JUNKERS_CONFIG1); + + if (newer_junkers) { + // new models like the FW series + switch (temptype) { + case THERMOSTAT_TEMP_MODE_NOFROST: + EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage_no_frost_temp; + break; + case THERMOSTAT_TEMP_MODE_NIGHT: EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage_night_temp; - } else if (EMS_Thermostat.hc[hc_num - 1].mode_type == 1) { + break; + case THERMOSTAT_TEMP_MODE_DAY: EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage_day_temp; + break; + default: + case THERMOSTAT_TEMP_MODE_AUTO: // automatic selection, if no type is defined, we use the standard code + if (EMS_Thermostat.hc[hc_num - 1].mode_type == 0) { + EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage_night_temp; + } else if (EMS_Thermostat.hc[hc_num - 1].mode_type == 1) { + EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage_day_temp; + } + break; } - break; + EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage1_HC1 + hc_num - 1; // 0x65 + EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC1 + hc_num - 1; + } else { + switch (temptype) { + case THERMOSTAT_TEMP_MODE_NOFROST: + EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage2_no_frost_temp; + break; + case THERMOSTAT_TEMP_MODE_ECO: + EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage2_eco_temp; + break; + default: + case THERMOSTAT_TEMP_MODE_HEAT: + EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage3_heat; + break; + } + // older junkers models like the FR100 + EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage2_HC1 + hc_num - 1; // 0x79 + EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC1 + hc_num - 1; } - if (hc_num == 1) { - EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage_HC1; - EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC1; - } else if (hc_num == 2) { - EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage_HC2; - EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC2; - } else if (hc_num == 3) { - EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage_HC3; - EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC3; - } else if (hc_num == 4) { - EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage_HC4; - EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC4; - } EMS_TxTelegram.type_validate = EMS_TxTelegram.type; } @@ -2517,7 +2533,7 @@ void ems_setThermostatMode(uint8_t mode, uint8_t hc_num) { return; } - uint8_t model = ems_getThermostatModel(); + uint8_t model = ems_getThermostatFlags(); uint8_t device_id = EMS_Thermostat.device_id; uint8_t set_mode; @@ -2581,19 +2597,16 @@ void ems_setThermostatMode(uint8_t mode, uint8_t hc_num) { EMS_TxTelegram.type_validate = EMS_TxTelegram.type; } else if (model == EMS_DEVICE_FLAG_JUNKERS) { - if (hc_num == 1) { - EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage_HC1; + if ((model & 0x3F) == EMS_DEVICE_FLAG_JUNKERS_CONFIG1) { + // config 1 + EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage1_HC1 + hc_num - 1; + EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC1; + } else { + // config 2 + EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage2_HC1 + hc_num - 1; EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC1; - } else if (hc_num == 2) { - EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage_HC2; - EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC2; - } else if (hc_num == 3) { - EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage_HC3; - EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC3; - } else if (hc_num == 4) { - EMS_TxTelegram.type = EMS_TYPE_JunkersSetMessage_HC4; - EMS_TxTelegram.comparisonPostRead = EMS_TYPE_JunkersStatusMessage_HC4; } + EMS_TxTelegram.offset = EMS_OFFSET_JunkersSetMessage_set_mode; EMS_TxTelegram.type_validate = EMS_TxTelegram.type; diff --git a/src/ems.h b/src/ems.h index 9132a5f63..93cad6ff1 100644 --- a/src/ems.h +++ b/src/ems.h @@ -48,33 +48,24 @@ // Device Flags // They are unique to the model type (mixing, solar, thermostat etc) enum EMS_DEVICE_FLAG_TYPES : uint8_t { - EMS_DEVICE_FLAG_NONE = 0, - EMS_DEVICE_FLAG_MMPLUS = 20, // mixing EMS+ - EMS_DEVICE_FLAG_MM10 = 21, // mixing MM10, MM50 - EMS_DEVICE_FLAG_SM10 = 10, - EMS_DEVICE_FLAG_SM100 = 11, // for SM100 and SM200 - EMS_DEVICE_FLAG_EASY = 1, - EMS_DEVICE_FLAG_RC10 = 2, - EMS_DEVICE_FLAG_RC20 = 3, - EMS_DEVICE_FLAG_RC30 = 4, - EMS_DEVICE_FLAG_RC30N = 5, // newer type of RC30 with RC35 circuit - EMS_DEVICE_FLAG_RC35 = 6, - EMS_DEVICE_FLAG_RC300 = 7, - EMS_DEVICE_FLAG_JUNKERS = (1 << 6), // 6th bit set if its junkers HT3 - EMS_DEVICE_FLAG_NO_WRITE = (1 << 7) // top bit set if thermostat write not supported + EMS_DEVICE_FLAG_NONE = 0, + EMS_DEVICE_FLAG_MMPLUS = 20, // mixing EMS+ + EMS_DEVICE_FLAG_MM10 = 21, // mixing MM10, MM50 + EMS_DEVICE_FLAG_SM10 = 10, + EMS_DEVICE_FLAG_SM100 = 11, // for SM100 and SM200 + EMS_DEVICE_FLAG_EASY = 1, + EMS_DEVICE_FLAG_RC10 = 2, + EMS_DEVICE_FLAG_RC20 = 3, + EMS_DEVICE_FLAG_RC30 = 4, + EMS_DEVICE_FLAG_RC30N = 5, // newer type of RC30 with RC35 circuit + EMS_DEVICE_FLAG_RC35 = 6, + EMS_DEVICE_FLAG_RC300 = 7, + EMS_DEVICE_FLAG_JUNKERS_CONFIG1 = 1, // use 0x65 for HC + EMS_DEVICE_FLAG_JUNKERS_CONFIG2 = 2, // use 0x79 for HC, older models + EMS_DEVICE_FLAG_JUNKERS = (1 << 6), // 6th bit set if its junkers HT3 + EMS_DEVICE_FLAG_NO_WRITE = (1 << 7) // top bit set if thermostat write not supported }; -typedef enum { - EMS_THERMOSTAT_MODE_UNKNOWN, - EMS_THERMOSTAT_MODE_OFF, - EMS_THERMOSTAT_MODE_MANUAL, - EMS_THERMOSTAT_MODE_AUTO, - EMS_THERMOSTAT_MODE_NIGHT, - EMS_THERMOSTAT_MODE_DAY, - EMS_THERMOSTAT_MODE_ECO, - EMS_THERMOSTAT_MODE_COMFORT -} _EMS_THERMOSTAT_MODE; - // trigger settings to determine if hot tap water or the heating is active #define EMS_BOILER_BURNPOWER_TAPWATER 100 #define EMS_BOILER_SELFLOWTEMP_HEATING 30 // was 70, changed to 30 for https://github.com/proddy/EMS-ESP/issues/193 @@ -324,15 +315,15 @@ typedef struct { uint16_t switchTemp; // Switch temperature // UBAMonitorWWMessage - uint16_t wWCurTmp; // Warm Water current temperature - uint32_t wWStarts; // Warm Water # starts - uint32_t wWWorkM; // Warm Water # minutes - uint8_t wWOneTime; // Warm Water one time function on/off - uint8_t wWDesinfecting; // Warm Water desinfection on/off - uint8_t wWReadiness; // Warm Water readiness on/off - uint8_t wWRecharging; // Warm Water recharge on/off - uint8_t wWTemperaturOK; // Warm Water temperatur ok on/off - uint8_t wWCurFlow; // Warm Water current flow in l/min + uint16_t wWCurTmp; // Warm Water current temperature + uint32_t wWStarts; // Warm Water # starts + uint32_t wWWorkM; // Warm Water # minutes + uint8_t wWOneTime; // Warm Water one time function on/off + uint8_t wWDesinfecting; // Warm Water desinfection on/off + uint8_t wWReadiness; // Warm Water readiness on/off + uint8_t wWRecharging; // Warm Water recharge on/off + uint8_t wWTemperatureOK; // Warm Water temperature ok on/off + uint8_t wWCurFlow; // Warm Water current flow in l/min // UBATotalUptimeMessage uint32_t UBAuptime; // Total UBA working hours @@ -450,6 +441,27 @@ typedef struct { EMS_processType_cb processType_cb; } _EMS_Type; +typedef enum : uint8_t { + THERMOSTAT_TEMP_MODE_AUTO = 0, + THERMOSTAT_TEMP_MODE_NIGHT, + THERMOSTAT_TEMP_MODE_DAY, + THERMOSTAT_TEMP_MODE_HOLIDAY, + THERMOSTAT_TEMP_MODE_NOFROST, + THERMOSTAT_TEMP_MODE_ECO, // 'sparen' + THERMOSTAT_TEMP_MODE_HEAT // 'heizen' +} _THERMOSTAT_TEMP_MODE; + +typedef enum { + EMS_THERMOSTAT_MODE_UNKNOWN, + EMS_THERMOSTAT_MODE_OFF, + EMS_THERMOSTAT_MODE_MANUAL, + EMS_THERMOSTAT_MODE_AUTO, + EMS_THERMOSTAT_MODE_NIGHT, + EMS_THERMOSTAT_MODE_DAY, + EMS_THERMOSTAT_MODE_ECO, + EMS_THERMOSTAT_MODE_COMFORT +} _EMS_THERMOSTAT_MODE; + // function definitions void ems_dumpBuffer(const char * prefix, uint8_t * telegram, uint8_t length); void ems_parseTelegram(uint8_t * telegram, uint8_t len); @@ -462,7 +474,7 @@ void ems_printTxQueue(); void ems_testTelegram(uint8_t test_num); void ems_startupTelegrams(); bool ems_checkEMSBUSAlive(); -void ems_setThermostatTemp(float temperature, uint8_t hc, uint8_t temptype = 0); +void ems_setThermostatTemp(float temperature, uint8_t hc, _THERMOSTAT_TEMP_MODE temptype = THERMOSTAT_TEMP_MODE_AUTO); void ems_setThermostatMode(uint8_t mode, uint8_t hc); void ems_setWarmWaterTemp(uint8_t temperature); void ems_setFlowTemp(uint8_t temperature); @@ -499,8 +511,8 @@ bool ems_getHeatPumpEnabled(); bool ems_getBusConnected(); _EMS_SYS_LOGGING ems_getLogging(); -uint8_t ems_getThermostatModel(); -uint8_t ems_getSolarModuleModel(); +uint8_t ems_getThermostatFlags(); +uint8_t ems_getSolarModuleFlags(); void ems_discoverModels(); bool ems_getTxCapable(); uint32_t ems_getPollFrequency(); diff --git a/src/ems_devices.h b/src/ems_devices.h index 1aeb2a16e..99d1b4992 100644 --- a/src/ems_devices.h +++ b/src/ems_devices.h @@ -177,25 +177,38 @@ #define EMS_OFFSET_RCPLUSSet_manual_setpoint 10 // manual setpoint // Junkers FR10, FR50, FW100, FW120 (EMS Plus) -#define EMS_TYPE_JunkersStatusMessage_HC1 0x6F // is an automatic thermostat broadcast giving us temps -#define EMS_TYPE_JunkersStatusMessage_HC2 0x70 // is an automatic thermostat broadcast giving us temps -#define EMS_TYPE_JunkersStatusMessage_HC3 0x71 // is an automatic thermostat broadcast giving us temps -#define EMS_TYPE_JunkersStatusMessage_HC4 0x72 // is an automatic thermostat broadcast giving us temps +// HC1 = 0x6F-0x72 +#define EMS_TYPE_JunkersStatusMessage_HC1 0x6F +#define EMS_TYPE_JunkersStatusMessage_HC2 0x70 +#define EMS_TYPE_JunkersStatusMessage_HC3 0x71 +#define EMS_TYPE_JunkersStatusMessage_HC4 0x72 #define EMS_OFFSET_JunkersStatusMessage_daymode 0 // 3 = day, 2 = night #define EMS_OFFSET_JunkersStatusMessage_mode 1 // current mode, 1 = manual, 2 = auto #define EMS_OFFSET_JunkersStatusMessage_setpoint 2 // setpoint temp #define EMS_OFFSET_JunkersStatusMessage_curr 4 // current temp -#define EMS_TYPE_JunkersSetMessage_HC1 0x65 // EMS type to set temperature on thermostat for heating circuit 1 -#define EMS_TYPE_JunkersSetMessage_HC2 0x66 // EMS type to set temperature on thermostat for heating circuit 2 -#define EMS_TYPE_JunkersSetMessage_HC3 0x67 // EMS type to set temperature on thermostat for heating circuit 3 -#define EMS_TYPE_JunkersSetMessage_HC4 0x68 // EMS type to set temperature on thermostat for heating circuit 4 +// HC1-4 0x65-0x68 - EMS_DEVICE_FLAG_JUNKERS_CONFIG1 +// Junkers FR10, FR50, FW100, FW120 +#define EMS_TYPE_JunkersSetMessage1_HC1 0x65 +#define EMS_TYPE_JunkersSetMessage1_HC2 0x66 +#define EMS_TYPE_JunkersSetMessage1_HC3 0x67 +#define EMS_TYPE_JunkersSetMessage1_HC4 0x68 #define EMS_OFFSET_JunkersSetMessage_day_temp 0x11 // EMS offset to set temperature on thermostat for day mode #define EMS_OFFSET_JunkersSetMessage_night_temp 0x10 // EMS offset to set temperature on thermostat for night mode #define EMS_OFFSET_JunkersSetMessage_no_frost_temp 0x0F // EMS offset to set temperature on thermostat for no frost mode #define EMS_OFFSET_JunkersSetMessage_set_mode 0x0E // EMS offset to set mode on thermostat +// HC1-4 0x79-0x7C - EMS_DEVICE_FLAG_JUNKERS_CONFIG2 +// Junkers FR100 +#define EMS_TYPE_JunkersSetMessage2_HC1 0x79 +#define EMS_TYPE_JunkersSetMessage2_HC2 0x7A +#define EMS_TYPE_JunkersSetMessage2_HC3 0x7B +#define EMS_TYPE_JunkersSetMessage2_HC4 0x7C +#define EMS_OFFSET_JunkersSetMessage2_no_frost_temp 0x05 +#define EMS_OFFSET_JunkersSetMessage2_eco_temp 0x06 +#define EMS_OFFSET_JunkersSetMessage3_heat 0x07 + /* * Table of all known EMS Devices * ProductID, DeviceType, Description, Flags @@ -289,14 +302,14 @@ static const _EMS_Device EMS_Devices[] = { {113, EMS_DEVICE_TYPE_THERMOSTAT, "Sieger ES72", EMS_DEVICE_FLAG_RC20}, // 0x17 // Junkers - all 0x10 - {105, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FW100", EMS_DEVICE_FLAG_JUNKERS}, // 0x10 - {106, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FW200", EMS_DEVICE_FLAG_JUNKERS}, // 0x10 - {107, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR100", EMS_DEVICE_FLAG_JUNKERS}, // 0x10 - {108, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR110", EMS_DEVICE_FLAG_JUNKERS}, // 0x10 - {111, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR10", EMS_DEVICE_FLAG_JUNKERS}, // 0x10 - {147, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR50", EMS_DEVICE_FLAG_JUNKERS}, // 0x10 - {191, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR120", EMS_DEVICE_FLAG_JUNKERS}, // 0x10 - {192, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FW120", EMS_DEVICE_FLAG_JUNKERS} // 0x10 + {105, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FW100", EMS_DEVICE_FLAG_JUNKERS | EMS_DEVICE_FLAG_JUNKERS_CONFIG1}, // 0x10 + {106, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FW200", EMS_DEVICE_FLAG_JUNKERS | EMS_DEVICE_FLAG_JUNKERS_CONFIG1}, // 0x10 + {107, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR100", EMS_DEVICE_FLAG_JUNKERS | EMS_DEVICE_FLAG_JUNKERS_CONFIG2}, // 0x10 + {108, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR110", EMS_DEVICE_FLAG_JUNKERS | EMS_DEVICE_FLAG_JUNKERS_CONFIG2}, // 0x10 + {111, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR10", EMS_DEVICE_FLAG_JUNKERS | EMS_DEVICE_FLAG_JUNKERS_CONFIG1}, // 0x10 + {147, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR50", EMS_DEVICE_FLAG_JUNKERS | EMS_DEVICE_FLAG_JUNKERS_CONFIG1}, // 0x10 + {191, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FR120", EMS_DEVICE_FLAG_JUNKERS | EMS_DEVICE_FLAG_JUNKERS_CONFIG1}, // 0x10 + {192, EMS_DEVICE_TYPE_THERMOSTAT, "Junkers FW120", EMS_DEVICE_FLAG_JUNKERS | EMS_DEVICE_FLAG_JUNKERS_CONFIG1} // 0x10 }; diff --git a/src/my_config.h b/src/my_config.h index 2c4e574a8..ccd09358f 100644 --- a/src/my_config.h +++ b/src/my_config.h @@ -27,6 +27,9 @@ #define TOPIC_THERMOSTAT_CMD_DAYTEMP "daytemp" // day temp (RC35 specific) #define TOPIC_THERMOSTAT_CMD_NIGHTTEMP "nighttemp" // night temp (RC35 specific) #define TOPIC_THERMOSTAT_CMD_HOLIDAYTEMP "holidayttemp" // holiday temp (RC35 specific) +#define TOPIC_THERMOSTAT_CMD_NOFROSTTEMP "nofrosttemp" // frost temp (Junkers specific) +#define TOPIC_THERMOSTAT_CMD_ECOTEMP "ecotemp" // eco temp (Junkers specific) +#define TOPIC_THERMOSTAT_CMD_HEATTEMP "heattemp" // heat temp (Junkers specific) #define THERMOSTAT_CURRTEMP "currtemp" // current temperature #define THERMOSTAT_SELTEMP "seltemp" // selected temperature diff --git a/src/version.h b/src/version.h index 1898ef6d0..d01d75c46 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define APP_VERSION "1.9.5b47" +#define APP_VERSION "1.9.5b48"