Skip to content

Commit 70ef308

Browse files
authored
Merge pull request #629 from IgorYbema/main
release v3.9
2 parents 5ab2a40 + 2cb132e commit 70ef308

28 files changed

+1207
-601
lines changed

.github/workflows/main.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@ jobs:
1111

1212
steps:
1313
- name: Checkout
14-
uses: actions/checkout@v3
14+
uses: actions/checkout@v4
1515

1616
- name: Update version.h
1717
if: github.ref != 'refs/heads/main' #do not change version in main branch run
1818
run: cd HeishaMon && echo "static const char *heishamon_version = \"Alpha-$(git rev-parse --short HEAD)\";" > version.h && cat version.h
1919
shell: bash
2020

2121
- name: Setup Arduino CLI
22-
uses: arduino/setup-arduino-cli@v1.1.1
22+
uses: arduino/setup-arduino-cli@v2
2323

2424
- name: Install platform
2525
run: |
2626
arduino-cli core update-index
2727
arduino-cli core install esp8266:esp8266
28-
arduino-cli core install esp32:esp32
28+
arduino-cli core install esp32:esp32@3.0.7
2929
3030
- name: Install dependencies
3131
run: arduino-cli lib install ringbuffer pubsubclient arduinojson dallastemperature onewire "Adafruit NeoPixel"
@@ -48,10 +48,10 @@ jobs:
4848

4949
- name: Add MD5 checksum to ESP32 binary
5050
run: cd HeishaMon && MD5=`md5sum HeishaMon.ino.bin | cut -d\ -f1` && mv HeishaMon.ino.bin HeishaMon_ESP32-alpha-$MD5.bin
51-
shell: bash
51+
shell: bash
5252

5353
- name: Upload artifacts
54-
uses: actions/upload-artifact@v2
54+
uses: actions/upload-artifact@v4
5555
with:
5656
name: HeishaMon.ino.bin
57-
path: HeishaMon/HeishaMon_*.bin
57+
path: HeishaMon/HeishaMon_*.bin

HeatPumpType.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Assuming that bytes from #129 to #138 are unique for each model of Aquarea heat
3333
|26 | 42 D4 0B 83 71 42 D2 0C 46 55 | WH-ADC0309J3E5C | WH-UD07JE5 | KIT-ADC07JE5C | 7 | 1ph | HP - All-In-One Compact |
3434
|27 | C2 D3 0C 34 65 B2 D3 0B 95 65 | Monoblock | WH-MDC07J3E5 | Monoblock | 7 | 1ph | HP (new version?) |
3535
|28 | C2 D3 0C 33 65 B2 D3 0B 94 65 | Monoblock | WH-MDC05J3E5 | Monoblock | 5 | 1ph | HP (new version) |
36-
|29 | E2 CF 0B 83 05 12 D0 0D 92 05 | WH-UQ12HE8 | WH-SQC12H9E8 | KIT-WQC12H9E8 | 12 | 3ph | T-CAP - Super Quiet |
36+
|29 | E2 CF 0B 83 05 12 D0 0D 92 05 | WH-SQC12H9E8 | WH-UQ12HE8 | KIT-WQC12H9E8 | 12 | 3ph | T-CAP - Super Quiet |
3737
|30 | E2 CF 0C 78 09 12 D0 0B 06 11 | WH-SXC12H6E5 | WH-UX12HE5 | KIT-WXC12H6E5 | 12 | 1ph | T-CAP |
3838
|31 | C2 D3 0C 35 65 B2 D3 0B 96 65 | Monoblock | WH-MDC09J3E5 | Monoblock | 9 | 1ph | HP (new version?) |
3939
|32 | 32 D4 0B 99 77 62 90 0B 01 78 | Monoblock | WH-MXC09J3E5 | Monoblock | 9 | 1ph | T-CAP

HeishaMon/HeishaMon.ino

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ static uint8_t cmdnrel = 0;
135135
WiFiClient mqtt_wifi_client;
136136
PubSubClient mqtt_client;
137137

138+
139+
138140
bool firstConnectSinceBoot = true; //if this is true there is no first connection made yet
139141

140142
struct timerqueue_t **timerqueue = NULL;
@@ -195,12 +197,15 @@ void check_wifi() {
195197
*/
196198
#ifdef ESP8266
197199
if ((heishamonSettings.wifi_ssid[0] != '\0') && (wifistatus != WL_DISCONNECTED) && (WiFi.scanComplete() != -1) && (WiFi.softAPgetStationNum() > 0)) {
200+
log_message(_F("WiFi lost, but softAP station connecting, so stop trying to connect to configured ssid..."));
201+
WiFi.disconnect(true);
202+
}
198203
#else
199204
if ((heishamonSettings.wifi_ssid[0] != '\0') && (wifistatus != WL_STOPPED) && (WiFi.scanComplete() != -1) && (WiFi.softAPgetStationNum() > 0)) {
200-
#endif
201205
log_message(_F("WiFi lost, but softAP station connecting, so stop trying to connect to configured ssid..."));
202-
WiFi.disconnect(true);
206+
WiFi.mode(WIFI_AP);
203207
}
208+
#endif
204209

205210
/* only start this routine if timeout on
206211
reconnecting to AP and SSID is set
@@ -221,22 +226,19 @@ void check_wifi() {
221226
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
222227
WiFi.softAP(_F("HeishaMon-Setup"));
223228
}
224-
if ((wifistatus == WL_STOPPED) && (WiFi.softAPgetStationNum() == 0)) {
229+
if ((wifistatus == WL_STOPPED ) && (WiFi.softAPgetStationNum() == 0)) { //make sure we start STA again if it was stopped
225230
log_message(_F("Retrying configured WiFi, ..."));
231+
WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); //select best AP with same SSID
226232
#endif
227233
if (heishamonSettings.wifi_password[0] == '\0') {
228234
WiFi.begin(heishamonSettings.wifi_ssid);
229235
} else {
230236
WiFi.begin(heishamonSettings.wifi_ssid, heishamonSettings.wifi_password);
231237
}
238+
#ifdef ESP8266
232239
} else {
233240
log_message(_F("Reconnecting to WiFi failed. Waiting a few seconds before trying again."));
234-
#ifdef ESP8266
235-
WiFi.disconnect(true);
236-
#else
237-
WiFi.mode(WIFI_MODE_APSTA);
238241
WiFi.disconnect(true);
239-
WiFi.mode(WIFI_MODE_AP);
240242
#endif
241243
}
242244
}
@@ -354,11 +356,10 @@ void mqtt_reconnect()
354356
resetlastalldatatime(); //resend all heatpump values to mqtt
355357
}
356358
//use this to receive valid heishamon raw data from other heishamon to debug this OT code
357-
#define OTDEBUG
358-
#ifdef OTDEBUG
359-
if ( heishamonSettings.listenonly && heishamonSettings.listenmqtt ) {
360-
sprintf(topic, "%s/raw/data", heishamonSettings.mqtt_topic_listen);
361-
mqtt_client.subscribe(topic); //subscribe to raw heatpump data over MQTT
359+
//#define RAWDEBUG
360+
#ifdef RAWDEBUG
361+
if ( heishamonSettings.listenonly) {
362+
mqtt_client.subscribe((char*)"panasonic_heat_pump/raw/data"); //subscribe to raw heatpump data over MQTT
362363
}
363364
#endif
364365
}
@@ -387,7 +388,7 @@ void log_message(char* string)
387388
struct tm *timeinfo = localtime(&rawtime);
388389
char timestring[32];
389390
strftime(timestring, 32, "%c", timeinfo);
390-
size_t len = strlen(string) + strlen(timestring) + 20; //+20 long enough to contain millis()
391+
size_t len = strlen(string) + strlen(timestring) + 32; //+32 long enough to contain millis() and the json part later for websocket mesg
391392
char* log_line = (char *) malloc(len);
392393
snprintf(log_line, len, "%s (%lu): %s", timestring, millis(), string);
393394

@@ -408,11 +409,10 @@ void log_message(char* string)
408409
mqtt_client.disconnect();
409410
}
410411
}
411-
char* websocketMsg = (char *) malloc(len+12);
412-
snprintf(websocketMsg, len+12, "{\"logMsg\":\"%s\"}", log_line);
412+
//send log message to websocket
413+
snprintf(log_line, len+12, "{\"logMsg\":\"%s (%lu): %s\"}", timestring, millis(), string);
414+
websocket_write_all(log_line, strlen(log_line));
413415
free(log_line);
414-
websocket_write_all(websocketMsg, strlen(websocketMsg));
415-
free(websocketMsg);
416416
#ifdef ESP32
417417
if (!inSetup) blinkNeoPixel(false);
418418
#endif
@@ -707,10 +707,9 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
707707
{
708708
char* topic_sendcommand = topic_command + strlen(mqtt_topic_commands) + 1; //strip the first 9 "commands/" from the topic to get what we need
709709
send_heatpump_command(topic_sendcommand, msg, send_command, log_message, heishamonSettings.optionalPCB);
710-
}
711710
//use this to receive valid heishamon raw data from other heishamon to debug this OT code
712-
#ifdef OTDEBUG
713-
else if (strcmp((char*)"panasonic_heat_pump/data", topic) == 0) { // check for raw heatpump input
711+
#ifdef RAWDEBUG
712+
} else if (strcmp((char*)"panasonic_heat_pump/raw/data", topic) == 0) { // check for raw heatpump input
714713
sprintf_P(log_msg, PSTR("Received raw heatpump data from MQTT"));
715714
log_message(log_msg);
716715
decode_heatpump_data(msg, actData, mqtt_client, log_message, heishamonSettings.mqtt_topic_base, heishamonSettings.updateAllTime);
@@ -750,7 +749,11 @@ void setupOTA() {
750749
ArduinoOTA.begin();
751750
}
752751

752+
753+
753754
int8_t webserver_cb(struct webserver_t *client, void *dat) {
755+
756+
754757
switch (client->step) {
755758
case WEBSERVER_CLIENT_REQUEST_METHOD: {
756759
if (strcmp_P((char *)dat, PSTR("POST")) == 0) {
@@ -1172,8 +1175,6 @@ void factoryReset() {
11721175
yield();
11731176
}
11741177
#else
1175-
pixels.begin();
1176-
pixels.clear();
11771178
while (true) {
11781179
delay(100);
11791180
pixels.setPixelColor(0, 128, 0, 0);
@@ -1414,8 +1415,6 @@ void setup() {
14141415
yield();
14151416
}
14161417
#else
1417-
pixels.begin();
1418-
pixels.clear();
14191418
while (true) {
14201419
delay(50);
14211420
pixels.setPixelColor(0, 128, 0, 0);
@@ -1486,16 +1485,21 @@ void setup() {
14861485
}
14871486

14881487
loggingSerial.println(F("Enabling rules.."));
1488+
if (heishamonSettings.force_rules == false) {
14891489
#if defined(ESP8266)
14901490
rst_info *resetInfo = ESP.getResetInfoPtr();
14911491
loggingSerial.printf(PSTR("Reset reason: %d, exception cause: %d\n"), resetInfo->reason, resetInfo->exccause);
1492-
if (resetInfo->reason > 0 && resetInfo->reason < 4) {
1492+
if (resetInfo->reason > 0 && resetInfo->reason < 4) {
14931493
#elif defined(ESP32)
1494-
esp_reset_reason_t reset_reason = esp_reset_reason();
1495-
loggingSerial.printf(PSTR("Reset reason: %d\n"), reset_reason);
1496-
if (reset_reason > 3 && reset_reason < 12) { //is this correct for esp32?
1494+
esp_reset_reason_t reset_reason = esp_reset_reason();
1495+
loggingSerial.printf(PSTR("Reset reason: %d\n"), reset_reason);
1496+
if (reset_reason > 3 && reset_reason < 12) { //is this correct for esp32?
14971497
#endif
1498-
loggingSerial.println("Not loading rules due to crash reboot!");
1498+
loggingSerial.println("Not loading rules due to crash reboot!");
1499+
} else {
1500+
rules_parse((char *)"/rules.txt");
1501+
rules_boot();
1502+
}
14991503
} else {
15001504
rules_parse((char *)"/rules.txt");
15011505
rules_boot();
@@ -1532,8 +1536,8 @@ void send_panasonic_query() {
15321536
send_command(panasonicQuery, PANASONICQUERYSIZE);
15331537
panasonicQuery[3] = 0x10; //setting 4th back to 0x10 for normal data request next time
15341538
} else {
1535-
if ((actData[0] == 0x71) && (actData[1] == 0xc8) && (actData[2] == 0x01) && (actData[193] == 0) && (actData[195] == 0) && (actData[197] == 0) ) { //do we have valid data but 0 value in heat consumptiom power, then assume K or L series
1536-
//can be replaced with: if ((actData[0] == 0x71) && (actData[0xc7] >= 3) ) { //do we have valid header and byte 0xc7 is more or equal 3 then assume K&L series
1539+
//if ((actData[0] == 0x71) && (actData[1] == 0xc8) && (actData[2] == 0x01) && (actData[193] == 0) && (actData[195] == 0) && (actData[197] == 0) ) { //do we have valid data but 0 value in heat consumptiom power, then assume K or L series
1540+
if ((actData[0] == 0x71) && (actData[0xc7] >= 3) ) { //do we have valid header and byte 0xc7 is more or equal 3 then assume K&L and more series
15371541
log_message(_F("Assuming K or L heatpump type due to missing heat/cool/dhw power data"));
15381542
extraDataBlockAvailable = true; //request for extra data next run
15391543
}
@@ -1584,7 +1588,7 @@ void loop() {
15841588

15851589
// check wifi
15861590
check_wifi();
1587-
// Handle OTA first.
1591+
// Handle OTA first.s
15881592
ArduinoOTA.handle();
15891593

15901594
mqtt_client.loop();
@@ -1728,12 +1732,48 @@ void loop() {
17281732
stats += timeoutread;
17291733
stats += F(",\"version\":\"");
17301734
stats += heishamon_version;
1735+
stats += F("\",\"board\":\"");
1736+
#ifdef ESP8266
1737+
stats += F("ESP8266");
1738+
#else
1739+
stats += F("ESP32");
1740+
#endif
17311741
stats += F("\",\"rules active\":");
17321742
stats += nrrules;
17331743
stats += F("}");
17341744
sprintf_P(mqtt_topic, PSTR("%s/stats"), heishamonSettings.mqtt_topic_base);
17351745
mqtt_client.publish(mqtt_topic, stats.c_str(), MQTT_RETAIN_VALUES);
17361746

1747+
//websocket stats
1748+
#ifdef ESP32
1749+
String ethernetStat;
1750+
if (ETH.phyAddr() != 0) {
1751+
if (ETH.connected()) {
1752+
if (ETH.hasIP()) {
1753+
ethernetStat = F("connected - IP: ");
1754+
ethernetStat += ETH.localIP().toString();
1755+
ethernetStat += F(")");
1756+
} else {
1757+
ethernetStat = F("connected - no IP");
1758+
}
1759+
}
1760+
else {
1761+
ethernetStat = F("not connected");
1762+
}
1763+
} else {
1764+
ethernetStat = F("not installed");
1765+
}
1766+
char *getuptime = getUptime();
1767+
sprintf_P(log_msg, PSTR("{\"data\": {\"stats\": {\"wifi\": %d, \"ethernet\": \"%s\", \"memory\": %d, \"correct\": %.0f,\"mqtt\": %d,\"uptime\": \"%s\"}}}"), getWifiQuality(), ethernetStat.c_str(), getFreeMemory(), readpercentage, mqttReconnects, getuptime);
1768+
free(getuptime);
1769+
#else
1770+
char *getuptime = getUptime();
1771+
sprintf_P(log_msg, PSTR("{\"data\": {\"stats\": {\"wifi\": %d, \"memory\": %d, \"correct\": %.0f,\"mqtt\": %d,\"uptime\": \"%s\"}}}"), getWifiQuality(), getFreeMemory(), readpercentage, mqttReconnects, getuptime);
1772+
free(getuptime);
1773+
#endif
1774+
1775+
websocket_write_all(log_msg, strlen(log_msg));
1776+
17371777
//get new data
17381778
if (!heishamonSettings.listenonly) send_panasonic_query();
17391779

HeishaMon/HeishaOT.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,20 @@ void processOTRequest(unsigned long request, OpenThermResponseStatus status) {
8585
if ((bool)CHEnable != getOTStructMember(_F("chEnable"))->value.b) { //only publish if changed
8686
getOTStructMember(_F("chEnable"))->value.b = (bool)CHEnable;
8787
CHEnable ? mqttPublish((char*)mqtt_topic_opentherm_write, _F("chEnable"), _F("true")) : mqttPublish((char*)mqtt_topic_opentherm_write, _F("chEnable"), _F("false")) ;
88+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %s}}}"), _F("chEnable"), CHEnable ? _F("true") : _F("false"));
89+
websocket_write_all(log_msg, strlen(log_msg));
8890
}
8991
if ((bool)DHWEnable != getOTStructMember(_F("dhwEnable"))->value.b) { //only publish if changed
9092
getOTStructMember(_F("dhwEnable"))->value.b = (bool)DHWEnable;
9193
DHWEnable ? mqttPublish((char*)mqtt_topic_opentherm_write, _F("dhwEnable"), _F("true")) : mqttPublish((char*)mqtt_topic_opentherm_write, _F("dhwEnable"), _F("false")) ;
94+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %s}}}"), _F("dhwEnable"), DHWEnable ? _F("true") : _F("false"));
95+
websocket_write_all(log_msg, strlen(log_msg));
9296
}
9397
if ((bool)Cooling != getOTStructMember(_F("coolingEnable"))->value.b) { //only publish if changed
9498
getOTStructMember(_F("coolingEnable"))->value.b = (bool)Cooling;
9599
Cooling ? mqttPublish((char*)mqtt_topic_opentherm_write, _F("coolingEnable"), _F("true")) : mqttPublish((char*)mqtt_topic_opentherm_write, _F("coolingEnable"), _F("false")) ;
100+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %s}}}"), _F("coolingEnable"), Cooling ? _F("true") : _F("false"));
101+
websocket_write_all(log_msg, strlen(log_msg));
96102
}
97103

98104
sprintf_P(log_msg, PSTR(
@@ -129,6 +135,8 @@ void processOTRequest(unsigned long request, OpenThermResponseStatus status) {
129135
if (getOTStructMember(_F("chSetpoint"))->value.f != ot.getFloat(request)) { //only publish if changed
130136
getOTStructMember(_F("chSetpoint"))->value.f = ot.getFloat(request);
131137
mqttPublish((char*)mqtt_topic_opentherm_write, _F("chSetpoint"), str);
138+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %.2f}}}"), _F("chSetpoint"), getOTStructMember(_F("chSetpoint"))->value.f);
139+
websocket_write_all(log_msg, strlen(log_msg));
132140
}
133141
otResponse = ot.buildResponse(OpenThermMessageType::WRITE_ACK, OpenThermMessageID::TSet, request & 0xffff);
134142
rules_event_cb(_F("?"), _F("chsetpoint"));
@@ -170,6 +178,8 @@ void processOTRequest(unsigned long request, OpenThermResponseStatus status) {
170178
getOTStructMember(_F("relativeModulation"))->value.f = getOTStructMember(_F("maxRelativeModulation"))->value.f;
171179
}
172180
mqttPublish((char*)mqtt_topic_opentherm_write, _F("maxRelativeModulation"), str);
181+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %.2f}}}"), _F("maxRelativeModulation"), getOTStructMember(_F("maxRelativeModulation"))->value.f);
182+
websocket_write_all(log_msg, strlen(log_msg));
173183
}
174184
otResponse = ot.buildResponse(OpenThermMessageType::WRITE_ACK, OpenThermMessageID::MaxRelModLevelSetting, request & 0xffff); //ACK for mandatory fields
175185
} break;
@@ -212,6 +222,8 @@ void processOTRequest(unsigned long request, OpenThermResponseStatus status) {
212222
if (getOTStructMember(_F("coolingControl"))->value.f != ot.getFloat(request)) {
213223
getOTStructMember(_F("coolingControl"))->value.f = ot.getFloat(request);
214224
mqttPublish((char*)mqtt_topic_opentherm_write, _F("coolingControl"), str);
225+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %.2f}}}"), _F("coolingControl"), getOTStructMember(_F("coolingControl"))->value.f);
226+
websocket_write_all(log_msg, strlen(log_msg));
215227
}
216228
otResponse = ot.buildResponse(OpenThermMessageType::WRITE_ACK, OpenThermMessageID::CoolingControl, request & 0xffff);
217229
rules_event_cb(_F("?"), _F("coolingControl"));
@@ -238,6 +250,8 @@ void processOTRequest(unsigned long request, OpenThermResponseStatus status) {
238250
if (getOTStructMember(_F("roomTemp"))->value.f != ot.getFloat(request)) {
239251
mqttPublish((char*)mqtt_topic_opentherm_write, _F("roomTemp"), str);
240252
getOTStructMember(_F("roomTemp"))->value.f = ot.getFloat(request);
253+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %.2f}}}"), _F("roomTemp"), getOTStructMember(_F("roomTemp"))->value.f);
254+
websocket_write_all(log_msg, strlen(log_msg));
241255
}
242256
otResponse = ot.buildResponse(OpenThermMessageType::WRITE_ACK, OpenThermMessageID::Tr, request & 0xffff);
243257
rules_event_cb(_F("?"), _F("roomtemp"));
@@ -250,6 +264,8 @@ void processOTRequest(unsigned long request, OpenThermResponseStatus status) {
250264
if (getOTStructMember(_F("roomTempSet"))->value.f != ot.getFloat(request)) {
251265
getOTStructMember(_F("roomTempSet"))->value.f = ot.getFloat(request);
252266
mqttPublish((char*)mqtt_topic_opentherm_write, _F("roomTempSet"), str);
267+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %.2f}}}"), _F("roomTempSet"), getOTStructMember(_F("roomTempSet"))->value.f);
268+
websocket_write_all(log_msg, strlen(log_msg));
253269
}
254270
otResponse = ot.buildResponse(OpenThermMessageType::WRITE_ACK, OpenThermMessageID::TrSet, request & 0xffff);
255271
rules_event_cb(_F("?"), _F("roomtempset"));
@@ -262,7 +278,9 @@ void processOTRequest(unsigned long request, OpenThermResponseStatus status) {
262278
log_message(log_msg);
263279
if (getOTStructMember(_F("dhwSetpoint"))->value.f != ot.getFloat(request)) {
264280
getOTStructMember(_F("dhwSetpoint"))->value.f = ot.getFloat(request);
265-
mqttPublish((char*)mqtt_topic_opentherm_write, _F("dhwSetpoint"), str);
281+
mqttPublish((char*)mqtt_topic_opentherm_write, _F("dhwSetpoint"), str);
282+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %.2f}}}"), _F("dhwSetpoint"), getOTStructMember(_F("dhwSetpoint"))->value.f);
283+
websocket_write_all(log_msg, strlen(log_msg));
266284
}
267285
otResponse = ot.buildResponse(OpenThermMessageType::WRITE_ACK, OpenThermMessageID::TdhwSet, ot.temperatureToData(getOTStructMember(_F("dhwSetpoint"))->value.f));
268286
} else { //READ_DATA
@@ -281,6 +299,8 @@ void processOTRequest(unsigned long request, OpenThermResponseStatus status) {
281299
if (getOTStructMember(_F("maxTSet"))->value.f != ot.getFloat(request)) {
282300
getOTStructMember(_F("maxTSet"))->value.f = ot.getFloat(request);
283301
mqttPublish((char*)mqtt_topic_opentherm_write, _F("maxTSet"), str);
302+
sprintf_P(log_msg, PSTR("{\"data\": {\"opentherm\": {\"name\": \"%s\", \"value\": %.2f}}}"), _F("maxTSet"), getOTStructMember(_F("maxTSet"))->value.f);
303+
websocket_write_all(log_msg, strlen(log_msg));
284304
}
285305
otResponse = ot.buildResponse(OpenThermMessageType::WRITE_ACK, OpenThermMessageID::MaxTSet, ot.temperatureToData(getOTStructMember(_F("maxTSet"))->value.f));
286306
} else { //READ_DATA

0 commit comments

Comments
 (0)