diff --git a/src/MyESP.cpp b/src/MyESP.cpp index f94fedecd..562eb81e5 100644 --- a/src/MyESP.cpp +++ b/src/MyESP.cpp @@ -353,8 +353,10 @@ void MyESP::_mqttOnMessage(char * topic, char * payload, size_t len) { // MQTT subscribe void MyESP::mqttSubscribe(const char * topic) { if (mqttClient.connected() && (strlen(topic) > 0)) { - char topic_s[MQTT_MAX_TOPIC_SIZE]; - strlcpy(topic_s, _mqttTopic(topic), sizeof(topic_s)); + char * topic_s = _mqttTopic(topic); + + //char topic_s[MQTT_MAX_TOPIC_SIZE]; + //strlcpy(topic_s, _mqttTopic(topic), sizeof(topic_s)); (void)mqttClient.subscribe(topic_s, _mqtt_qos); myDebug_P(PSTR("[MQTT] Subscribing to %s"), topic_s); @@ -702,7 +704,11 @@ void MyESP::_printSetCommands() { myDebug_P(PSTR(" mqtt_port=%d"), _mqtt_port); myDebug_P(PSTR(" mqtt_heartbeat=%s"), (_mqtt_heartbeat) ? "on" : "off"); +#ifdef FORCE_SERIAL + myDebug_P(PSTR(" serial=%s (this is always when compiled with -DFORCE_SERIAL)"), (_general_serial) ? "on" : "off"); +#else myDebug_P(PSTR(" serial=%s"), (_general_serial) ? "on" : "off"); +#endif myDebug_P(PSTR(" ntp_enabled=%s"), (_ntp_enabled) ? "on" : "off"); // print any custom settings diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index 3733719e3..d5191c557 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -1584,6 +1584,32 @@ void OTACallback_post() { emsuart_start(); } + +// see's if a topic is appended with an interger value +// used to identify a heating circuit +// returns HC number +uint8_t _hasHCspecified(const char * topic, const char * input) { + int orig_len = strlen(topic); // original length of the topic we're comparing too + + // check if the strings match ignoring any suffix + if (strncmp(input, topic, orig_len) == 0) { + // see if we have additional chars at the end, we want none or 1 + uint8_t diff = (strlen(input) - orig_len); + if (diff > 1) { + return 0; // invalid + } + + if (diff == 0) { + return EMS_THERMOSTAT_DEFAULTHC; // identical, use default + } + + // return the value of the last char + return input[orig_len] - '0'; + } + + return 0; // invalid +} + // MQTT Callback to handle incoming/outgoing changes void MQTTCallback(unsigned int type, const char * topic, const char * message) { // we're connected. lets subscribe to some topics @@ -1611,49 +1637,55 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) { // handle incoming MQTT publish events if (type == MQTT_MESSAGE_EVENT) { + uint8_t hc; // thermostat temp changes - if (strcmp(topic, TOPIC_THERMOSTAT_CMD_TEMP) == 0) { + hc = _hasHCspecified(TOPIC_THERMOSTAT_CMD_TEMP, topic); + if (hc) { float f = strtof((char *)message, 0); char s[10] = {0}; - myDebug_P(PSTR("MQTT topic: thermostat temperature value %s"), _float_to_char(s, f)); - ems_setThermostatTemp(f, EMS_THERMOSTAT_DEFAULTHC); - publishValues(true); // publish back immediately, can't remember why I do this?! + myDebug_P(PSTR("MQTT topic: thermostat HC%d temperature value %s"), hc, _float_to_char(s, f)); + ems_setThermostatTemp(f, hc); + publishValues(true); // publish back immediately } // thermostat mode changes - if (strcmp(topic, TOPIC_THERMOSTAT_CMD_MODE) == 0) { - myDebug_P(PSTR("MQTT topic: thermostat mode value %s"), message); + hc = _hasHCspecified(TOPIC_THERMOSTAT_CMD_MODE, topic); + if (hc) { + myDebug_P(PSTR("MQTT topic: thermostat HC%d mode value %s"), hc, message); if (strcmp((char *)message, "auto") == 0) { - ems_setThermostatMode(2, EMS_THERMOSTAT_DEFAULTHC); + ems_setThermostatMode(2, hc); } else if (strcmp((char *)message, "day") == 0 || strcmp((char *)message, "manual") == 0) { - ems_setThermostatMode(1, EMS_THERMOSTAT_DEFAULTHC); + ems_setThermostatMode(1, hc); } else if (strcmp((char *)message, "night") == 0 || strcmp((char *)message, "off") == 0) { - ems_setThermostatMode(0, EMS_THERMOSTAT_DEFAULTHC); + ems_setThermostatMode(0, hc); } } // set night temp value - if (strcmp(topic, TOPIC_THERMOSTAT_CMD_NIGHTTEMP) == 0) { + hc = _hasHCspecified(TOPIC_THERMOSTAT_CMD_NIGHTTEMP, topic); + if (hc) { float f = strtof((char *)message, 0); char s[10] = {0}; - myDebug_P(PSTR("MQTT topic: new thermostat night temperature value %s"), _float_to_char(s, f)); - ems_setThermostatTemp(f, EMS_THERMOSTAT_DEFAULTHC, 1); + myDebug_P(PSTR("MQTT topic: new thermostat HC%d night temperature value %s"), hc, _float_to_char(s, f)); + ems_setThermostatTemp(f, hc, 1); } // set daytemp value - if (strcmp(topic, TOPIC_THERMOSTAT_CMD_DAYTEMP) == 0) { + hc = _hasHCspecified(TOPIC_THERMOSTAT_CMD_DAYTEMP, topic); + if (hc) { float f = strtof((char *)message, 0); char s[10] = {0}; - myDebug_P(PSTR("MQTT topic: new thermostat day temperature value %s"), _float_to_char(s, f)); - ems_setThermostatTemp(f, EMS_THERMOSTAT_DEFAULTHC, 2); + myDebug_P(PSTR("MQTT topic: new thermostat HC%d day temperature value %s"), hc, _float_to_char(s, f)); + ems_setThermostatTemp(f, hc, 2); } // set holiday value - if (strcmp(topic, TOPIC_THERMOSTAT_CMD_HOLIDAYTEMP) == 0) { + hc = _hasHCspecified(TOPIC_THERMOSTAT_CMD_HOLIDAYTEMP, topic); + if (hc) { float f = strtof((char *)message, 0); char s[10] = {0}; - myDebug_P(PSTR("MQTT topic: new thermostat holiday temperature value %s"), _float_to_char(s, f)); - ems_setThermostatTemp(f, EMS_THERMOSTAT_DEFAULTHC, 3); + myDebug_P(PSTR("MQTT topic: new thermostat HC%d holiday temperature value %s"), hc, _float_to_char(s, f)); + ems_setThermostatTemp(f, hc, 3); } // wwActivated @@ -1752,6 +1784,7 @@ void WebCallback(JsonObject root) { } } + // send over EMS devices JsonArray list = emsbus.createNestedArray("devices"); for (std::list<_Generic_Device>::iterator it = Devices.begin(); it != Devices.end(); it++) { @@ -1762,10 +1795,11 @@ void WebCallback(JsonObject root) { item["productid"] = (it)->product_id; char s[10]; - itoa((it)->device_id, s, 16); - item["deviceid"] = s; // convert to hex + itoa((it)->device_id, s, 16); // convert to hex + item["deviceid"] = s; } + // send over Thermostat data JsonObject thermostat = root.createNestedObject("thermostat"); if (ems_getThermostatEnabled()) { @@ -1774,7 +1808,6 @@ void WebCallback(JsonObject root) { char buffer[200]; thermostat["tm"] = ems_getThermostatDescription(buffer, true); - // TODO: enable support multiple HCs uint8_t hc_num = EMS_THERMOSTAT_DEFAULTHC; // default to HC1 // Render Current & Setpoint Room Temperature @@ -2047,6 +2080,7 @@ void setup() { EMSESP_Settings.dallas_sensors = ds18.setup(EMSESP_Settings.dallas_gpio, EMSESP_Settings.dallas_parasite); // returns #sensors systemCheckTimer.attach(SYSTEMCHECK_TIME, do_systemCheck); // check if EMS is reachable + } // diff --git a/src/ems.cpp b/src/ems.cpp index d26010d2e..cb3667752 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -2561,6 +2561,7 @@ void ems_sendRawTelegram(char * telegram) { /** * Set the temperature of the thermostat + * 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) { diff --git a/src/my_config.h b/src/my_config.h index 15f06b4d2..8d1a9f144 100644 --- a/src/my_config.h +++ b/src/my_config.h @@ -10,14 +10,19 @@ #include "ems.h" +// TOPICS with _CMD_ are used for receiving commands from an MQTT Broker +// EMS-ESP will subscribe to these topics + // MQTT for thermostat #define TOPIC_THERMOSTAT_DATA "thermostat_data" // for sending thermostat values to MQTT -#define TOPIC_THERMOSTAT_CMD_TEMP "thermostat_cmd_temp" // for received thermostat temp changes via MQTT -#define TOPIC_THERMOSTAT_CMD_MODE "thermostat_cmd_mode" // for received thermostat mode changes via MQTT -#define TOPIC_THERMOSTAT_CMD_HC "thermostat_cmd_hc" // for received thermostat hc number changes via MQTT -#define TOPIC_THERMOSTAT_CMD_DAYTEMP "thermostat_daytemp" // for received thermostat day temp (RC35 specific) -#define TOPIC_THERMOSTAT_CMD_NIGHTTEMP "thermostat_nighttemp" // for received thermostat night temp (RC35 specific) -#define TOPIC_THERMOSTAT_CMD_HOLIDAYTEMP "thermostat_holidayttemp" // for received thermostat holiday temp (RC35 specific) + +// these topics can be suffixed with a Heating Circuit number, e.g. thermostat_cmd_temp1 +#define TOPIC_THERMOSTAT_CMD_TEMP "thermostat_cmd_temp" // temp changes via MQTT +#define TOPIC_THERMOSTAT_CMD_MODE "thermostat_cmd_mode" // mode changes via MQTT +#define TOPIC_THERMOSTAT_CMD_HC "thermostat_cmd_hc" // hc number changes via MQTT +#define TOPIC_THERMOSTAT_CMD_DAYTEMP "thermostat_daytemp" // day temp (RC35 specific) +#define TOPIC_THERMOSTAT_CMD_NIGHTTEMP "thermostat_nighttemp" // night temp (RC35 specific) +#define TOPIC_THERMOSTAT_CMD_HOLIDAYTEMP "thermostat_holidayttemp" // holiday temp (RC35 specific) #define THERMOSTAT_CURRTEMP "thermostat_currtemp" // current temperature #define THERMOSTAT_SELTEMP "thermostat_seltemp" // selected temperature #define THERMOSTAT_HC "thermostat_hc" // which heating circuit number @@ -32,10 +37,10 @@ #define TOPIC_BOILER_DATA "boiler_data" // for sending boiler values to MQTT #define TOPIC_BOILER_TAPWATER_ACTIVE "tapwater_active" // if hot tap water is running #define TOPIC_BOILER_HEATING_ACTIVE "heating_active" // if heating is on -#define TOPIC_BOILER_CMD_WWACTIVATED "boiler_cmd_wwactivated" // for received message to change water on/off -#define TOPIC_BOILER_CMD_WWTEMP "boiler_cmd_wwtemp" // for received boiler wwtemp changes via MQTT -#define TOPIC_BOILER_CMD_COMFORT "boiler_cmd_comfort" // for received boiler ww comfort setting via MQTT -#define TOPIC_BOILER_CMD_FLOWTEMP "boiler_cmd_flowtemp" // for received boiler flowtemp value via MQTT +#define TOPIC_BOILER_CMD_WWACTIVATED "boiler_cmd_wwactivated" // change water on/off +#define TOPIC_BOILER_CMD_WWTEMP "boiler_cmd_wwtemp" // wwtemp changes via MQTT +#define TOPIC_BOILER_CMD_COMFORT "boiler_cmd_comfort" // ww comfort setting via MQTT +#define TOPIC_BOILER_CMD_FLOWTEMP "boiler_cmd_flowtemp" // flowtemp value via MQTT // MQTT for SM10/SM100 Solar Module #define TOPIC_SM_DATA "sm_data" // topic name