diff --git a/lib/AmsJsonGenerator/include/AmsJsonGenerator.h b/lib/AmsJsonGenerator/include/AmsJsonGenerator.h new file mode 100644 index 00000000..70d32a13 --- /dev/null +++ b/lib/AmsJsonGenerator/include/AmsJsonGenerator.h @@ -0,0 +1,9 @@ +#pragma once + +#include "AmsDataStorage.h" + +class AmsJsonGenerator { +public: + static void generateDayPlotJson(AmsDataStorage* ds, char* buf, size_t bufSize); + static void generateMonthPlotJson(AmsDataStorage* ds, char* buf, size_t bufSize); +}; \ No newline at end of file diff --git a/lib/AmsJsonGenerator/src/AmsJsonGenerator.cpp b/lib/AmsJsonGenerator/src/AmsJsonGenerator.cpp new file mode 100644 index 00000000..81239405 --- /dev/null +++ b/lib/AmsJsonGenerator/src/AmsJsonGenerator.cpp @@ -0,0 +1,17 @@ +#include "AmsJsonGenerator.h" + +void AmsJsonGenerator::generateDayPlotJson(AmsDataStorage* ds, char* buf, size_t bufSize) { + uint16_t pos = snprintf_P(buf, bufSize, PSTR("{\"unit\":\"kwh\"")); + for(uint8_t i = 0; i < 24; i++) { + pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"i%02d\":%.3f,\"e%02d\":%.3f"), i, ds->getHourImport(i) / 1000.0, i, ds->getHourExport(i) / 1000.0); + } + snprintf_P(buf+pos, bufSize-pos, PSTR("}")); +} + +void AmsJsonGenerator::generateMonthPlotJson(AmsDataStorage* ds, char* buf, size_t bufSize) { + uint16_t pos = snprintf_P(buf, bufSize, PSTR("{\"unit\":\"kwh\"")); + for(uint8_t i = 1; i < 32; i++) { + pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"i%02d\":%.3f,\"e%02d\":%.3f"), i, ds->getDayImport(i) / 1000.0, i, ds->getDayExport(i) / 1000.0); + } + snprintf_P(buf+pos, bufSize-pos, PSTR("}")); +} diff --git a/lib/AmsMqttHandler/src/AmsMqttHandler.cpp b/lib/AmsMqttHandler/src/AmsMqttHandler.cpp index fe217492..44001488 100644 --- a/lib/AmsMqttHandler/src/AmsMqttHandler.cpp +++ b/lib/AmsMqttHandler/src/AmsMqttHandler.cpp @@ -124,18 +124,6 @@ bool AmsMqttHandler::connect() { #endif debugger->printf_P(PSTR("Successfully connected to MQTT\n")); mqtt.onMessage(std::bind(&AmsMqttHandler::onMessage, this, std::placeholders::_1, std::placeholders::_2)); - if(strlen(mqttConfig.subscribeTopic) > 0) { - #if defined(AMS_REMOTE_DEBUG) - if (debugger->isActive(RemoteDebug::INFO)) - #endif - debugger->printf_P(PSTR(" Subscribing to [%s]\n"), mqttConfig.subscribeTopic); - if(!mqtt.subscribe(mqttConfig.subscribeTopic)) { - #if defined(AMS_REMOTE_DEBUG) - if (debugger->isActive(RemoteDebug::ERROR)) - #endif - debugger->printf_P(PSTR(" Unable to subscribe to to [%s]\n"), mqttConfig.subscribeTopic); - } - } mqtt.publish(statusTopic, "online", true, 0); mqtt.loop(); postConnect(); diff --git a/lib/JsonMqttHandler/include/JsonMqttHandler.h b/lib/JsonMqttHandler/include/JsonMqttHandler.h index dc997b9b..0b23bd8f 100644 --- a/lib/JsonMqttHandler/include/JsonMqttHandler.h +++ b/lib/JsonMqttHandler/include/JsonMqttHandler.h @@ -12,14 +12,18 @@ class JsonMqttHandler : public AmsMqttHandler { public: #if defined(AMS_REMOTE_DEBUG) - JsonMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf, HwTools* hw, AmsFirmwareUpdater* updater) : AmsMqttHandler(mqttConfig, debugger, buf, updater) { - this->hw = hw; - }; + JsonMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf, HwTools* hw, AmsDataStorage* ds, AmsFirmwareUpdater* updater) : AmsMqttHandler(mqttConfig, debugger, buf, updater) { #else - JsonMqttHandler(MqttConfig& mqttConfig, Stream* debugger, char* buf, HwTools* hw) : AmsMqttHandler(mqttConfig, debugger, buf) { - this->hw = hw; - }; + JsonMqttHandler(MqttConfig& mqttConfig, Stream* debugger, char* buf, HwTools* hw, AmsDataStorage* ds, AmsFirmwareUpdater* updater) : AmsMqttHandler(mqttConfig, debugger, buf, updater) { #endif + subTopic = String(mqttConfig.subscribeTopic); + if(subTopic.isEmpty()) { + String pubTopic = String(mqttConfig.publishTopic); + subTopic = pubTopic+"/command"; + } + this->hw = hw; + this->ds = ds; + }; bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, PriceService* ps); bool publishTemperatures(AmsConfiguration*, HwTools*); bool publishPrices(PriceService*); @@ -27,12 +31,17 @@ public: bool publishRaw(String data); bool publishFirmware(); + bool postConnect(); + void onMessage(String &topic, String &payload); uint8_t getFormat(); private: + String subTopic; HwTools* hw; + AmsDataStorage* ds; + uint16_t appendJsonHeader(AmsData* data); uint16_t appendJsonFooter(EnergyAccounting* ea, uint16_t pos); bool publishList1(AmsData* data, EnergyAccounting* ea); diff --git a/lib/JsonMqttHandler/src/JsonMqttHandler.cpp b/lib/JsonMqttHandler/src/JsonMqttHandler.cpp index 530eab9d..1ba9c96b 100644 --- a/lib/JsonMqttHandler/src/JsonMqttHandler.cpp +++ b/lib/JsonMqttHandler/src/JsonMqttHandler.cpp @@ -8,6 +8,18 @@ #include "FirmwareVersion.h" #include "hexutils.h" #include "Uptime.h" +#include "AmsJsonGenerator.h" + +bool JsonMqttHandler::postConnect() { + if(!subTopic.isEmpty() && !mqtt.subscribe(subTopic)) { + #if defined(AMS_REMOTE_DEBUG) + if (debugger->isActive(RemoteDebug::ERROR)) + #endif + debugger->printf_P(PSTR(" Unable to subscribe to to [%s]\n"), subTopic.c_str()); + return false; + } + return true; +} bool JsonMqttHandler::publish(AmsData* update, AmsData* previousState, EnergyAccounting* ea, PriceService* ps) { if(strlen(mqttConfig.publishTopic) == 0) { @@ -447,11 +459,35 @@ bool JsonMqttHandler::publishFirmware() { } void JsonMqttHandler::onMessage(String &topic, String &payload) { - if(strncmp(topic.c_str(), mqttConfig.subscribeTopic, 12) == 0) { + if(strlen(mqttConfig.publishTopic) == 0 || !mqtt.connected()) + return; + + #if defined(AMS_REMOTE_DEBUG) + if (debugger->isActive(RemoteDebug::INFO)) + #endif + debugger->printf_P(PSTR("Received command [%s] to [%s]\n"), payload.c_str(), topic.c_str()); + + if(topic.equals(subTopic)) { + #if defined(AMS_REMOTE_DEBUG) + if (debugger->isActive(RemoteDebug::DEBUG)) + #endif + debugger->printf_P(PSTR(" - this is our subscribed topic\n")); if(payload.equals("fwupgrade")) { if(strcmp(updater->getNextVersion(), FirmwareVersion::VersionString) != 0) { updater->setTargetVersion(updater->getNextVersion()); } + } else if(payload.equals("dayplot")) { + char pubTopic[192]; + snprintf_P(pubTopic, 192, PSTR("%s/dayplot"), mqttConfig.publishTopic); + AmsJsonGenerator::generateDayPlotJson(ds, json, BufferSize); + bool ret = mqtt.publish(pubTopic, json); + loop(); + } else if(payload.equals("monthplot")) { + char pubTopic[192]; + snprintf_P(pubTopic, 192, PSTR("%s/monthplot"), mqttConfig.publishTopic); + AmsJsonGenerator::generateMonthPlotJson(ds, json, BufferSize); + bool ret = mqtt.publish(pubTopic, json); + loop(); } } } diff --git a/lib/SvelteUi/src/AmsWebServer.cpp b/lib/SvelteUi/src/AmsWebServer.cpp index 81a92bfa..dd91f1ca 100644 --- a/lib/SvelteUi/src/AmsWebServer.cpp +++ b/lib/SvelteUi/src/AmsWebServer.cpp @@ -9,6 +9,7 @@ #include "FirmwareVersion.h" #include "base64.h" #include "hexutils.h" +#include "AmsJsonGenerator.h" #include "html/index_html.h" #include "html/index_css.h" @@ -682,12 +683,7 @@ void AmsWebServer::dayplotJson() { if(ds == NULL) { notFound(); } else { - uint16_t pos = snprintf_P(buf, BufferSize, PSTR("{\"unit\":\"kwh\"")); - for(uint8_t i = 0; i < 24; i++) { - pos += snprintf_P(buf+pos, BufferSize-pos, PSTR(",\"i%02d\":%.3f,\"e%02d\":%.3f"), i, ds->getHourImport(i) / 1000.0, i, ds->getHourExport(i) / 1000.0); - } - snprintf_P(buf+pos, BufferSize-pos, PSTR("}")); - + AmsJsonGenerator::generateDayPlotJson(ds, buf, BufferSize); addConditionalCloudHeaders(); server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); @@ -705,12 +701,7 @@ void AmsWebServer::monthplotJson() { if(ds == NULL) { notFound(); } else { - uint16_t pos = snprintf_P(buf, BufferSize, PSTR("{\"unit\":\"kwh\"")); - for(uint8_t i = 1; i < 32; i++) { - pos += snprintf_P(buf+pos, BufferSize-pos, PSTR(",\"i%02d\":%.3f,\"e%02d\":%.3f"), i, ds->getDayImport(i) / 1000.0, i, ds->getDayExport(i) / 1000.0); - } - snprintf_P(buf+pos, BufferSize-pos, PSTR("}")); - + AmsJsonGenerator::generateMonthPlotJson(ds, buf, BufferSize); addConditionalCloudHeaders(); server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); diff --git a/platformio.ini b/platformio.ini index 8416b12c..288e83d1 100755 --- a/platformio.ini +++ b/platformio.ini @@ -2,7 +2,7 @@ extra_configs = platformio-user.ini [common] -lib_deps = EEPROM, LittleFS, DNSServer, 256dpi/MQTT@2.5.2, OneWireNg@0.13.3, DallasTemperature@4.0.4, https://github.com/gskjold/RemoteDebug.git, PaulStoffregen/Time@1.6.1, JChristensen/Timezone@1.2.4, bblanchon/ArduinoJson@7.0.4, FirmwareVersion, AmsConfiguration, AmsData, AmsDataStorage, HwTools, Uptime, AmsDecoder, PriceService, EnergyAccounting, AmsFirmwareUpdater, AmsMqttHandler, RawMqttHandler, JsonMqttHandler, DomoticzMqttHandler, HomeAssistantMqttHandler, PassthroughMqttHandler, RealtimePlot, ConnectionHandler, MeterCommunicators +lib_deps = EEPROM, LittleFS, DNSServer, 256dpi/MQTT@2.5.2, OneWireNg@0.13.3, DallasTemperature@4.0.4, https://github.com/gskjold/RemoteDebug.git, PaulStoffregen/Time@1.6.1, JChristensen/Timezone@1.2.4, bblanchon/ArduinoJson@7.0.4, FirmwareVersion, AmsConfiguration, AmsData, AmsDataStorage, HwTools, Uptime, AmsDecoder, PriceService, EnergyAccounting, AmsFirmwareUpdater, AmsJsonGenerator, AmsMqttHandler, RawMqttHandler, JsonMqttHandler, DomoticzMqttHandler, HomeAssistantMqttHandler, PassthroughMqttHandler, RealtimePlot, ConnectionHandler, MeterCommunicators lib_ignore = OneWire extra_scripts = pre:scripts/addversion.py diff --git a/src/AmsToMqttBridge.cpp b/src/AmsToMqttBridge.cpp index 84418300..ffec7664 100644 --- a/src/AmsToMqttBridge.cpp +++ b/src/AmsToMqttBridge.cpp @@ -625,7 +625,7 @@ void loop() { chipId = ESP.getChipId(); #endif strcpy(energySpeedometerConfig.clientId, (String("ams") + String(chipId, HEX)).c_str()); - energySpeedometer = new JsonMqttHandler(energySpeedometerConfig, &Debug, (char*) commonBuffer, &hw, &updater); + energySpeedometer = new JsonMqttHandler(energySpeedometerConfig, &Debug, (char*) commonBuffer, &hw, &ds, &updater); energySpeedometer->setCaVerification(false); } if(!energySpeedometer->connected()) { @@ -1560,7 +1560,7 @@ void MQTT_connect() { case 0: case 5: case 6: - mqttHandler = new JsonMqttHandler(mqttConfig, &Debug, (char*) commonBuffer, &hw, &updater); + mqttHandler = new JsonMqttHandler(mqttConfig, &Debug, (char*) commonBuffer, &hw, &ds, &updater); break; case 1: case 2: