mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
MQTT support for handling multiple Heating Circuits
This commit is contained in:
@@ -353,8 +353,10 @@ void MyESP::_mqttOnMessage(char * topic, char * payload, size_t len) {
|
|||||||
// MQTT subscribe
|
// MQTT subscribe
|
||||||
void MyESP::mqttSubscribe(const char * topic) {
|
void MyESP::mqttSubscribe(const char * topic) {
|
||||||
if (mqttClient.connected() && (strlen(topic) > 0)) {
|
if (mqttClient.connected() && (strlen(topic) > 0)) {
|
||||||
char topic_s[MQTT_MAX_TOPIC_SIZE];
|
char * topic_s = _mqttTopic(topic);
|
||||||
strlcpy(topic_s, _mqttTopic(topic), sizeof(topic_s));
|
|
||||||
|
//char topic_s[MQTT_MAX_TOPIC_SIZE];
|
||||||
|
//strlcpy(topic_s, _mqttTopic(topic), sizeof(topic_s));
|
||||||
(void)mqttClient.subscribe(topic_s, _mqtt_qos);
|
(void)mqttClient.subscribe(topic_s, _mqtt_qos);
|
||||||
myDebug_P(PSTR("[MQTT] Subscribing to %s"), topic_s);
|
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_port=%d"), _mqtt_port);
|
||||||
myDebug_P(PSTR(" mqtt_heartbeat=%s"), (_mqtt_heartbeat) ? "on" : "off");
|
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");
|
myDebug_P(PSTR(" serial=%s"), (_general_serial) ? "on" : "off");
|
||||||
|
#endif
|
||||||
myDebug_P(PSTR(" ntp_enabled=%s"), (_ntp_enabled) ? "on" : "off");
|
myDebug_P(PSTR(" ntp_enabled=%s"), (_ntp_enabled) ? "on" : "off");
|
||||||
|
|
||||||
// print any custom settings
|
// print any custom settings
|
||||||
|
|||||||
@@ -1584,6 +1584,32 @@ void OTACallback_post() {
|
|||||||
emsuart_start();
|
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
|
// MQTT Callback to handle incoming/outgoing changes
|
||||||
void MQTTCallback(unsigned int type, const char * topic, const char * message) {
|
void MQTTCallback(unsigned int type, const char * topic, const char * message) {
|
||||||
// we're connected. lets subscribe to some topics
|
// 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
|
// handle incoming MQTT publish events
|
||||||
if (type == MQTT_MESSAGE_EVENT) {
|
if (type == MQTT_MESSAGE_EVENT) {
|
||||||
|
uint8_t hc;
|
||||||
// thermostat temp changes
|
// 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);
|
float f = strtof((char *)message, 0);
|
||||||
char s[10] = {0};
|
char s[10] = {0};
|
||||||
myDebug_P(PSTR("MQTT topic: thermostat temperature value %s"), _float_to_char(s, f));
|
myDebug_P(PSTR("MQTT topic: thermostat HC%d temperature value %s"), hc, _float_to_char(s, f));
|
||||||
ems_setThermostatTemp(f, EMS_THERMOSTAT_DEFAULTHC);
|
ems_setThermostatTemp(f, hc);
|
||||||
publishValues(true); // publish back immediately, can't remember why I do this?!
|
publishValues(true); // publish back immediately
|
||||||
}
|
}
|
||||||
|
|
||||||
// thermostat mode changes
|
// thermostat mode changes
|
||||||
if (strcmp(topic, TOPIC_THERMOSTAT_CMD_MODE) == 0) {
|
hc = _hasHCspecified(TOPIC_THERMOSTAT_CMD_MODE, topic);
|
||||||
myDebug_P(PSTR("MQTT topic: thermostat mode value %s"), message);
|
if (hc) {
|
||||||
|
myDebug_P(PSTR("MQTT topic: thermostat HC%d mode value %s"), hc, message);
|
||||||
if (strcmp((char *)message, "auto") == 0) {
|
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) {
|
} 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) {
|
} 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
|
// 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);
|
float f = strtof((char *)message, 0);
|
||||||
char s[10] = {0};
|
char s[10] = {0};
|
||||||
myDebug_P(PSTR("MQTT topic: new thermostat night temperature value %s"), _float_to_char(s, f));
|
myDebug_P(PSTR("MQTT topic: new thermostat HC%d night temperature value %s"), hc, _float_to_char(s, f));
|
||||||
ems_setThermostatTemp(f, EMS_THERMOSTAT_DEFAULTHC, 1);
|
ems_setThermostatTemp(f, hc, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set daytemp value
|
// 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);
|
float f = strtof((char *)message, 0);
|
||||||
char s[10] = {0};
|
char s[10] = {0};
|
||||||
myDebug_P(PSTR("MQTT topic: new thermostat day temperature value %s"), _float_to_char(s, f));
|
myDebug_P(PSTR("MQTT topic: new thermostat HC%d day temperature value %s"), hc, _float_to_char(s, f));
|
||||||
ems_setThermostatTemp(f, EMS_THERMOSTAT_DEFAULTHC, 2);
|
ems_setThermostatTemp(f, hc, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set holiday value
|
// 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);
|
float f = strtof((char *)message, 0);
|
||||||
char s[10] = {0};
|
char s[10] = {0};
|
||||||
myDebug_P(PSTR("MQTT topic: new thermostat holiday temperature value %s"), _float_to_char(s, f));
|
myDebug_P(PSTR("MQTT topic: new thermostat HC%d holiday temperature value %s"), hc, _float_to_char(s, f));
|
||||||
ems_setThermostatTemp(f, EMS_THERMOSTAT_DEFAULTHC, 3);
|
ems_setThermostatTemp(f, hc, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wwActivated
|
// wwActivated
|
||||||
@@ -1752,6 +1784,7 @@ void WebCallback(JsonObject root) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send over EMS devices
|
||||||
JsonArray list = emsbus.createNestedArray("devices");
|
JsonArray list = emsbus.createNestedArray("devices");
|
||||||
|
|
||||||
for (std::list<_Generic_Device>::iterator it = Devices.begin(); it != Devices.end(); it++) {
|
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;
|
item["productid"] = (it)->product_id;
|
||||||
|
|
||||||
char s[10];
|
char s[10];
|
||||||
itoa((it)->device_id, s, 16);
|
itoa((it)->device_id, s, 16); // convert to hex
|
||||||
item["deviceid"] = s; // convert to hex
|
item["deviceid"] = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send over Thermostat data
|
||||||
JsonObject thermostat = root.createNestedObject("thermostat");
|
JsonObject thermostat = root.createNestedObject("thermostat");
|
||||||
|
|
||||||
if (ems_getThermostatEnabled()) {
|
if (ems_getThermostatEnabled()) {
|
||||||
@@ -1774,7 +1808,6 @@ void WebCallback(JsonObject root) {
|
|||||||
char buffer[200];
|
char buffer[200];
|
||||||
thermostat["tm"] = ems_getThermostatDescription(buffer, true);
|
thermostat["tm"] = ems_getThermostatDescription(buffer, true);
|
||||||
|
|
||||||
// TODO: enable support multiple HCs
|
|
||||||
uint8_t hc_num = EMS_THERMOSTAT_DEFAULTHC; // default to HC1
|
uint8_t hc_num = EMS_THERMOSTAT_DEFAULTHC; // default to HC1
|
||||||
|
|
||||||
// Render Current & Setpoint Room Temperature
|
// 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
|
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
|
systemCheckTimer.attach(SYSTEMCHECK_TIME, do_systemCheck); // check if EMS is reachable
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -2561,6 +2561,7 @@ void ems_sendRawTelegram(char * telegram) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the temperature of the thermostat
|
* Set the temperature of the thermostat
|
||||||
|
* hc_num is 1 to 4
|
||||||
* temptype 0 = normal, 1=night temp, 2=day temp, 3=holiday temp
|
* 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, uint8_t temptype) {
|
||||||
|
|||||||
@@ -10,14 +10,19 @@
|
|||||||
|
|
||||||
#include "ems.h"
|
#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
|
// MQTT for thermostat
|
||||||
#define TOPIC_THERMOSTAT_DATA "thermostat_data" // for sending thermostat values to MQTT
|
#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
|
// these topics can be suffixed with a Heating Circuit number, e.g. thermostat_cmd_temp1
|
||||||
#define TOPIC_THERMOSTAT_CMD_HC "thermostat_cmd_hc" // for received thermostat hc number changes via MQTT
|
#define TOPIC_THERMOSTAT_CMD_TEMP "thermostat_cmd_temp" // temp changes via MQTT
|
||||||
#define TOPIC_THERMOSTAT_CMD_DAYTEMP "thermostat_daytemp" // for received thermostat day temp (RC35 specific)
|
#define TOPIC_THERMOSTAT_CMD_MODE "thermostat_cmd_mode" // mode changes via MQTT
|
||||||
#define TOPIC_THERMOSTAT_CMD_NIGHTTEMP "thermostat_nighttemp" // for received thermostat night temp (RC35 specific)
|
#define TOPIC_THERMOSTAT_CMD_HC "thermostat_cmd_hc" // hc number changes via MQTT
|
||||||
#define TOPIC_THERMOSTAT_CMD_HOLIDAYTEMP "thermostat_holidayttemp" // for received thermostat holiday temp (RC35 specific)
|
#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_CURRTEMP "thermostat_currtemp" // current temperature
|
||||||
#define THERMOSTAT_SELTEMP "thermostat_seltemp" // selected temperature
|
#define THERMOSTAT_SELTEMP "thermostat_seltemp" // selected temperature
|
||||||
#define THERMOSTAT_HC "thermostat_hc" // which heating circuit number
|
#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_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_TAPWATER_ACTIVE "tapwater_active" // if hot tap water is running
|
||||||
#define TOPIC_BOILER_HEATING_ACTIVE "heating_active" // if heating is on
|
#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_WWACTIVATED "boiler_cmd_wwactivated" // change water on/off
|
||||||
#define TOPIC_BOILER_CMD_WWTEMP "boiler_cmd_wwtemp" // for received boiler wwtemp changes via MQTT
|
#define TOPIC_BOILER_CMD_WWTEMP "boiler_cmd_wwtemp" // wwtemp changes via MQTT
|
||||||
#define TOPIC_BOILER_CMD_COMFORT "boiler_cmd_comfort" // for received boiler ww comfort setting via MQTT
|
#define TOPIC_BOILER_CMD_COMFORT "boiler_cmd_comfort" // ww comfort setting via MQTT
|
||||||
#define TOPIC_BOILER_CMD_FLOWTEMP "boiler_cmd_flowtemp" // for received boiler flowtemp value via MQTT
|
#define TOPIC_BOILER_CMD_FLOWTEMP "boiler_cmd_flowtemp" // flowtemp value via MQTT
|
||||||
|
|
||||||
// MQTT for SM10/SM100 Solar Module
|
// MQTT for SM10/SM100 Solar Module
|
||||||
#define TOPIC_SM_DATA "sm_data" // topic name
|
#define TOPIC_SM_DATA "sm_data" // topic name
|
||||||
|
|||||||
Reference in New Issue
Block a user