From 92e8beadc0f658075645438bcf07e5c99012c37f Mon Sep 17 00:00:00 2001 From: Daniel Ekman Date: Tue, 21 Dec 2021 13:07:07 +0100 Subject: [PATCH 1/9] intial test with HA, copy of json --- src/AmsToMqttBridge.ino | 4 + src/mqtt/HomeAssistantMqttHandler.cpp | 272 ++++++++++++++++++++++++++ src/mqtt/HomeAssistantMqttHandler.h | 24 +++ web/mqtt.html | 1 + 4 files changed, 301 insertions(+) create mode 100644 src/mqtt/HomeAssistantMqttHandler.cpp create mode 100644 src/mqtt/HomeAssistantMqttHandler.h diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index c84d9635..6f00b570 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -32,6 +32,7 @@ ADC_MODE(ADC_VCC); #include "mqtt/JsonMqttHandler.h" #include "mqtt/RawMqttHandler.h" #include "mqtt/DomoticzMqttHandler.h" +#include "mqtt/HomeAssistantMqttHandler.h" #include "Uptime.h" @@ -947,6 +948,9 @@ void MQTT_connect() { config.getDomoticzConfig(domo); mqttHandler = new DomoticzMqttHandler(mqtt, domo); break; + case 4: + mqttHandler = new HomeAssistantMqttHandler(mqtt, mqttConfig.clientId, mqttConfig.publishTopic, &hw); + break; } if(mqttConfig.ssl) { diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp new file mode 100644 index 00000000..fc8a1c8f --- /dev/null +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -0,0 +1,272 @@ +#include "HomeAssistantMqttHandler.h" +#include "hexutils.h" +#include "Uptime.h" +#include "web/root/json1_json.h" +#include "web/root/json2_json.h" +#include "web/root/json3_json.h" +#include "web/root/json3pf_json.h" +#include "web/root/jsonsys_json.h" +#include "web/root/jsonprices_json.h" + +bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { + if(topic.isEmpty() || !mqtt->connected()) + return false; + + if(data->getListType() == 1) { + char json[192]; + snprintf_P(json, sizeof(json), JSON1_JSON, + WiFi.macAddress().c_str(), + clientId.c_str(), + (uint32_t) (millis64()/1000), + data->getPackageTimestamp(), + hw->getVcc(), + hw->getWifiRssi(), + hw->getTemperature(), + data->getActiveImportPower() + ); + return mqtt->publish(topic, json); + } else if(data->getListType() == 2) { + char json[384]; + snprintf_P(json, sizeof(json), JSON2_JSON, + WiFi.macAddress().c_str(), + clientId.c_str(), + (uint32_t) (millis64()/1000), + data->getPackageTimestamp(), + hw->getVcc(), + hw->getWifiRssi(), + hw->getTemperature(), + data->getListId().c_str(), + data->getMeterId().c_str(), + data->getMeterModel().c_str(), + data->getActiveImportPower(), + data->getReactiveImportPower(), + data->getActiveExportPower(), + data->getReactiveExportPower(), + data->getL1Current(), + data->getL2Current(), + data->getL3Current(), + data->getL1Voltage(), + data->getL2Voltage(), + data->getL3Voltage() + ); + return mqtt->publish(topic, json); + } else if(data->getListType() == 3) { + if(data->getPowerFactor() == 0) { + char json[512]; + snprintf_P(json, sizeof(json), JSON3_JSON, + WiFi.macAddress().c_str(), + clientId.c_str(), + (uint32_t) (millis64()/1000), + data->getPackageTimestamp(), + hw->getVcc(), + hw->getWifiRssi(), + hw->getTemperature(), + data->getListId().c_str(), + data->getMeterId().c_str(), + data->getMeterModel().c_str(), + data->getActiveImportPower(), + data->getReactiveImportPower(), + data->getActiveExportPower(), + data->getReactiveExportPower(), + data->getL1Current(), + data->getL2Current(), + data->getL3Current(), + data->getL1Voltage(), + data->getL2Voltage(), + data->getL3Voltage(), + data->getActiveImportCounter(), + data->getActiveExportCounter(), + data->getReactiveImportCounter(), + data->getReactiveExportCounter(), + data->getMeterTimestamp() + ); + return mqtt->publish(topic, json); + } else { + char json[768]; + snprintf_P(json, sizeof(json), JSON3PF_JSON, + WiFi.macAddress().c_str(), + clientId.c_str(), + (uint32_t) (millis64()/1000), + data->getPackageTimestamp(), + hw->getVcc(), + hw->getWifiRssi(), + hw->getTemperature(), + data->getListId().c_str(), + data->getMeterId().c_str(), + data->getMeterModel().c_str(), + data->getActiveImportPower(), + data->getReactiveImportPower(), + data->getActiveExportPower(), + data->getReactiveExportPower(), + data->getL1Current(), + data->getL2Current(), + data->getL3Current(), + data->getL1Voltage(), + data->getL2Voltage(), + data->getL3Voltage(), + data->getPowerFactor(), + data->getL1PowerFactor(), + data->getL2PowerFactor(), + data->getL3PowerFactor(), + data->getActiveImportCounter(), + data->getActiveExportCounter(), + data->getReactiveImportCounter(), + data->getReactiveExportCounter(), + data->getMeterTimestamp() + ); + return mqtt->publish(topic, json); + } + } + return false; +} + +bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw) { + int count = hw->getTempSensorCount(); + if(count == 0) + return false; + + int size = 32 + (count * 26); + + char buf[size]; + snprintf(buf, 24, "{\"temperatures\":{"); + + for(int i = 0; i < count; i++) { + TempSensorData* data = hw->getTempSensorData(i); + if(data != NULL) { + char* pos = buf+strlen(buf); + snprintf(pos, 26, "\"%s\":%.2f,", + toHex(data->address, 8).c_str(), + data->lastRead + ); + data->changed = false; + delay(1); + } + } + char* pos = buf+strlen(buf); + snprintf(count == 0 ? pos : pos-1, 8, "}}"); + return mqtt->publish(topic, buf); +} + +bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { + if(topic.isEmpty() || !mqtt->connected()) + return false; + if(strlen(eapi->getToken()) == 0) + return false; + + time_t now = time(nullptr); + + float min1hr, min3hr, min6hr; + int8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1; + float min = INT16_MAX, max = INT16_MIN; + float values[24] = {0}; + for(uint8_t i = 0; i < 24; i++) { + float val = eapi->getValueForHour(now, i); + values[i] = val; + + if(val == ENTSOE_NO_VALUE) break; + + if(val < min) min = val; + if(val > max) max = val; + + if(min1hrIdx == -1 || min1hr > val) { + min1hr = val; + min1hrIdx = i; + } + + if(i >= 2) { + i -= 2; + float val1 = values[i++]; + float val2 = values[i++]; + float val3 = val; + if(val1 == ENTSOE_NO_VALUE || val2 == ENTSOE_NO_VALUE || val3 == ENTSOE_NO_VALUE) continue; + float val3hr = val1+val2+val3; + if(min3hrIdx == -1 || min3hr > val3hr) { + min3hr = val3hr; + min3hrIdx = i-2; + } + } + + if(i >= 5) { + i -= 5; + float val1 = values[i++]; + float val2 = values[i++]; + float val3 = values[i++]; + float val4 = values[i++]; + float val5 = values[i++]; + float val6 = val; + if(val1 == ENTSOE_NO_VALUE || val2 == ENTSOE_NO_VALUE || val3 == ENTSOE_NO_VALUE || val4 == ENTSOE_NO_VALUE || val5 == ENTSOE_NO_VALUE || val6 == ENTSOE_NO_VALUE) continue; + float val6hr = val1+val2+val3+val4+val5+val6; + if(min6hrIdx == -1 || min6hr > val6hr) { + min6hr = val6hr; + min6hrIdx = i-5; + } + } + + } + + char ts1hr[21]; + if(min1hrIdx > -1) { + time_t ts = now + (SECS_PER_HOUR * min1hrIdx); + //Serial.printf("1hr: %d %lu\n", min1hrIdx, ts); + tmElements_t tm; + breakTime(ts, tm); + sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); + } + char ts3hr[21]; + if(min3hrIdx > -1) { + time_t ts = now + (SECS_PER_HOUR * min3hrIdx); + //Serial.printf("3hr: %d %lu\n", min3hrIdx, ts); + tmElements_t tm; + breakTime(ts, tm); + sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); + } + char ts6hr[21]; + if(min6hrIdx > -1) { + time_t ts = now + (SECS_PER_HOUR * min6hrIdx); + //Serial.printf("6hr: %d %lu\n", min6hrIdx, ts); + tmElements_t tm; + breakTime(ts, tm); + sprintf(ts6hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); + } + + char json[384]; + snprintf_P(json, sizeof(json), JSONPRICES_JSON, + WiFi.macAddress().c_str(), + values[0], + values[1], + values[2], + values[3], + values[4], + values[5], + values[6], + values[7], + values[8], + values[9], + values[10], + values[11], + min == INT16_MAX ? 0.0 : min, + max == INT16_MIN ? 0.0 : max, + ts1hr, + ts3hr, + ts6hr + ); + return mqtt->publish(topic, json); +} + +bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { + if(init || topic.isEmpty() || !mqtt->connected()) + return false; + if(!topic.endsWith("/")) topic += "/"; + + char json[192]; + snprintf_P(json, sizeof(json), JSONSYS_JSON, + WiFi.macAddress().c_str(), + clientId.c_str(), + (uint32_t) (millis64()/1000), + hw->getVcc(), + hw->getWifiRssi(), + hw->getTemperature() + ); + init = mqtt->publish(topic, json); + return init; +} diff --git a/src/mqtt/HomeAssistantMqttHandler.h b/src/mqtt/HomeAssistantMqttHandler.h new file mode 100644 index 00000000..14c652b2 --- /dev/null +++ b/src/mqtt/HomeAssistantMqttHandler.h @@ -0,0 +1,24 @@ +#ifndef _HOMEASSISTANTMQTTHANDLER_H +#define _HOMEASSISTANTMQTTHANDLER_H + +#include "AmsMqttHandler.h" + +class HomeAssistantMqttHandler : public AmsMqttHandler { +public: + HomeAssistantMqttHandler(MQTTClient* mqtt, const char* clientId, const char* topic, HwTools* hw) : AmsMqttHandler(mqtt) { + this->clientId = clientId; + this->topic = String(topic); + this->hw = hw; + }; + bool publish(AmsData* data, AmsData* previousState); + bool publishTemperatures(AmsConfiguration*, HwTools*); + bool publishPrices(EntsoeApi*); + bool publishSystem(HwTools*); + +private: + String clientId; + String topic; + HwTools* hw; + bool init = false; +}; +#endif diff --git a/web/mqtt.html b/web/mqtt.html index 9fefb1d7..ce128e01 100644 --- a/web/mqtt.html +++ b/web/mqtt.html @@ -62,6 +62,7 @@ + From d7d25083dc451a8af7e27f2ab5c43b96d5107411 Mon Sep 17 00:00:00 2001 From: Daniel Ekman Date: Tue, 21 Dec 2021 14:21:02 +0100 Subject: [PATCH 2/9] flat data messages --- src/mqtt/HomeAssistantMqttHandler.cpp | 60 +++++++-------------------- src/web/AmsWebServer.cpp | 2 +- web/json1ha.json | 3 ++ web/json2ha.json | 15 +++++++ web/json3ha.json | 20 +++++++++ web/json3hapf.json | 24 +++++++++++ web/mqtt.html | 2 +- 7 files changed, 80 insertions(+), 46 deletions(-) create mode 100644 web/json1ha.json create mode 100644 web/json2ha.json create mode 100644 web/json3ha.json create mode 100644 web/json3hapf.json diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index fc8a1c8f..24ee83a6 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -1,10 +1,10 @@ #include "HomeAssistantMqttHandler.h" #include "hexutils.h" #include "Uptime.h" -#include "web/root/json1_json.h" -#include "web/root/json2_json.h" -#include "web/root/json3_json.h" -#include "web/root/json3pf_json.h" +#include "web/root/json1ha_json.h" +#include "web/root/json2ha_json.h" +#include "web/root/json3ha_json.h" +#include "web/root/json3hapf_json.h" #include "web/root/jsonsys_json.h" #include "web/root/jsonprices_json.h" @@ -14,27 +14,13 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { if(data->getListType() == 1) { char json[192]; - snprintf_P(json, sizeof(json), JSON1_JSON, - WiFi.macAddress().c_str(), - clientId.c_str(), - (uint32_t) (millis64()/1000), - data->getPackageTimestamp(), - hw->getVcc(), - hw->getWifiRssi(), - hw->getTemperature(), + snprintf_P(json, sizeof(json), JSON1HA_JSON, data->getActiveImportPower() ); - return mqtt->publish(topic, json); + return mqtt->publish(topic + "/data1", json); } else if(data->getListType() == 2) { char json[384]; - snprintf_P(json, sizeof(json), JSON2_JSON, - WiFi.macAddress().c_str(), - clientId.c_str(), - (uint32_t) (millis64()/1000), - data->getPackageTimestamp(), - hw->getVcc(), - hw->getWifiRssi(), - hw->getTemperature(), + snprintf_P(json, sizeof(json), JSON2HA_JSON, data->getListId().c_str(), data->getMeterId().c_str(), data->getMeterModel().c_str(), @@ -49,18 +35,11 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { data->getL2Voltage(), data->getL3Voltage() ); - return mqtt->publish(topic, json); + return mqtt->publish(topic + "/data2", json); } else if(data->getListType() == 3) { if(data->getPowerFactor() == 0) { char json[512]; - snprintf_P(json, sizeof(json), JSON3_JSON, - WiFi.macAddress().c_str(), - clientId.c_str(), - (uint32_t) (millis64()/1000), - data->getPackageTimestamp(), - hw->getVcc(), - hw->getWifiRssi(), - hw->getTemperature(), + snprintf_P(json, sizeof(json), JSON3HA_JSON, data->getListId().c_str(), data->getMeterId().c_str(), data->getMeterModel().c_str(), @@ -80,17 +59,10 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { data->getReactiveExportCounter(), data->getMeterTimestamp() ); - return mqtt->publish(topic, json); + return mqtt->publish(topic + "/data3", json); } else { char json[768]; - snprintf_P(json, sizeof(json), JSON3PF_JSON, - WiFi.macAddress().c_str(), - clientId.c_str(), - (uint32_t) (millis64()/1000), - data->getPackageTimestamp(), - hw->getVcc(), - hw->getWifiRssi(), - hw->getTemperature(), + snprintf_P(json, sizeof(json), JSON3HAPF_JSON, data->getListId().c_str(), data->getMeterId().c_str(), data->getMeterModel().c_str(), @@ -114,7 +86,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { data->getReactiveExportCounter(), data->getMeterTimestamp() ); - return mqtt->publish(topic, json); + return mqtt->publish(topic + "/data3pf", json); } } return false; @@ -144,7 +116,7 @@ bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwT } char* pos = buf+strlen(buf); snprintf(count == 0 ? pos : pos-1, 8, "}}"); - return mqtt->publish(topic, buf); + return mqtt->publish(topic + "/temperatures", buf); } bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { @@ -250,13 +222,13 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { ts3hr, ts6hr ); - return mqtt->publish(topic, json); + return mqtt->publish(topic + "/prices", json); } bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { if(init || topic.isEmpty() || !mqtt->connected()) return false; - if(!topic.endsWith("/")) topic += "/"; + //if(!topic.endsWith("/")) topic += "/"; char json[192]; snprintf_P(json, sizeof(json), JSONSYS_JSON, @@ -267,6 +239,6 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { hw->getWifiRssi(), hw->getTemperature() ); - init = mqtt->publish(topic, json); + init = mqtt->publish(topic + "/state", json); return init; } diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index d14c9c9f..ff05f9a2 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -539,7 +539,7 @@ void AmsWebServer::configMqttHtml() { html.replace("{u}", mqtt.username); html.replace("{pw}", mqtt.password); html.replace("{f}", String(mqtt.payloadFormat)); - for(int i = 0; i<4; i++) { + for(int i = 0; i<5; i++) { html.replace("{f" + String(i) + "}", mqtt.payloadFormat == i ? "selected" : ""); } diff --git a/web/json1ha.json b/web/json1ha.json new file mode 100644 index 00000000..9fa1f374 --- /dev/null +++ b/web/json1ha.json @@ -0,0 +1,3 @@ +{ + "P" : %d +} diff --git a/web/json2ha.json b/web/json2ha.json new file mode 100644 index 00000000..8fa16c93 --- /dev/null +++ b/web/json2ha.json @@ -0,0 +1,15 @@ +{ + "lv" : "%s", + "id" : "%s", + "type" : "%s", + "P" : %d, + "Q" : %d, + "PO" : %d, + "QO" : %d, + "I1" : %.2f, + "I2" : %.2f, + "I3" : %.2f, + "U1" : %.2f, + "U2" : %.2f, + "U3" : %.2f +} diff --git a/web/json3ha.json b/web/json3ha.json new file mode 100644 index 00000000..55220a70 --- /dev/null +++ b/web/json3ha.json @@ -0,0 +1,20 @@ +{ + "lv" : "%s", + "id" : "%s", + "type" : "%s", + "P" : %d, + "Q" : %d, + "PO" : %d, + "QO" : %d, + "I1" : %.2f, + "I2" : %.2f, + "I3" : %.2f, + "U1" : %.2f, + "U2" : %.2f, + "U3" : %.2f, + "tPI" : %.2f, + "tPO" : %.2f, + "tQI" : %.2f, + "tQO" : %.2f, + "rtc" : %lu +} diff --git a/web/json3hapf.json b/web/json3hapf.json new file mode 100644 index 00000000..dd3e4a5b --- /dev/null +++ b/web/json3hapf.json @@ -0,0 +1,24 @@ +{ + "lv" : "%s", + "id" : "%s", + "type" : "%s", + "P" : %d, + "Q" : %d, + "PO" : %d, + "QO" : %d, + "I1" : %.2f, + "I2" : %.2f, + "I3" : %.2f, + "U1" : %.2f, + "U2" : %.2f, + "U3" : %.2f, + "PF" : %.2f, + "PF1" : %.2f, + "PF2" : %.2f, + "PF3" : %.2f, + "tPI" : %.2f, + "tPO" : %.2f, + "tQI" : %.2f, + "tQO" : %.2f, + "rtc" : %lu +} diff --git a/web/mqtt.html b/web/mqtt.html index ce128e01..34d445a9 100644 --- a/web/mqtt.html +++ b/web/mqtt.html @@ -62,7 +62,7 @@ - + From 86939d4890036a0b5cba78358c99c94eac41435e Mon Sep 17 00:00:00 2001 From: Daniel Ekman Date: Tue, 21 Dec 2021 15:56:09 +0100 Subject: [PATCH 3/9] topic contains all fields, null if not used --- src/AmsToMqttBridge.ino | 7 +++++++ src/mqtt/HomeAssistantMqttHandler.cpp | 8 ++++---- web/json2ha.json | 11 ++++++++++- web/json3ha.json | 4 ++++ web/jsonha.json | 24 ++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 web/jsonha.json diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 6f00b570..f029c22b 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -315,6 +315,7 @@ bool longPressActive = false; bool wifiConnected = false; unsigned long lastTemperatureRead = 0; +unsigned long lastSystemMessage = 0; unsigned long lastErrorBlink = 0; int lastError = 0; @@ -473,6 +474,12 @@ void loop() { } if(readHanPort() || now - meterState.getLastUpdateMillis() > 30000) { + if(now - lastSystemMessage > 15000) { + if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) { + lastSystemMessage = now; + mqttHandler->publishSystem(&hw); + } + } if(now - lastTemperatureRead > 15000) { unsigned long start = millis(); hw.updateTemperatures(); diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 24ee83a6..10ed07ec 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -17,7 +17,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { snprintf_P(json, sizeof(json), JSON1HA_JSON, data->getActiveImportPower() ); - return mqtt->publish(topic + "/data1", json); + return mqtt->publish(topic + "/power", json); } else if(data->getListType() == 2) { char json[384]; snprintf_P(json, sizeof(json), JSON2HA_JSON, @@ -35,7 +35,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { data->getL2Voltage(), data->getL3Voltage() ); - return mqtt->publish(topic + "/data2", json); + return mqtt->publish(topic + "/sensor", json); } else if(data->getListType() == 3) { if(data->getPowerFactor() == 0) { char json[512]; @@ -59,7 +59,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { data->getReactiveExportCounter(), data->getMeterTimestamp() ); - return mqtt->publish(topic + "/data3", json); + return mqtt->publish(topic + "/sensor", json); } else { char json[768]; snprintf_P(json, sizeof(json), JSON3HAPF_JSON, @@ -86,7 +86,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { data->getReactiveExportCounter(), data->getMeterTimestamp() ); - return mqtt->publish(topic + "/data3pf", json); + return mqtt->publish(topic + "/sensor", json); } } return false; diff --git a/web/json2ha.json b/web/json2ha.json index 8fa16c93..b854e4cc 100644 --- a/web/json2ha.json +++ b/web/json2ha.json @@ -11,5 +11,14 @@ "I3" : %.2f, "U1" : %.2f, "U2" : %.2f, - "U3" : %.2f + "U3" : %.2f, + "PF" : null, + "PF1" : null, + "PF2" : null, + "PF3" : null, + "tPI" : null, + "tPO" : null, + "tQI" : null, + "tQO" : null, + "rtc" : null } diff --git a/web/json3ha.json b/web/json3ha.json index 55220a70..806933f3 100644 --- a/web/json3ha.json +++ b/web/json3ha.json @@ -12,6 +12,10 @@ "U1" : %.2f, "U2" : %.2f, "U3" : %.2f, + "PF" : null, + "PF1" : null, + "PF2" : null, + "PF3" : null, "tPI" : %.2f, "tPO" : %.2f, "tQI" : %.2f, diff --git a/web/jsonha.json b/web/jsonha.json new file mode 100644 index 00000000..dd3e4a5b --- /dev/null +++ b/web/jsonha.json @@ -0,0 +1,24 @@ +{ + "lv" : "%s", + "id" : "%s", + "type" : "%s", + "P" : %d, + "Q" : %d, + "PO" : %d, + "QO" : %d, + "I1" : %.2f, + "I2" : %.2f, + "I3" : %.2f, + "U1" : %.2f, + "U2" : %.2f, + "U3" : %.2f, + "PF" : %.2f, + "PF1" : %.2f, + "PF2" : %.2f, + "PF3" : %.2f, + "tPI" : %.2f, + "tPO" : %.2f, + "tQI" : %.2f, + "tQO" : %.2f, + "rtc" : %lu +} From 03089e92cbe13cdaa16ff5850732a90c99277213 Mon Sep 17 00:00:00 2001 From: Daniel Ekman Date: Tue, 21 Dec 2021 20:40:17 +0100 Subject: [PATCH 4/9] basic stuff implemented --- src/AmsToMqttBridge.ino | 7 ---- src/mqtt/HomeAssistantMqttHandler.cpp | 54 +++++++++++++++------------ src/mqtt/HomeAssistantMqttHandler.h | 2 +- web/ha1.json | 3 ++ web/{json2ha.json => ha2.json} | 0 web/{json3ha.json => ha3.json} | 0 web/{json3hapf.json => ha3pf.json} | 0 web/hadiscover1.json | 15 ++++++++ web/json1ha.json | 3 -- 9 files changed, 50 insertions(+), 34 deletions(-) create mode 100644 web/ha1.json rename web/{json2ha.json => ha2.json} (100%) rename web/{json3ha.json => ha3.json} (100%) rename web/{json3hapf.json => ha3pf.json} (100%) create mode 100644 web/hadiscover1.json delete mode 100644 web/json1ha.json diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index f029c22b..6f00b570 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -315,7 +315,6 @@ bool longPressActive = false; bool wifiConnected = false; unsigned long lastTemperatureRead = 0; -unsigned long lastSystemMessage = 0; unsigned long lastErrorBlink = 0; int lastError = 0; @@ -474,12 +473,6 @@ void loop() { } if(readHanPort() || now - meterState.getLastUpdateMillis() > 30000) { - if(now - lastSystemMessage > 15000) { - if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) { - lastSystemMessage = now; - mqttHandler->publishSystem(&hw); - } - } if(now - lastTemperatureRead > 15000) { unsigned long start = millis(); hw.updateTemperatures(); diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 10ed07ec..d10630c6 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -1,10 +1,10 @@ #include "HomeAssistantMqttHandler.h" #include "hexutils.h" #include "Uptime.h" -#include "web/root/json1ha_json.h" -#include "web/root/json2ha_json.h" -#include "web/root/json3ha_json.h" -#include "web/root/json3hapf_json.h" +#include "web/root/ha1_json.h" +#include "web/root/ha2_json.h" +#include "web/root/ha3_json.h" +#include "web/root/ha3pf_json.h" #include "web/root/jsonsys_json.h" #include "web/root/jsonprices_json.h" @@ -12,21 +12,22 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { if(topic.isEmpty() || !mqtt->connected()) return false; + listType = data->getListType(); // for discovery stuff in publishSystem() if(data->getListType() == 1) { char json[192]; - snprintf_P(json, sizeof(json), JSON1HA_JSON, + snprintf_P(json, sizeof(json), HA1_JSON, data->getActiveImportPower() ); - return mqtt->publish(topic + "/power", json); + return mqtt->publish(topic + "/sensor", json); } else if(data->getListType() == 2) { char json[384]; - snprintf_P(json, sizeof(json), JSON2HA_JSON, + snprintf_P(json, sizeof(json), HA2_JSON, data->getListId().c_str(), data->getMeterId().c_str(), data->getMeterModel().c_str(), data->getActiveImportPower(), data->getReactiveImportPower(), - data->getActiveExportPower(), + sequence, //data->getActiveExportPower(), data->getReactiveExportPower(), data->getL1Current(), data->getL2Current(), @@ -39,7 +40,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { } else if(data->getListType() == 3) { if(data->getPowerFactor() == 0) { char json[512]; - snprintf_P(json, sizeof(json), JSON3HA_JSON, + snprintf_P(json, sizeof(json), HA3_JSON, data->getListId().c_str(), data->getMeterId().c_str(), data->getMeterModel().c_str(), @@ -62,7 +63,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { return mqtt->publish(topic + "/sensor", json); } else { char json[768]; - snprintf_P(json, sizeof(json), JSON3HAPF_JSON, + snprintf_P(json, sizeof(json), HA3PF_JSON, data->getListId().c_str(), data->getMeterId().c_str(), data->getMeterModel().c_str(), @@ -226,19 +227,26 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { } bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { - if(init || topic.isEmpty() || !mqtt->connected()) + if(topic.isEmpty() || !mqtt->connected()){ + sequence = 0; return false; - //if(!topic.endsWith("/")) topic += "/"; + } - char json[192]; - snprintf_P(json, sizeof(json), JSONSYS_JSON, - WiFi.macAddress().c_str(), - clientId.c_str(), - (uint32_t) (millis64()/1000), - hw->getVcc(), - hw->getWifiRssi(), - hw->getTemperature() - ); - init = mqtt->publish(topic + "/state", json); - return init; + if(sequence % 3 == 0){ + char json[192]; + snprintf_P(json, sizeof(json), JSONSYS_JSON, + WiFi.macAddress().c_str(), + clientId.c_str(), + (uint32_t) (millis64()/1000), + hw->getVcc(), + hw->getWifiRssi(), + hw->getTemperature() + ); + mqtt->publish(topic + "/state", json); + } + if(sequence % 6 == 1 && listType > 0){ // every 60 ams message, publish mqtt discovery + mqtt->publish(topic + "/discovery", "{\"discovery\":1}"); // test + } + if(listType>0) sequence++; + return true; } diff --git a/src/mqtt/HomeAssistantMqttHandler.h b/src/mqtt/HomeAssistantMqttHandler.h index 14c652b2..4725d303 100644 --- a/src/mqtt/HomeAssistantMqttHandler.h +++ b/src/mqtt/HomeAssistantMqttHandler.h @@ -19,6 +19,6 @@ private: String clientId; String topic; HwTools* hw; - bool init = false; + uint8_t sequence = 0, listType = 0; }; #endif diff --git a/web/ha1.json b/web/ha1.json new file mode 100644 index 00000000..62d98528 --- /dev/null +++ b/web/ha1.json @@ -0,0 +1,3 @@ +{ + "P" : %d, +} diff --git a/web/json2ha.json b/web/ha2.json similarity index 100% rename from web/json2ha.json rename to web/ha2.json diff --git a/web/json3ha.json b/web/ha3.json similarity index 100% rename from web/json3ha.json rename to web/ha3.json diff --git a/web/json3hapf.json b/web/ha3pf.json similarity index 100% rename from web/json3hapf.json rename to web/ha3pf.json diff --git a/web/hadiscover1.json b/web/hadiscover1.json new file mode 100644 index 00000000..de8f64fa --- /dev/null +++ b/web/hadiscover1.json @@ -0,0 +1,15 @@ +{ + "name" : "%s", + "stat_t" : "%s", + "json_attr_t" : "%s", + "unit_of_meas" : "%s", + "val_tpl" : "{{value_json['%s']}}", + "uniq_id" : "%s", + "dev" : { + "ids" : [ "%s" ], + "name" : "AMS reader", + "mdl" : "ESP32", + "sw" : "2.0.0", + "mf" : "AmsToMqttBridge" + } + } \ No newline at end of file diff --git a/web/json1ha.json b/web/json1ha.json deleted file mode 100644 index 9fa1f374..00000000 --- a/web/json1ha.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "P" : %d -} From 2e4e4328f2f264ba6997dddac37a1e7384616b89 Mon Sep 17 00:00:00 2001 From: Daniel Ekman Date: Tue, 21 Dec 2021 23:17:29 +0100 Subject: [PATCH 5/9] first working discovery --- src/mqtt/HomeAssistantMqttHandler.cpp | 53 +++++++++++++++++++++++++-- web/hadiscover1.json | 14 ++++--- web/hadiscover2.json | 13 +++++++ 3 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 web/hadiscover2.json diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index d10630c6..0f55d8a5 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -7,6 +7,8 @@ #include "web/root/ha3pf_json.h" #include "web/root/jsonsys_json.h" #include "web/root/jsonprices_json.h" +#include "web/root/hadiscover1_json.h" +#include "web/root/hadiscover2_json.h" bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { if(topic.isEmpty() || !mqtt->connected()) @@ -27,7 +29,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { data->getMeterModel().c_str(), data->getActiveImportPower(), data->getReactiveImportPower(), - sequence, //data->getActiveExportPower(), + data->getActiveExportPower(), data->getReactiveExportPower(), data->getL1Current(), data->getL2Current(), @@ -244,8 +246,53 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { ); mqtt->publish(topic + "/state", json); } - if(sequence % 6 == 1 && listType > 0){ // every 60 ams message, publish mqtt discovery - mqtt->publish(topic + "/discovery", "{\"discovery\":1}"); // test + if(sequence % 60 == 1 && listType > 0){ // every 60 ams message, publish mqtt discovery + char json[512]; + String haTopic = "homeassistant/sensor/"; + String haUID = "ams-3a08"; + + snprintf_P(json, sizeof(json), HADISCOVER1_JSON, + "AMS reader status", + (topic + "/state").c_str(), + (topic + "/state").c_str(), + (haUID + "_status").c_str(), + (haUID + "_status").c_str(), + "dB", + "rssi", + haUID.c_str(), + "AMS reader", + "ESP32", + "2.0.0", + "AmsToMqttBridge" + ); + mqtt->publish(haTopic + haUID + "_status/config", json); + + snprintf_P(json, sizeof(json), HADISCOVER2_JSON, + "AMS active import", + (topic + "/sensor").c_str(), + (haUID + "_activeI").c_str(), + (haUID + "_activeI").c_str(), + "W", + "P", + "power", + "measurement", + haUID.c_str() + ); + mqtt->publish(haTopic + haUID + "_activeI/config", json); + + snprintf_P(json, sizeof(json), HADISCOVER2_JSON, + "AMS accumulated active energy", + (topic + "/sensor").c_str(), + (haUID + "_accumI").c_str(), + (haUID + "_accumI").c_str(), + "kWh", + "tPI", + "energy", + "total_increasing", + haUID.c_str() + ); + mqtt->publish(haTopic + haUID + "_accumI/config", json); + } if(listType>0) sequence++; return true; diff --git a/web/hadiscover1.json b/web/hadiscover1.json index de8f64fa..1521981e 100644 --- a/web/hadiscover1.json +++ b/web/hadiscover1.json @@ -2,14 +2,16 @@ "name" : "%s", "stat_t" : "%s", "json_attr_t" : "%s", + "uniq_id" : "%s", + "obj_id" : "%s", "unit_of_meas" : "%s", "val_tpl" : "{{value_json['%s']}}", - "uniq_id" : "%s", + "json_attr_tpl" : "{{ value_json }}", "dev" : { "ids" : [ "%s" ], - "name" : "AMS reader", - "mdl" : "ESP32", - "sw" : "2.0.0", - "mf" : "AmsToMqttBridge" + "name" : "%s", + "mdl" : "%s", + "sw" : "%s", + "mf" : "%s" } - } \ No newline at end of file +} \ No newline at end of file diff --git a/web/hadiscover2.json b/web/hadiscover2.json new file mode 100644 index 00000000..9ec370b2 --- /dev/null +++ b/web/hadiscover2.json @@ -0,0 +1,13 @@ +{ + "name" : "%s", + "stat_t" : "%s", + "uniq_id" : "%s", + "obj_id" : "%s", + "unit_of_meas" : "%s", + "val_tpl" : "{{value_json['%s']}}", + "dev_cla" : "%s", + "stat_cla" : "%s", + "dev" : { + "ids" : [ "%s" ] + } +} \ No newline at end of file From b79e6112b11bb8a1e65ffb801d0adbe3111c0469 Mon Sep 17 00:00:00 2001 From: Daniel Ekman Date: Wed, 22 Dec 2021 17:10:10 +0100 Subject: [PATCH 6/9] move energy to separate topic --- src/mqtt/HomeAssistantMqttHandler.cpp | 91 ++++++++------------------- web/ha2.json | 27 ++------ web/ha3.json | 13 ++-- web/ha3pf.json | 24 ------- 4 files changed, 36 insertions(+), 119 deletions(-) delete mode 100644 web/ha3pf.json diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 0f55d8a5..ffd0dcad 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -4,7 +4,6 @@ #include "web/root/ha1_json.h" #include "web/root/ha2_json.h" #include "web/root/ha3_json.h" -#include "web/root/ha3pf_json.h" #include "web/root/jsonsys_json.h" #include "web/root/jsonprices_json.h" #include "web/root/hadiscover1_json.h" @@ -15,15 +14,28 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { return false; listType = data->getListType(); // for discovery stuff in publishSystem() - if(data->getListType() == 1) { + if(data->getListType() == 3) { // publish energy counts + if(data->getActiveExportCounter() > 0){ + char json[256]; + snprintf_P(json, sizeof(json), HA2_JSON, + data->getActiveImportCounter(), + data->getActiveExportCounter(), + data->getReactiveImportCounter(), + data->getReactiveExportCounter(), + data->getMeterTimestamp() + ); + mqtt->publish(topic + "/energy", json); + } + } + if(data->getListType() == 1) { // publish power counts char json[192]; snprintf_P(json, sizeof(json), HA1_JSON, data->getActiveImportPower() ); - return mqtt->publish(topic + "/sensor", json); - } else if(data->getListType() == 2) { - char json[384]; - snprintf_P(json, sizeof(json), HA2_JSON, + return mqtt->publish(topic + "/power", json); + } else if(data->getListType() == 2 || data->getListType() == 3) { + char json[768]; + snprintf_P(json, sizeof(json), HA3_JSON, data->getListId().c_str(), data->getMeterId().c_str(), data->getMeterModel().c_str(), @@ -36,69 +48,20 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { data->getL3Current(), data->getL1Voltage(), data->getL2Voltage(), - data->getL3Voltage() + data->getL3Voltage(), + data->getPowerFactor() == 0 ? 1 : data->getPowerFactor(), + data->getPowerFactor() == 0 ? 1 : data->getL1PowerFactor(), + data->getPowerFactor() == 0 ? 1 : data->getL2PowerFactor(), + data->getPowerFactor() == 0 ? 1 : data->getL3PowerFactor() ); - return mqtt->publish(topic + "/sensor", json); - } else if(data->getListType() == 3) { - if(data->getPowerFactor() == 0) { - char json[512]; - snprintf_P(json, sizeof(json), HA3_JSON, - data->getListId().c_str(), - data->getMeterId().c_str(), - data->getMeterModel().c_str(), - data->getActiveImportPower(), - data->getReactiveImportPower(), - data->getActiveExportPower(), - data->getReactiveExportPower(), - data->getL1Current(), - data->getL2Current(), - data->getL3Current(), - data->getL1Voltage(), - data->getL2Voltage(), - data->getL3Voltage(), - data->getActiveImportCounter(), - data->getActiveExportCounter(), - data->getReactiveImportCounter(), - data->getReactiveExportCounter(), - data->getMeterTimestamp() - ); - return mqtt->publish(topic + "/sensor", json); - } else { - char json[768]; - snprintf_P(json, sizeof(json), HA3PF_JSON, - data->getListId().c_str(), - data->getMeterId().c_str(), - data->getMeterModel().c_str(), - data->getActiveImportPower(), - data->getReactiveImportPower(), - data->getActiveExportPower(), - data->getReactiveExportPower(), - data->getL1Current(), - data->getL2Current(), - data->getL3Current(), - data->getL1Voltage(), - data->getL2Voltage(), - data->getL3Voltage(), - data->getPowerFactor(), - data->getL1PowerFactor(), - data->getL2PowerFactor(), - data->getL3PowerFactor(), - data->getActiveImportCounter(), - data->getActiveExportCounter(), - data->getReactiveImportCounter(), - data->getReactiveExportCounter(), - data->getMeterTimestamp() - ); - return mqtt->publish(topic + "/sensor", json); - } + return mqtt->publish(topic + "/power", json); } return false; } bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw) { int count = hw->getTempSensorCount(); - if(count == 0) - return false; + if(count == 0) return false; int size = 32 + (count * 26); @@ -269,7 +232,7 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { snprintf_P(json, sizeof(json), HADISCOVER2_JSON, "AMS active import", - (topic + "/sensor").c_str(), + (topic + "/power").c_str(), (haUID + "_activeI").c_str(), (haUID + "_activeI").c_str(), "W", @@ -282,7 +245,7 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { snprintf_P(json, sizeof(json), HADISCOVER2_JSON, "AMS accumulated active energy", - (topic + "/sensor").c_str(), + (topic + "/energy").c_str(), (haUID + "_accumI").c_str(), (haUID + "_accumI").c_str(), "kWh", diff --git a/web/ha2.json b/web/ha2.json index b854e4cc..9ffcdaf5 100644 --- a/web/ha2.json +++ b/web/ha2.json @@ -1,24 +1,7 @@ { - "lv" : "%s", - "id" : "%s", - "type" : "%s", - "P" : %d, - "Q" : %d, - "PO" : %d, - "QO" : %d, - "I1" : %.2f, - "I2" : %.2f, - "I3" : %.2f, - "U1" : %.2f, - "U2" : %.2f, - "U3" : %.2f, - "PF" : null, - "PF1" : null, - "PF2" : null, - "PF3" : null, - "tPI" : null, - "tPO" : null, - "tQI" : null, - "tQO" : null, - "rtc" : null + "tPI" : %.2f, + "tPO" : %.2f, + "tQI" : %.2f, + "tQO" : %.2f, + "rtc" : %llu } diff --git a/web/ha3.json b/web/ha3.json index 806933f3..41fad56b 100644 --- a/web/ha3.json +++ b/web/ha3.json @@ -12,13 +12,8 @@ "U1" : %.2f, "U2" : %.2f, "U3" : %.2f, - "PF" : null, - "PF1" : null, - "PF2" : null, - "PF3" : null, - "tPI" : %.2f, - "tPO" : %.2f, - "tQI" : %.2f, - "tQO" : %.2f, - "rtc" : %lu + "PF" : %.2f, + "PF1" : %.2f, + "PF2" : %.2f, + "PF3" : %.2f } diff --git a/web/ha3pf.json b/web/ha3pf.json deleted file mode 100644 index dd3e4a5b..00000000 --- a/web/ha3pf.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "lv" : "%s", - "id" : "%s", - "type" : "%s", - "P" : %d, - "Q" : %d, - "PO" : %d, - "QO" : %d, - "I1" : %.2f, - "I2" : %.2f, - "I3" : %.2f, - "U1" : %.2f, - "U2" : %.2f, - "U3" : %.2f, - "PF" : %.2f, - "PF1" : %.2f, - "PF2" : %.2f, - "PF3" : %.2f, - "tPI" : %.2f, - "tPO" : %.2f, - "tQI" : %.2f, - "tQO" : %.2f, - "rtc" : %lu -} From 18bc6753dbb878aba0b0132f8aee2828cd2a1725 Mon Sep 17 00:00:00 2001 From: Daniel Ekman Date: Wed, 22 Dec 2021 20:20:21 +0100 Subject: [PATCH 7/9] publish all disscovery params --- src/mqtt/HomeAssistantMqttHandler.cpp | 103 ++++++++++++++++---------- web/hadiscover3.json | 12 +++ 2 files changed, 74 insertions(+), 41 deletions(-) create mode 100644 web/hadiscover3.json diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index ffd0dcad..5f654159 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -8,6 +8,7 @@ #include "web/root/jsonprices_json.h" #include "web/root/hadiscover1_json.h" #include "web/root/hadiscover2_json.h" +#include "web/root/hadiscover3_json.h" bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { if(topic.isEmpty() || !mqtt->connected()) @@ -15,17 +16,15 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { listType = data->getListType(); // for discovery stuff in publishSystem() if(data->getListType() == 3) { // publish energy counts - if(data->getActiveExportCounter() > 0){ - char json[256]; - snprintf_P(json, sizeof(json), HA2_JSON, - data->getActiveImportCounter(), - data->getActiveExportCounter(), - data->getReactiveImportCounter(), - data->getReactiveExportCounter(), - data->getMeterTimestamp() - ); - mqtt->publish(topic + "/energy", json); - } + char json[256]; + snprintf_P(json, sizeof(json), HA2_JSON, + data->getActiveImportCounter(), + data->getActiveExportCounter(), + data->getReactiveImportCounter(), + data->getReactiveExportCounter(), + data->getMeterTimestamp() + ); + mqtt->publish(topic + "/energy", json); } if(data->getListType() == 1) { // publish power counts char json[192]; @@ -33,7 +32,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { data->getActiveImportPower() ); return mqtt->publish(topic + "/power", json); - } else if(data->getListType() == 2 || data->getListType() == 3) { + } else if(data->getListType() == 2 || data->getListType() == 3) { // publish power counts and volts/amps char json[768]; snprintf_P(json, sizeof(json), HA3_JSON, data->getListId().c_str(), @@ -209,17 +208,17 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { ); mqtt->publish(topic + "/state", json); } - if(sequence % 60 == 1 && listType > 0){ // every 60 ams message, publish mqtt discovery + if(sequence % 60 == 1 && listType > 1){ // every 60 ams message, publish mqtt discovery char json[512]; String haTopic = "homeassistant/sensor/"; String haUID = "ams-3a08"; - + String param = "status"; snprintf_P(json, sizeof(json), HADISCOVER1_JSON, "AMS reader status", (topic + "/state").c_str(), (topic + "/state").c_str(), - (haUID + "_status").c_str(), - (haUID + "_status").c_str(), + (haUID + "_" + param).c_str(), + (haUID + "_" + param).c_str(), "dB", "rssi", haUID.c_str(), @@ -228,34 +227,56 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { "2.0.0", "AmsToMqttBridge" ); - mqtt->publish(haTopic + haUID + "_status/config", json); + mqtt->publish(haTopic + haUID + "_" + param + "/config", json); - snprintf_P(json, sizeof(json), HADISCOVER2_JSON, - "AMS active import", - (topic + "/power").c_str(), - (haUID + "_activeI").c_str(), - (haUID + "_activeI").c_str(), - "W", - "P", - "power", - "measurement", - haUID.c_str() - ); - mqtt->publish(haTopic + haUID + "_activeI/config", json); + String names[14] = {"Active import", "Reactive import", "Active export", "Reactive export", "L1 current", "L2 current", "L3 current", "L1 voltage", "L2 voltage", "L3 voltage", + "Accumulated active import", "Accumulated active export", "Accumulated reactive import", "Accumulated reactive export"}; + String params[14] = {"P", "Q", "PO", "QO", "I1", "I2", "I3", "U1", "U2", "U3", "tPI", "tPO", "tQI", "tQO"}; + String uom[14] = {"W", "W", "W", "W", "A", "A", "A", "V", "V", "V", "kWh", "kWh", "kWh", "kWh"}; + String devcl[14] = {"power", "power", "power", "power", "current", "current", "current", "voltage", "voltage", "voltage", "energy", "energy", "energy", "energy"}; + for(int i=0;i<4;i++){ + snprintf_P(json, sizeof(json), HADISCOVER2_JSON, + names[i].c_str(), // name + (topic + "/power").c_str(), // state_topic + (haUID + "_" + params[i]).c_str(), // unique_id + (haUID + "_" + params[i]).c_str(), // object_id + uom[i].c_str(), // unit_of_measurement + params[i].c_str(), // value_template + devcl[i].c_str(), // device_class + "measurement", // state_class + haUID.c_str() // dev ids + ); + mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); + } - snprintf_P(json, sizeof(json), HADISCOVER2_JSON, - "AMS accumulated active energy", - (topic + "/energy").c_str(), - (haUID + "_accumI").c_str(), - (haUID + "_accumI").c_str(), - "kWh", - "tPI", - "energy", - "total_increasing", - haUID.c_str() - ); - mqtt->publish(haTopic + haUID + "_accumI/config", json); + for(int i=4;i<10;i++){ + snprintf_P(json, sizeof(json), HADISCOVER3_JSON, + names[i].c_str(), // name + (topic + "/power").c_str(), // state_topic + (haUID + "_" + params[i]).c_str(), // unique_id + (haUID + "_" + params[i]).c_str(), // object_id + uom[i].c_str(), // unit_of_measurement + params[i].c_str(), // value_template + devcl[i].c_str(), // device_class + haUID.c_str() // dev ids + ); + mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); + } + for(int i=10;i<14;i++){ + snprintf_P(json, sizeof(json), HADISCOVER2_JSON, + names[i].c_str(), // name + (topic + "/energy").c_str(), // state_topic + (haUID + "_" + params[i]).c_str(), // unique_id + (haUID + "_" + params[i]).c_str(), // object_id + uom[i].c_str(), // unit_of_measurement + params[i].c_str(), // value_template + devcl[i].c_str(), // device_class + "total_increasing", // state_class + haUID.c_str() // dev ids + ); + mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); + } } if(listType>0) sequence++; return true; diff --git a/web/hadiscover3.json b/web/hadiscover3.json new file mode 100644 index 00000000..6394f154 --- /dev/null +++ b/web/hadiscover3.json @@ -0,0 +1,12 @@ +{ + "name" : "%s", + "stat_t" : "%s", + "uniq_id" : "%s", + "obj_id" : "%s", + "unit_of_meas" : "%s", + "val_tpl" : "{{value_json['%s']}}", + "dev_cla" : "%s", + "dev" : { + "ids" : [ "%s" ] + } +} \ No newline at end of file From 586c0cba25552ce18c838ed217730df3479279ab Mon Sep 17 00:00:00 2001 From: Daniel Ekman Date: Thu, 23 Dec 2021 17:34:28 +0100 Subject: [PATCH 8/9] include supply volt and temp --- src/mqtt/HomeAssistantMqttHandler.cpp | 75 ++++++++++++++++----------- web/hadiscover1.json | 5 +- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 5f654159..0cdcd661 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -210,31 +210,32 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { } if(sequence % 60 == 1 && listType > 1){ // every 60 ams message, publish mqtt discovery char json[512]; - String haTopic = "homeassistant/sensor/"; - String haUID = "ams-3a08"; - String param = "status"; - snprintf_P(json, sizeof(json), HADISCOVER1_JSON, - "AMS reader status", - (topic + "/state").c_str(), - (topic + "/state").c_str(), - (haUID + "_" + param).c_str(), - (haUID + "_" + param).c_str(), - "dB", - "rssi", - haUID.c_str(), - "AMS reader", - "ESP32", - "2.0.0", - "AmsToMqttBridge" - ); - mqtt->publish(haTopic + haUID + "_" + param + "/config", json); + String haTopic = "homeassistant/sensor/"; // home-assistant discovery topic + String haUID = "ams-3a08"; // unit identity (wifi hostname) - String names[14] = {"Active import", "Reactive import", "Active export", "Reactive export", "L1 current", "L2 current", "L3 current", "L1 voltage", "L2 voltage", "L3 voltage", - "Accumulated active import", "Accumulated active export", "Accumulated reactive import", "Accumulated reactive export"}; - String params[14] = {"P", "Q", "PO", "QO", "I1", "I2", "I3", "U1", "U2", "U3", "tPI", "tPO", "tQI", "tQO"}; - String uom[14] = {"W", "W", "W", "W", "A", "A", "A", "V", "V", "V", "kWh", "kWh", "kWh", "kWh"}; - String devcl[14] = {"power", "power", "power", "power", "current", "current", "current", "voltage", "voltage", "voltage", "energy", "energy", "energy", "energy"}; - for(int i=0;i<4;i++){ + String names[17] = {"Status", "Active import", "Reactive import", "Active export", "Reactive export", "L1 current", "L2 current", "L3 current", "L1 voltage", "L2 voltage", "L3 voltage", + "Accumulated active import", "Accumulated active export", "Accumulated reactive import", "Accumulated reactive export", "Supply volt", "Temperature"}; + String params[17] = {"rssi", "P", "Q", "PO", "QO", "I1", "I2", "I3", "U1", "U2", "U3", "tPI", "tPO", "tQI", "tQO", "vcc", "temp"}; + String uom[17] = {"dB", "W", "W", "W", "W", "A", "A", "A", "V", "V", "V", "kWh", "kWh", "kWh", "kWh", "V", "C"}; + String devcl[17] = {"", "power", "power", "power", "power", "current", "current", "current", "voltage", "voltage", "voltage", "energy", "energy", "energy", "energy", "voltage", "temperature"}; + + snprintf_P(json, sizeof(json), HADISCOVER1_JSON, + names[0].c_str(), // name + (topic + "/state").c_str(), // state_topic + (haUID + "_" + params[0]).c_str(), // unique_id + (haUID + "_" + params[0]).c_str(), // object_id + uom[0].c_str(), // unit_of_measurement + params[0].c_str(), // value_template + haUID.c_str(), // ids + "AMS reader", // name + "ESP32", // model + "2.0.0", // fw version + "AmsToMqttBridge", // manufacturer + ("http://" + haUID + ".local/").c_str() // configuration_url + ); + mqtt->publish(haTopic + haUID + "_" + params[0] + "/config", json); + + for(int i=1;i<5;i++){ snprintf_P(json, sizeof(json), HADISCOVER2_JSON, names[i].c_str(), // name (topic + "/power").c_str(), // state_topic @@ -249,24 +250,24 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); } - for(int i=4;i<10;i++){ + for(int i=5;i<11;i++){ snprintf_P(json, sizeof(json), HADISCOVER3_JSON, names[i].c_str(), // name (topic + "/power").c_str(), // state_topic (haUID + "_" + params[i]).c_str(), // unique_id (haUID + "_" + params[i]).c_str(), // object_id - uom[i].c_str(), // unit_of_measurement - params[i].c_str(), // value_template - devcl[i].c_str(), // device_class + uom[i].c_str(), // unit_of_measurement + params[i].c_str(), // value_template + devcl[i].c_str(), // device_class haUID.c_str() // dev ids ); mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); } - for(int i=10;i<14;i++){ + for(int i=11;i<15;i++){ snprintf_P(json, sizeof(json), HADISCOVER2_JSON, names[i].c_str(), // name - (topic + "/energy").c_str(), // state_topic + (topic + "/energy").c_str(), // state_topic (haUID + "_" + params[i]).c_str(), // unique_id (haUID + "_" + params[i]).c_str(), // object_id uom[i].c_str(), // unit_of_measurement @@ -277,6 +278,20 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { ); mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); } + + for(int i=15;i<17;i++){ + snprintf_P(json, sizeof(json), HADISCOVER3_JSON, + names[i].c_str(), // name + (topic + "/state").c_str(), // state_topic + (haUID + "_" + params[i]).c_str(), // unique_id + (haUID + "_" + params[i]).c_str(), // object_id + uom[i].c_str(), // unit_of_measurement + params[i].c_str(), // value_template + devcl[i].c_str(), // device_class + haUID.c_str() // dev ids + ); + mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); + } } if(listType>0) sequence++; return true; diff --git a/web/hadiscover1.json b/web/hadiscover1.json index 1521981e..1ab5c95c 100644 --- a/web/hadiscover1.json +++ b/web/hadiscover1.json @@ -1,17 +1,16 @@ { "name" : "%s", "stat_t" : "%s", - "json_attr_t" : "%s", "uniq_id" : "%s", "obj_id" : "%s", "unit_of_meas" : "%s", "val_tpl" : "{{value_json['%s']}}", - "json_attr_tpl" : "{{ value_json }}", "dev" : { "ids" : [ "%s" ], "name" : "%s", "mdl" : "%s", "sw" : "%s", - "mf" : "%s" + "mf" : "%s", + "cu" : "%s" } } \ No newline at end of file From f6d2bef285c132d44f3b04e9fbbef858e7dc3c3a Mon Sep 17 00:00:00 2001 From: Daniel Ekman Date: Fri, 14 Jan 2022 00:01:25 +0100 Subject: [PATCH 9/9] reduce discovery code to single loop --- src/mqtt/HomeAssistantMqttHandler.cpp | 128 ++++++++++---------------- web/hadiscover1.json | 13 +-- web/hadiscover2.json | 11 ++- web/hadiscover3.json | 12 --- 4 files changed, 66 insertions(+), 98 deletions(-) delete mode 100644 web/hadiscover3.json diff --git a/src/mqtt/HomeAssistantMqttHandler.cpp b/src/mqtt/HomeAssistantMqttHandler.cpp index 0cdcd661..511e28f1 100644 --- a/src/mqtt/HomeAssistantMqttHandler.cpp +++ b/src/mqtt/HomeAssistantMqttHandler.cpp @@ -8,7 +8,6 @@ #include "web/root/jsonprices_json.h" #include "web/root/hadiscover1_json.h" #include "web/root/hadiscover2_json.h" -#include "web/root/hadiscover3_json.h" bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState) { if(topic.isEmpty() || !mqtt->connected()) @@ -208,88 +207,63 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw) { ); mqtt->publish(topic + "/state", json); } - if(sequence % 60 == 1 && listType > 1){ // every 60 ams message, publish mqtt discovery + + if(sequence % 60 == 1 && listType > 1){ // every 60 ams message, publish mqtt discovery. TODO: publish once with retain char json[512]; String haTopic = "homeassistant/sensor/"; // home-assistant discovery topic String haUID = "ams-3a08"; // unit identity (wifi hostname) - String names[17] = {"Status", "Active import", "Reactive import", "Active export", "Reactive export", "L1 current", "L2 current", "L3 current", "L1 voltage", "L2 voltage", "L3 voltage", - "Accumulated active import", "Accumulated active export", "Accumulated reactive import", "Accumulated reactive export", "Supply volt", "Temperature"}; - String params[17] = {"rssi", "P", "Q", "PO", "QO", "I1", "I2", "I3", "U1", "U2", "U3", "tPI", "tPO", "tQI", "tQO", "vcc", "temp"}; - String uom[17] = {"dB", "W", "W", "W", "W", "A", "A", "A", "V", "V", "V", "kWh", "kWh", "kWh", "kWh", "V", "C"}; - String devcl[17] = {"", "power", "power", "power", "power", "current", "current", "current", "voltage", "voltage", "voltage", "energy", "energy", "energy", "energy", "voltage", "temperature"}; + int sensors = 17; + String topics[sensors] = {"/state", "/state", "/state", "/power", "/power", "/power", "/power", "/power", "/power", "/power", "/power", "/power", "/power", "/energy", "/energy", "/energy", "/energy"}; + String names[sensors] = {"Status", "Supply volt", "Temperature", "Active import", "Reactive import", "Active export", "Reactive export", "L1 current", "L2 current", "L3 current", + "L1 voltage", "L2 voltage", "L3 voltage", "Accumulated active import", "Accumulated active export", "Accumulated reactive import", "Accumulated reactive export"}; + String params[sensors] = {"rssi", "vcc", "temp", "P", "Q", "PO", "QO", "I1", "I2", "I3", "U1", "U2", "U3", "tPI", "tPO", "tQI", "tQO"}; + String uom[sensors] = {"dBm", "V", "C", "W", "W", "W", "W", "A", "A", "A", "V", "V", "V", "kWh", "kWh", "kWh", "kWh"}; + String devcl[sensors] = {"signal_strength", "voltage", "temperature", "power", "power", "power", "power", "current", "current", "current", "voltage", "voltage", "voltage", "energy", "energy", "energy", "energy"}; + String stacl[sensors] = {"", "", "", "measurement", "measurement", "measurement", "measurement", "", "", "", "", "", "", "total_increasing", "total_increasing", "total_increasing", "total_increasing"}; + //String category[sensors] = {"Diagnostic", "Diagnostic", "Diagnostic", "Power", "Power", "Power", "Power", "Voltage", "Voltage", "Voltage", "Current", "Current", "Current", "Energy", "Energy", "Energy", "Energy"}; - snprintf_P(json, sizeof(json), HADISCOVER1_JSON, - names[0].c_str(), // name - (topic + "/state").c_str(), // state_topic - (haUID + "_" + params[0]).c_str(), // unique_id - (haUID + "_" + params[0]).c_str(), // object_id - uom[0].c_str(), // unit_of_measurement - params[0].c_str(), // value_template - haUID.c_str(), // ids - "AMS reader", // name - "ESP32", // model - "2.0.0", // fw version - "AmsToMqttBridge", // manufacturer - ("http://" + haUID + ".local/").c_str() // configuration_url - ); - mqtt->publish(haTopic + haUID + "_" + params[0] + "/config", json); + String haName = "AMS reader"; + String haModel = "ESP32"; + String haVersion = "2.0.0"; + String haManuf = "AmsToMqttBridge"; + String haUrl = "http://" + haUID + ".local/"; - for(int i=1;i<5;i++){ - snprintf_P(json, sizeof(json), HADISCOVER2_JSON, - names[i].c_str(), // name - (topic + "/power").c_str(), // state_topic - (haUID + "_" + params[i]).c_str(), // unique_id - (haUID + "_" + params[i]).c_str(), // object_id - uom[i].c_str(), // unit_of_measurement - params[i].c_str(), // value_template - devcl[i].c_str(), // device_class - "measurement", // state_class - haUID.c_str() // dev ids - ); - mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); - } - - for(int i=5;i<11;i++){ - snprintf_P(json, sizeof(json), HADISCOVER3_JSON, - names[i].c_str(), // name - (topic + "/power").c_str(), // state_topic - (haUID + "_" + params[i]).c_str(), // unique_id - (haUID + "_" + params[i]).c_str(), // object_id - uom[i].c_str(), // unit_of_measurement - params[i].c_str(), // value_template - devcl[i].c_str(), // device_class - haUID.c_str() // dev ids - ); - mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); - } - - for(int i=11;i<15;i++){ - snprintf_P(json, sizeof(json), HADISCOVER2_JSON, - names[i].c_str(), // name - (topic + "/energy").c_str(), // state_topic - (haUID + "_" + params[i]).c_str(), // unique_id - (haUID + "_" + params[i]).c_str(), // object_id - uom[i].c_str(), // unit_of_measurement - params[i].c_str(), // value_template - devcl[i].c_str(), // device_class - "total_increasing", // state_class - haUID.c_str() // dev ids - ); - mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); - } - - for(int i=15;i<17;i++){ - snprintf_P(json, sizeof(json), HADISCOVER3_JSON, - names[i].c_str(), // name - (topic + "/state").c_str(), // state_topic - (haUID + "_" + params[i]).c_str(), // unique_id - (haUID + "_" + params[i]).c_str(), // object_id - uom[i].c_str(), // unit_of_measurement - params[i].c_str(), // value_template - devcl[i].c_str(), // device_class - haUID.c_str() // dev ids - ); + for(int i=0;i 0) { // TODO: reduce to single JSON, state_class: null (witout quotation). or make it some extra optional string that us appended + snprintf_P(json, sizeof(json), HADISCOVER2_JSON, + names[i].c_str(), // name + (topic + topics[i]).c_str(), // state_topic + (haUID + "_" + params[i]).c_str(), // unique_id + (haUID + "_" + params[i]).c_str(), // object_id + uom[i].c_str(), // unit_of_measurement + params[i].c_str(), // value_template + devcl[i].c_str(), // device_class + haUID.c_str(), // dev ids + haName.c_str(), // name + haModel.c_str(), // model + haVersion.c_str(), // fw version + haManuf.c_str(), // manufacturer + haUrl.c_str(), // configuration_url + stacl[i].c_str() // state_class + ); + } else { + snprintf_P(json, sizeof(json), HADISCOVER1_JSON, + names[i].c_str(), // name + (topic + topics[i]).c_str(), // state_topic + (haUID + "_" + params[i]).c_str(), // unique_id + (haUID + "_" + params[i]).c_str(), // object_id + uom[i].c_str(), // unit_of_measurement + params[i].c_str(), // value_template + devcl[i].c_str(), // device_class + haUID.c_str(), // dev ids + haName.c_str(), // name + haModel.c_str(), // model + haVersion.c_str(), // fw version + haManuf.c_str(), // manufacturer + haUrl.c_str() // configuration_url + ); + } mqtt->publish(haTopic + haUID + "_" + params[i] + "/config", json); } } diff --git a/web/hadiscover1.json b/web/hadiscover1.json index 1ab5c95c..984da268 100644 --- a/web/hadiscover1.json +++ b/web/hadiscover1.json @@ -5,12 +5,13 @@ "obj_id" : "%s", "unit_of_meas" : "%s", "val_tpl" : "{{value_json['%s']}}", + "dev_cla" : "%s", "dev" : { - "ids" : [ "%s" ], - "name" : "%s", - "mdl" : "%s", - "sw" : "%s", - "mf" : "%s", - "cu" : "%s" + "ids" : [ "%s" ], + "name" : "%s", + "mdl" : "%s", + "sw" : "%s", + "mf" : "%s", + "cu" : "%s" } } \ No newline at end of file diff --git a/web/hadiscover2.json b/web/hadiscover2.json index 9ec370b2..493312fa 100644 --- a/web/hadiscover2.json +++ b/web/hadiscover2.json @@ -6,8 +6,13 @@ "unit_of_meas" : "%s", "val_tpl" : "{{value_json['%s']}}", "dev_cla" : "%s", - "stat_cla" : "%s", "dev" : { - "ids" : [ "%s" ] - } + "ids" : [ "%s" ], + "name" : "%s", + "mdl" : "%s", + "sw" : "%s", + "mf" : "%s", + "cu" : "%s" + }, + "stat_cla" : "%s" } \ No newline at end of file diff --git a/web/hadiscover3.json b/web/hadiscover3.json deleted file mode 100644 index 6394f154..00000000 --- a/web/hadiscover3.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name" : "%s", - "stat_t" : "%s", - "uniq_id" : "%s", - "obj_id" : "%s", - "unit_of_meas" : "%s", - "val_tpl" : "{{value_json['%s']}}", - "dev_cla" : "%s", - "dev" : { - "ids" : [ "%s" ] - } -} \ No newline at end of file