mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-14 15:54:47 +00:00
Merge branch 'mqtt_changes'
This commit is contained in:
commit
0fa178a617
@ -33,7 +33,8 @@ struct SystemConfig {
|
||||
bool userConfigured;
|
||||
uint8_t dataCollectionConsent; // 0 = unknown, 1 = accepted, 2 = declined
|
||||
char country[3];
|
||||
}; // 7
|
||||
uint8_t energyspeedometer;
|
||||
}; // 8
|
||||
|
||||
struct WiFiConfig {
|
||||
char ssid[32];
|
||||
@ -231,6 +232,8 @@ public:
|
||||
|
||||
bool getSystemConfig(SystemConfig&);
|
||||
bool setSystemConfig(SystemConfig&);
|
||||
bool isSystemConfigChanged();
|
||||
void ackSystemConfigChanged();
|
||||
|
||||
bool getWiFiConfig(WiFiConfig&);
|
||||
bool setWiFiConfig(WiFiConfig&);
|
||||
@ -318,7 +321,7 @@ protected:
|
||||
private:
|
||||
uint8_t configVersion = 0;
|
||||
|
||||
bool wifiChanged, mqttChanged, meterChanged = true, ntpChanged = true, entsoeChanged = false, energyAccountingChanged = true;
|
||||
bool sysChanged = false, wifiChanged = false, mqttChanged = false, meterChanged = true, ntpChanged = true, entsoeChanged = false, energyAccountingChanged = true;
|
||||
|
||||
uint8_t tempSensorCount = 0;
|
||||
TempSensorConfig** tempSensors = NULL;
|
||||
|
||||
@ -13,12 +13,22 @@ bool AmsConfiguration::getSystemConfig(SystemConfig& config) {
|
||||
config.vendorConfigured = false;
|
||||
config.userConfigured = false;
|
||||
config.dataCollectionConsent = 0;
|
||||
config.energyspeedometer = 0;
|
||||
strcpy(config.country, "");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool AmsConfiguration::setSystemConfig(SystemConfig& config) {
|
||||
SystemConfig existing;
|
||||
if(getSystemConfig(existing)) {
|
||||
sysChanged |= config.boardType != existing.boardType;
|
||||
sysChanged |= config.vendorConfigured != existing.vendorConfigured;
|
||||
sysChanged |= config.userConfigured != existing.userConfigured;
|
||||
sysChanged |= config.dataCollectionConsent != existing.dataCollectionConsent;
|
||||
sysChanged |= strcmp(config.country, existing.country) != 0;
|
||||
sysChanged |= config.energyspeedometer != existing.energyspeedometer;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
stripNonAscii((uint8_t*) config.country, 2);
|
||||
EEPROM.put(CONFIG_SYSTEM_START, config);
|
||||
@ -27,6 +37,14 @@ bool AmsConfiguration::setSystemConfig(SystemConfig& config) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::isSystemConfigChanged() {
|
||||
return sysChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::ackSystemConfigChanged() {
|
||||
sysChanged = false;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::getWiFiConfig(WiFiConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
@ -85,7 +103,7 @@ void AmsConfiguration::clearWifi(WiFiConfig& config) {
|
||||
|
||||
uint16_t chipId;
|
||||
#if defined(ESP32)
|
||||
chipId = ESP.getEfuseMac();
|
||||
chipId = ( ESP.getEfuseMac() >> 32 ) % 0xFFFFFFFF;
|
||||
config.power = 195;
|
||||
#else
|
||||
chipId = ESP.getChipId();
|
||||
@ -738,6 +756,7 @@ void AmsConfiguration::clear() {
|
||||
EEPROM.get(CONFIG_SYSTEM_START, sys);
|
||||
sys.userConfigured = false;
|
||||
sys.dataCollectionConsent = 0;
|
||||
sys.energyspeedometer = 0;
|
||||
strcpy(sys.country, "");
|
||||
EEPROM.put(CONFIG_SYSTEM_START, sys);
|
||||
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
#ifndef _AMSMQTTHANDLER_H
|
||||
#define _AMSMQTTHANDLER_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <MQTT.h>
|
||||
#include "AmsData.h"
|
||||
#include "AmsConfiguration.h"
|
||||
#include "EnergyAccounting.h"
|
||||
#include "HwTools.h"
|
||||
#include "EntsoeApi.h"
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <esp_task_wdt.h>
|
||||
#endif
|
||||
|
||||
class AmsMqttHandler {
|
||||
public:
|
||||
AmsMqttHandler(MQTTClient* mqtt, char* buf) {
|
||||
this->mqtt = mqtt;
|
||||
this->json = buf;
|
||||
};
|
||||
virtual ~AmsMqttHandler() {};
|
||||
|
||||
virtual bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, EntsoeApi* eapi);
|
||||
virtual bool publishTemperatures(AmsConfiguration*, HwTools*);
|
||||
virtual bool publishPrices(EntsoeApi* eapi);
|
||||
virtual bool publishSystem(HwTools*, EntsoeApi*, EnergyAccounting*);
|
||||
|
||||
protected:
|
||||
MQTTClient* mqtt;
|
||||
char* json;
|
||||
uint16_t BufferSize = 2048;
|
||||
|
||||
bool loop();
|
||||
};
|
||||
|
||||
#endif
|
||||
60
lib/AmsMqttHandler/include/AmsMqttHandler.h
Normal file
60
lib/AmsMqttHandler/include/AmsMqttHandler.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef _AMSMQTTHANDLER_H
|
||||
#define _AMSMQTTHANDLER_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <MQTT.h>
|
||||
#include "AmsData.h"
|
||||
#include "AmsConfiguration.h"
|
||||
#include "EnergyAccounting.h"
|
||||
#include "HwTools.h"
|
||||
#include "EntsoeApi.h"
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <esp_task_wdt.h>
|
||||
#endif
|
||||
|
||||
class AmsMqttHandler {
|
||||
public:
|
||||
AmsMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf) {
|
||||
this->mqttConfig = mqttConfig;
|
||||
this->debugger = debugger;
|
||||
this->json = buf;
|
||||
mqtt.dropOverflow(true);
|
||||
};
|
||||
|
||||
void setCaVerification(bool);
|
||||
|
||||
bool connect();
|
||||
void disconnect();
|
||||
lwmqtt_err_t lastError();
|
||||
bool connected();
|
||||
bool loop();
|
||||
|
||||
virtual uint8_t getFormat() { return 0; };
|
||||
|
||||
virtual bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, EntsoeApi* eapi) { return false; };
|
||||
virtual bool publishTemperatures(AmsConfiguration*, HwTools*) { return false; };
|
||||
virtual bool publishPrices(EntsoeApi* eapi) { return false; };
|
||||
virtual bool publishSystem(HwTools*, EntsoeApi*, EnergyAccounting*) { return false; };
|
||||
virtual bool publishRaw(String data) { return false; };
|
||||
|
||||
virtual ~AmsMqttHandler() {
|
||||
if(mqttClient != NULL) {
|
||||
mqttClient->stop();
|
||||
delete mqttClient;
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
RemoteDebug* debugger;
|
||||
MqttConfig mqttConfig;
|
||||
MQTTClient mqtt = MQTTClient(256);
|
||||
unsigned long lastMqttRetry = -10000;
|
||||
bool caVerification = true;
|
||||
WiFiClient *mqttClient = NULL;
|
||||
WiFiClientSecure *mqttSecureClient = NULL;
|
||||
char* json;
|
||||
uint16_t BufferSize = 2048;
|
||||
};
|
||||
|
||||
#endif
|
||||
165
lib/AmsMqttHandler/src/AmsMqttHandler.cpp
Normal file
165
lib/AmsMqttHandler/src/AmsMqttHandler.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
#include "AmsMqttHandler.h"
|
||||
#include "FirmwareVersion.h"
|
||||
#include "AmsStorage.h"
|
||||
#include "LittleFS.h"
|
||||
|
||||
void AmsMqttHandler::setCaVerification(bool caVerification) {
|
||||
this->caVerification = caVerification;
|
||||
}
|
||||
|
||||
bool AmsMqttHandler::connect() {
|
||||
if(millis() - lastMqttRetry < 10000) {
|
||||
yield();
|
||||
return false;
|
||||
}
|
||||
lastMqttRetry = millis();
|
||||
|
||||
time_t epoch = time(nullptr);
|
||||
|
||||
if(mqttConfig.ssl) {
|
||||
if(epoch < FirmwareVersion::BuildEpoch) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("NTP not ready for MQTT SSL\n"));
|
||||
return false;
|
||||
}
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("MQTT SSL is configured (%dkb free heap)\n"), ESP.getFreeHeap());
|
||||
if(mqttSecureClient == NULL) {
|
||||
mqttSecureClient = new WiFiClientSecure();
|
||||
#if defined(ESP8266)
|
||||
mqttSecureClient->setBufferSizes(512, 512);
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("ESP8266 firmware does not have enough memory...\n"));
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if(caVerification && LittleFS.begin()) {
|
||||
File file;
|
||||
|
||||
if(LittleFS.exists(FILE_MQTT_CA)) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("Found MQTT CA file (%dkb free heap)\n"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CA, (char*) "r");
|
||||
#if defined(ESP8266)
|
||||
BearSSL::X509List *serverTrustedCA = new BearSSL::X509List(file);
|
||||
mqttSecureClient->setTrustAnchors(serverTrustedCA);
|
||||
#elif defined(ESP32)
|
||||
if(mqttSecureClient->loadCACert(file, file.size())) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("CA accepted\n"));
|
||||
} else {
|
||||
if(debugger->isActive(RemoteDebug::WARNING)) debugger->printf_P(PSTR("CA was rejected\n"));
|
||||
delete mqttSecureClient;
|
||||
mqttSecureClient = NULL;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
file.close();
|
||||
|
||||
if(LittleFS.exists(FILE_MQTT_CERT) && LittleFS.exists(FILE_MQTT_KEY)) {
|
||||
#if defined(ESP8266)
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("Found MQTT certificate file (%dkb free heap)\n"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CERT, (char*) "r");
|
||||
BearSSL::X509List *serverCertList = new BearSSL::X509List(file);
|
||||
file.close();
|
||||
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("Found MQTT key file (%dkb free heap)\n"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_KEY, (char*) "r");
|
||||
BearSSL::PrivateKey *serverPrivKey = new BearSSL::PrivateKey(file);
|
||||
file.close();
|
||||
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("Setting client certificates (%dkb free heap)"), ESP.getFreeHeap());
|
||||
mqttSecureClient->setClientRSACert(serverCertList, serverPrivKey);
|
||||
#elif defined(ESP32)
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("Found MQTT certificate file (%dkb free heap)\n"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CERT, (char*) "r");
|
||||
mqttSecureClient->loadCertificate(file, file.size());
|
||||
file.close();
|
||||
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("Found MQTT key file (%dkb free heap)\n"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_KEY, (char*) "r");
|
||||
mqttSecureClient->loadPrivateKey(file, file.size());
|
||||
file.close();
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("No CA, disabling validation\n"));
|
||||
mqttSecureClient->setInsecure();
|
||||
}
|
||||
LittleFS.end();
|
||||
} else {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("CA verification disabled\n"));
|
||||
mqttSecureClient->setInsecure();
|
||||
}
|
||||
mqttClient = mqttSecureClient;
|
||||
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("MQTT SSL setup complete (%dkb free heap)\n"), ESP.getFreeHeap());
|
||||
}
|
||||
}
|
||||
|
||||
if(mqttClient == NULL) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("No SSL, using client without SSL support\n"));
|
||||
mqttClient = new WiFiClient();
|
||||
}
|
||||
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("Connecting to MQTT %s:%d\n"), mqttConfig.host, mqttConfig.port);
|
||||
|
||||
mqtt.begin(mqttConfig.host, mqttConfig.port, *mqttClient);
|
||||
|
||||
#if defined(ESP8266)
|
||||
if(mqttSecureClient) {
|
||||
time_t epoch = time(nullptr);
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("Setting NTP time %lu for secure MQTT connection\n"), epoch);
|
||||
mqttSecureClient->setX509Time(epoch);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Connect to a unsecure or secure MQTT server
|
||||
if ((strlen(mqttConfig.username) == 0 && mqtt.connect(mqttConfig.clientId)) ||
|
||||
(strlen(mqttConfig.username) > 0 && mqtt.connect(mqttConfig.clientId, mqttConfig.username, mqttConfig.password))) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("Successfully connected to MQTT!\n"));
|
||||
return true;
|
||||
} else {
|
||||
if (debugger->isActive(RemoteDebug::ERROR)) {
|
||||
debugger->printf_P(PSTR("Failed to connect to MQTT: %d\n"), mqtt.lastError());
|
||||
#if defined(ESP8266)
|
||||
if(mqttSecureClient) {
|
||||
mqttSecureClient->getLastSSLError((char*) json, BufferSize);
|
||||
debugger->println((char*) json);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AmsMqttHandler::disconnect() {
|
||||
mqtt.disconnect();
|
||||
mqtt.loop();
|
||||
delay(10);
|
||||
yield();
|
||||
|
||||
if(mqttClient != NULL) {
|
||||
mqttClient->stop();
|
||||
delete mqttClient;
|
||||
mqttClient = NULL;
|
||||
if(mqttSecureClient != NULL) {
|
||||
mqttSecureClient = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lwmqtt_err_t AmsMqttHandler::lastError() {
|
||||
return mqtt.lastError();
|
||||
}
|
||||
|
||||
bool AmsMqttHandler::connected() {
|
||||
return mqtt.connected();
|
||||
}
|
||||
|
||||
bool AmsMqttHandler::loop() {
|
||||
bool ret = mqtt.loop();
|
||||
delay(10);
|
||||
yield();
|
||||
#if defined(ESP32)
|
||||
esp_task_wdt_reset();
|
||||
#elif defined(ESP8266)
|
||||
ESP.wdtFeed();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@ -6,13 +6,16 @@
|
||||
|
||||
class DomoticzMqttHandler : public AmsMqttHandler {
|
||||
public:
|
||||
DomoticzMqttHandler(MQTTClient* mqtt, char* buf, DomoticzConfig config) : AmsMqttHandler(mqtt, buf) {
|
||||
DomoticzMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf, DomoticzConfig config) : AmsMqttHandler(mqttConfig, debugger, buf) {
|
||||
this->config = config;
|
||||
};
|
||||
bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, EntsoeApi* eapi);
|
||||
bool publishTemperatures(AmsConfiguration*, HwTools*);
|
||||
bool publishPrices(EntsoeApi*);
|
||||
bool publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea);
|
||||
bool publishRaw(String data);
|
||||
|
||||
uint8_t getFormat();
|
||||
|
||||
private:
|
||||
DomoticzConfig config;
|
||||
|
||||
@ -14,7 +14,7 @@ bool DomoticzMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyA
|
||||
config.elidx,
|
||||
val
|
||||
);
|
||||
ret = mqtt->publish(F("domoticz/in"), json);
|
||||
ret = mqtt.publish(F("domoticz/in"), json);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ bool DomoticzMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyA
|
||||
config.vl1idx,
|
||||
val
|
||||
);
|
||||
ret |= mqtt->publish(F("domoticz/in"), json);
|
||||
ret |= mqtt.publish(F("domoticz/in"), json);
|
||||
}
|
||||
|
||||
if (config.vl2idx > 0){
|
||||
@ -38,7 +38,7 @@ bool DomoticzMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyA
|
||||
config.vl2idx,
|
||||
val
|
||||
);
|
||||
ret |= mqtt->publish(F("domoticz/in"), json);
|
||||
ret |= mqtt.publish(F("domoticz/in"), json);
|
||||
}
|
||||
|
||||
if (config.vl3idx > 0){
|
||||
@ -48,7 +48,7 @@ bool DomoticzMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyA
|
||||
config.vl3idx,
|
||||
val
|
||||
);
|
||||
ret |= mqtt->publish(F("domoticz/in"), json);
|
||||
ret |= mqtt.publish(F("domoticz/in"), json);
|
||||
}
|
||||
|
||||
if (config.cl1idx > 0){
|
||||
@ -58,7 +58,7 @@ bool DomoticzMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyA
|
||||
config.cl1idx,
|
||||
val
|
||||
);
|
||||
ret |= mqtt->publish(F("domoticz/in"), json);
|
||||
ret |= mqtt.publish(F("domoticz/in"), json);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -74,3 +74,11 @@ bool DomoticzMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
bool DomoticzMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t DomoticzMqttHandler::getFormat() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
bool DomoticzMqttHandler::publishRaw(String data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -7,12 +7,12 @@
|
||||
|
||||
class HomeAssistantMqttHandler : public AmsMqttHandler {
|
||||
public:
|
||||
HomeAssistantMqttHandler(MQTTClient* mqtt, char* buf, const char* clientId, const char* topic, uint8_t boardType, HomeAssistantConfig config, HwTools* hw) : AmsMqttHandler(mqtt, buf) {
|
||||
this->clientId = clientId;
|
||||
this->topic = String(topic);
|
||||
HomeAssistantMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf, uint8_t boardType, HomeAssistantConfig config, HwTools* hw) : AmsMqttHandler(mqttConfig, debugger, buf) {
|
||||
this->hw = hw;
|
||||
l1Init = l2Init = l2eInit = l3Init = l3eInit = l4Init = l4eInit = rtInit = rteInit = pInit = sInit = false;
|
||||
|
||||
topic = String(mqttConfig.publishTopic);
|
||||
|
||||
if(strlen(config.discoveryNameTag) > 0) {
|
||||
snprintf_P(buf, 128, PSTR("AMS reader (%s)"), config.discoveryNameTag);
|
||||
deviceName = String(buf);
|
||||
@ -56,11 +56,13 @@ public:
|
||||
bool publishTemperatures(AmsConfiguration*, HwTools*);
|
||||
bool publishPrices(EntsoeApi*);
|
||||
bool publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea);
|
||||
bool publishRaw(String data);
|
||||
|
||||
protected:
|
||||
bool loop();
|
||||
uint8_t getFormat();
|
||||
|
||||
private:
|
||||
String topic;
|
||||
|
||||
String deviceName;
|
||||
String deviceModel;
|
||||
String deviceUid;
|
||||
@ -74,8 +76,6 @@ private:
|
||||
bool tInit[32] = {false};
|
||||
bool prInit[38] = {false};
|
||||
|
||||
String clientId;
|
||||
String topic;
|
||||
HwTools* hw;
|
||||
|
||||
bool publishList1(AmsData* data, EnergyAccounting* ea);
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#endif
|
||||
|
||||
bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, EntsoeApi* eapi) {
|
||||
if(topic.isEmpty() || !mqtt->connected())
|
||||
if(topic.isEmpty() || !mqtt.connected())
|
||||
return false;
|
||||
|
||||
if(data->getListType() >= 3) { // publish energy counts
|
||||
@ -45,7 +45,7 @@ bool HomeAssistantMqttHandler::publishList1(AmsData* data, EnergyAccounting* ea)
|
||||
snprintf_P(json, BufferSize, HA1_JSON,
|
||||
data->getActiveImportPower()
|
||||
);
|
||||
return mqtt->publish(topic + "/power", json);
|
||||
return mqtt.publish(topic + "/power", json);
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea) {
|
||||
@ -66,7 +66,7 @@ bool HomeAssistantMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea)
|
||||
data->getL2Voltage(),
|
||||
data->getL3Voltage()
|
||||
);
|
||||
return mqtt->publish(topic + "/power", json);
|
||||
return mqtt.publish(topic + "/power", json);
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea) {
|
||||
@ -79,7 +79,7 @@ bool HomeAssistantMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea)
|
||||
data->getReactiveExportCounter(),
|
||||
data->getMeterTimestamp()
|
||||
);
|
||||
return mqtt->publish(topic + "/energy", json);
|
||||
return mqtt.publish(topic + "/energy", json);
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea) {
|
||||
@ -110,7 +110,7 @@ bool HomeAssistantMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea)
|
||||
data->getPowerFactor() == 0 ? 1 : data->getL2PowerFactor(),
|
||||
data->getPowerFactor() == 0 ? 1 : data->getL3PowerFactor()
|
||||
);
|
||||
return mqtt->publish(topic + "/power", json);
|
||||
return mqtt.publish(topic + "/power", json);
|
||||
}
|
||||
|
||||
String HomeAssistantMqttHandler::getMeterModel(AmsData* data) {
|
||||
@ -146,7 +146,7 @@ bool HomeAssistantMqttHandler::publishRealtime(AmsData* data, EnergyAccounting*
|
||||
ea->getProducedThisMonth(),
|
||||
ea->getIncomeThisMonth()
|
||||
);
|
||||
return mqtt->publish(topic + "/realtime", json);
|
||||
return mqtt.publish(topic + "/realtime", json);
|
||||
}
|
||||
|
||||
|
||||
@ -174,13 +174,13 @@ bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwT
|
||||
}
|
||||
char* pos = buf+strlen(buf);
|
||||
snprintf_P(count == 0 ? pos : pos-1, 8, PSTR("}}"));
|
||||
bool ret = mqtt->publish(topic + "/temperatures", buf);
|
||||
bool ret = mqtt.publish(topic + "/temperatures", buf);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
if(topic.isEmpty() || !mqtt->connected())
|
||||
if(topic.isEmpty() || !mqtt.connected())
|
||||
return false;
|
||||
if(eapi->getValueForHour(0) == ENTSOE_NO_VALUE)
|
||||
return false;
|
||||
@ -310,13 +310,13 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
ts3hr,
|
||||
ts6hr
|
||||
);
|
||||
bool ret = mqtt->publish(topic + "/prices", json, true, 0);
|
||||
bool ret = mqtt.publish(topic + "/prices", json, true, 0);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) {
|
||||
if(topic.isEmpty() || !mqtt->connected())
|
||||
if(topic.isEmpty() || !mqtt.connected())
|
||||
return false;
|
||||
|
||||
publishSystemSensors();
|
||||
@ -324,14 +324,14 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, Energ
|
||||
|
||||
snprintf_P(json, BufferSize, JSONSYS_JSON,
|
||||
WiFi.macAddress().c_str(),
|
||||
clientId.c_str(),
|
||||
mqttConfig.clientId,
|
||||
(uint32_t) (millis64()/1000),
|
||||
hw->getVcc(),
|
||||
hw->getWifiRssi(),
|
||||
hw->getTemperature(),
|
||||
FirmwareVersion::VersionString
|
||||
);
|
||||
bool ret = mqtt->publish(topic + "/state", json);
|
||||
bool ret = mqtt.publish(topic + "/state", json);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
@ -345,7 +345,7 @@ void HomeAssistantMqttHandler::publishSensor(const HomeAssistantSensor& sensor)
|
||||
snprintf_P(json, BufferSize, HADISCOVER_JSON,
|
||||
sensorNamePrefix.c_str(),
|
||||
sensor.name,
|
||||
topic.c_str(), sensor.topic,
|
||||
mqttConfig.publishTopic, sensor.topic,
|
||||
deviceUid.c_str(), uid.c_str(),
|
||||
deviceUid.c_str(), uid.c_str(),
|
||||
sensor.uom,
|
||||
@ -363,7 +363,7 @@ void HomeAssistantMqttHandler::publishSensor(const HomeAssistantSensor& sensor)
|
||||
strlen_P(sensor.stacl) > 0 ? (char *) FPSTR(sensor.stacl) : "",
|
||||
strlen_P(sensor.stacl) > 0 ? "\"" : ""
|
||||
);
|
||||
mqtt->publish(discoveryTopic + deviceUid + "_" + uid.c_str() + "/config", json, true, 0);
|
||||
mqtt.publish(discoveryTopic + deviceUid + "_" + uid.c_str() + "/config", json, true, 0);
|
||||
loop();
|
||||
}
|
||||
|
||||
@ -540,14 +540,10 @@ void HomeAssistantMqttHandler::publishSystemSensors() {
|
||||
sInit = true;
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::loop() {
|
||||
bool ret = mqtt->loop();
|
||||
delay(10);
|
||||
yield();
|
||||
#if defined(ESP32)
|
||||
esp_task_wdt_reset();
|
||||
#elif defined(ESP8266)
|
||||
ESP.wdtFeed();
|
||||
#endif
|
||||
return ret;
|
||||
uint8_t HomeAssistantMqttHandler::getFormat() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishRaw(String data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -5,22 +5,18 @@
|
||||
|
||||
class JsonMqttHandler : public AmsMqttHandler {
|
||||
public:
|
||||
JsonMqttHandler(MQTTClient* mqtt, char* buf, const char* clientId, const char* topic, HwTools* hw) : AmsMqttHandler(mqtt, buf) {
|
||||
this->clientId = clientId;
|
||||
this->topic = String(topic);
|
||||
JsonMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf, HwTools* hw) : AmsMqttHandler(mqttConfig, debugger, buf) {
|
||||
this->hw = hw;
|
||||
};
|
||||
bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, EntsoeApi* eapi);
|
||||
bool publishTemperatures(AmsConfiguration*, HwTools*);
|
||||
bool publishPrices(EntsoeApi*);
|
||||
bool publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea);
|
||||
bool publishRaw(String data);
|
||||
|
||||
protected:
|
||||
bool loop();
|
||||
uint8_t getFormat();
|
||||
|
||||
private:
|
||||
String clientId;
|
||||
String topic;
|
||||
HwTools* hw;
|
||||
|
||||
bool publishList1(AmsData* data, EnergyAccounting* ea);
|
||||
|
||||
@ -10,11 +10,18 @@
|
||||
#include "json/jsonprices_json.h"
|
||||
|
||||
bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, EntsoeApi* eapi) {
|
||||
if(topic.isEmpty() || !mqtt->connected())
|
||||
if(strlen(mqttConfig.publishTopic) == 0) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("Unable to publish data, no publish topic\n"));
|
||||
return false;
|
||||
}
|
||||
if(!mqtt.connected()) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("Unable to publish data, not connected\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("Publishing list ID %d!\n"), data->getListType());
|
||||
if(data->getListType() == 1) {
|
||||
ret = publishList1(data, ea);
|
||||
} else if(data->getListType() == 2) {
|
||||
@ -31,7 +38,7 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccou
|
||||
bool JsonMqttHandler::publishList1(AmsData* data, EnergyAccounting* ea) {
|
||||
snprintf_P(json, BufferSize, JSON1_JSON,
|
||||
WiFi.macAddress().c_str(),
|
||||
clientId.c_str(),
|
||||
mqttConfig.clientId,
|
||||
(uint32_t) (millis64()/1000),
|
||||
data->getPackageTimestamp(),
|
||||
hw->getVcc(),
|
||||
@ -45,13 +52,13 @@ bool JsonMqttHandler::publishList1(AmsData* data, EnergyAccounting* ea) {
|
||||
ea->getProducedThisHour(),
|
||||
ea->getProducedToday()
|
||||
);
|
||||
return mqtt->publish(topic, json);
|
||||
return mqtt.publish(mqttConfig.publishTopic, json);
|
||||
}
|
||||
|
||||
bool JsonMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea) {
|
||||
snprintf_P(json, BufferSize, JSON2_JSON,
|
||||
WiFi.macAddress().c_str(),
|
||||
clientId.c_str(),
|
||||
mqttConfig.clientId,
|
||||
(uint32_t) (millis64()/1000),
|
||||
data->getPackageTimestamp(),
|
||||
hw->getVcc(),
|
||||
@ -77,13 +84,13 @@ bool JsonMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea) {
|
||||
ea->getProducedThisHour(),
|
||||
ea->getProducedToday()
|
||||
);
|
||||
return mqtt->publish(topic, json);
|
||||
return mqtt.publish(mqttConfig.publishTopic, json);
|
||||
}
|
||||
|
||||
bool JsonMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea) {
|
||||
snprintf_P(json, BufferSize, JSON3_JSON,
|
||||
WiFi.macAddress().c_str(),
|
||||
clientId.c_str(),
|
||||
mqttConfig.clientId,
|
||||
(uint32_t) (millis64()/1000),
|
||||
data->getPackageTimestamp(),
|
||||
hw->getVcc(),
|
||||
@ -114,13 +121,13 @@ bool JsonMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea) {
|
||||
ea->getProducedThisHour(),
|
||||
ea->getProducedToday()
|
||||
);
|
||||
return mqtt->publish(topic, json);
|
||||
return mqtt.publish(mqttConfig.publishTopic, json);
|
||||
}
|
||||
|
||||
bool JsonMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea) {
|
||||
snprintf_P(json, BufferSize, JSON4_JSON,
|
||||
WiFi.macAddress().c_str(),
|
||||
clientId.c_str(),
|
||||
mqttConfig.clientId,
|
||||
(uint32_t) (millis64()/1000),
|
||||
data->getPackageTimestamp(),
|
||||
hw->getVcc(),
|
||||
@ -161,7 +168,7 @@ bool JsonMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea) {
|
||||
ea->getProducedThisHour(),
|
||||
ea->getProducedToday()
|
||||
);
|
||||
return mqtt->publish(topic, json);
|
||||
return mqtt.publish(mqttConfig.publishTopic, json);
|
||||
}
|
||||
|
||||
String JsonMqttHandler::getMeterModel(AmsData* data) {
|
||||
@ -191,13 +198,13 @@ bool JsonMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw)
|
||||
}
|
||||
char* pos = json+strlen(json);
|
||||
snprintf_P(count == 0 ? pos : pos-1, 8, PSTR("}}"));
|
||||
bool ret = mqtt->publish(topic, json);
|
||||
bool ret = mqtt.publish(mqttConfig.publishTopic, json);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
if(topic.isEmpty() || !mqtt->connected())
|
||||
if(strlen(mqttConfig.publishTopic) == 0 || !mqtt.connected())
|
||||
return false;
|
||||
if(eapi->getValueForHour(0) == ENTSOE_NO_VALUE)
|
||||
return false;
|
||||
@ -325,37 +332,33 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
ts3hr,
|
||||
ts6hr
|
||||
);
|
||||
bool ret = mqtt->publish(topic, json);
|
||||
bool ret = mqtt.publish(mqttConfig.publishTopic, json);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool JsonMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) {
|
||||
if(topic.isEmpty() || !mqtt->connected())
|
||||
if(strlen(mqttConfig.publishTopic) == 0 || !mqtt.connected())
|
||||
return false;
|
||||
|
||||
snprintf_P(json, BufferSize, JSONSYS_JSON,
|
||||
WiFi.macAddress().c_str(),
|
||||
clientId.c_str(),
|
||||
mqttConfig.clientId,
|
||||
(uint32_t) (millis64()/1000),
|
||||
hw->getVcc(),
|
||||
hw->getWifiRssi(),
|
||||
hw->getTemperature(),
|
||||
FirmwareVersion::VersionString
|
||||
);
|
||||
bool ret = mqtt->publish(topic, json);
|
||||
bool ret = mqtt.publish(mqttConfig.publishTopic, json);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool JsonMqttHandler::loop() {
|
||||
bool ret = mqtt->loop();
|
||||
delay(10);
|
||||
yield();
|
||||
#if defined(ESP32)
|
||||
esp_task_wdt_reset();
|
||||
#elif defined(ESP8266)
|
||||
ESP.wdtFeed();
|
||||
#endif
|
||||
return ret;
|
||||
uint8_t JsonMqttHandler::getFormat() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool JsonMqttHandler::publishRaw(String data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -5,21 +5,21 @@
|
||||
|
||||
class RawMqttHandler : public AmsMqttHandler {
|
||||
public:
|
||||
RawMqttHandler(MQTTClient* mqtt, char* buf, const char* topic, bool full) : AmsMqttHandler(mqtt, buf) {
|
||||
this->topic = String(topic);
|
||||
this->full = full;
|
||||
RawMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf) : AmsMqttHandler(mqttConfig, debugger, buf) {
|
||||
full = mqttConfig.payloadFormat == 2;
|
||||
topic = String(mqttConfig.publishTopic);
|
||||
};
|
||||
bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, EntsoeApi* eapi);
|
||||
bool publishTemperatures(AmsConfiguration*, HwTools*);
|
||||
bool publishPrices(EntsoeApi*);
|
||||
bool publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea);
|
||||
bool publishRaw(String data);
|
||||
|
||||
protected:
|
||||
bool loop();
|
||||
uint8_t getFormat();
|
||||
|
||||
private:
|
||||
String topic;
|
||||
bool full;
|
||||
String topic;
|
||||
|
||||
bool publishList1(AmsData* data, AmsData* meterState);
|
||||
bool publishList2(AmsData* data, AmsData* meterState);
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
#include "Uptime.h"
|
||||
|
||||
bool RawMqttHandler::publish(AmsData* data, AmsData* meterState, EnergyAccounting* ea, EntsoeApi* eapi) {
|
||||
if(topic.isEmpty() || !mqtt->connected())
|
||||
if(topic.isEmpty() || !mqtt.connected())
|
||||
return false;
|
||||
|
||||
if(data->getPackageTimestamp() > 0) {
|
||||
mqtt->publish(topic + "/meter/dlms/timestamp", String(data->getPackageTimestamp()));
|
||||
mqtt.publish(topic + "/meter/dlms/timestamp", String(data->getPackageTimestamp()));
|
||||
}
|
||||
switch(data->getListType()) {
|
||||
case 4:
|
||||
@ -32,7 +32,7 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState, EnergyAccountin
|
||||
|
||||
bool RawMqttHandler::publishList1(AmsData* data, AmsData* meterState) {
|
||||
if(full || meterState->getActiveImportPower() != data->getActiveImportPower()) {
|
||||
mqtt->publish(topic + "/meter/import/active", String(data->getActiveImportPower()));
|
||||
mqtt.publish(topic + "/meter/import/active", String(data->getActiveImportPower()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -40,101 +40,101 @@ bool RawMqttHandler::publishList1(AmsData* data, AmsData* meterState) {
|
||||
bool RawMqttHandler::publishList2(AmsData* data, AmsData* meterState) {
|
||||
// Only send data if changed. ID and Type is sent on the 10s interval only if changed
|
||||
if(full || meterState->getMeterId() != data->getMeterId()) {
|
||||
mqtt->publish(topic + "/meter/id", data->getMeterId());
|
||||
mqtt.publish(topic + "/meter/id", data->getMeterId());
|
||||
}
|
||||
if(full || meterState->getMeterModel() != data->getMeterModel()) {
|
||||
mqtt->publish(topic + "/meter/type", data->getMeterModel());
|
||||
mqtt.publish(topic + "/meter/type", data->getMeterModel());
|
||||
}
|
||||
if(full || meterState->getL1Current() != data->getL1Current()) {
|
||||
mqtt->publish(topic + "/meter/l1/current", String(data->getL1Current(), 2));
|
||||
mqtt.publish(topic + "/meter/l1/current", String(data->getL1Current(), 2));
|
||||
}
|
||||
if(full || meterState->getL1Voltage() != data->getL1Voltage()) {
|
||||
mqtt->publish(topic + "/meter/l1/voltage", String(data->getL1Voltage(), 2));
|
||||
mqtt.publish(topic + "/meter/l1/voltage", String(data->getL1Voltage(), 2));
|
||||
}
|
||||
if(full || meterState->getL2Current() != data->getL2Current()) {
|
||||
mqtt->publish(topic + "/meter/l2/current", String(data->getL2Current(), 2));
|
||||
mqtt.publish(topic + "/meter/l2/current", String(data->getL2Current(), 2));
|
||||
}
|
||||
if(full || meterState->getL2Voltage() != data->getL2Voltage()) {
|
||||
mqtt->publish(topic + "/meter/l2/voltage", String(data->getL2Voltage(), 2));
|
||||
mqtt.publish(topic + "/meter/l2/voltage", String(data->getL2Voltage(), 2));
|
||||
}
|
||||
if(full || meterState->getL3Current() != data->getL3Current()) {
|
||||
mqtt->publish(topic + "/meter/l3/current", String(data->getL3Current(), 2));
|
||||
mqtt.publish(topic + "/meter/l3/current", String(data->getL3Current(), 2));
|
||||
}
|
||||
if(full || meterState->getL3Voltage() != data->getL3Voltage()) {
|
||||
mqtt->publish(topic + "/meter/l3/voltage", String(data->getL3Voltage(), 2));
|
||||
mqtt.publish(topic + "/meter/l3/voltage", String(data->getL3Voltage(), 2));
|
||||
}
|
||||
if(full || meterState->getReactiveExportPower() != data->getReactiveExportPower()) {
|
||||
mqtt->publish(topic + "/meter/export/reactive", String(data->getReactiveExportPower()));
|
||||
mqtt.publish(topic + "/meter/export/reactive", String(data->getReactiveExportPower()));
|
||||
}
|
||||
if(full || meterState->getActiveExportPower() != data->getActiveExportPower()) {
|
||||
mqtt->publish(topic + "/meter/export/active", String(data->getActiveExportPower()));
|
||||
mqtt.publish(topic + "/meter/export/active", String(data->getActiveExportPower()));
|
||||
}
|
||||
if(full || meterState->getReactiveImportPower() != data->getReactiveImportPower()) {
|
||||
mqtt->publish(topic + "/meter/import/reactive", String(data->getReactiveImportPower()));
|
||||
mqtt.publish(topic + "/meter/import/reactive", String(data->getReactiveImportPower()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RawMqttHandler::publishList3(AmsData* data, AmsData* meterState) {
|
||||
// ID and type belongs to List 2, but I see no need to send that every 10s
|
||||
mqtt->publish(topic + "/meter/id", data->getMeterId(), true, 0);
|
||||
mqtt->publish(topic + "/meter/type", data->getMeterModel(), true, 0);
|
||||
mqtt->publish(topic + "/meter/clock", String(data->getMeterTimestamp()));
|
||||
mqtt->publish(topic + "/meter/import/reactive/accumulated", String(data->getReactiveImportCounter(), 3), true, 0);
|
||||
mqtt->publish(topic + "/meter/import/active/accumulated", String(data->getActiveImportCounter(), 3), true, 0);
|
||||
mqtt->publish(topic + "/meter/export/reactive/accumulated", String(data->getReactiveExportCounter(), 3), true, 0);
|
||||
mqtt->publish(topic + "/meter/export/active/accumulated", String(data->getActiveExportCounter(), 3), true, 0);
|
||||
mqtt.publish(topic + "/meter/id", data->getMeterId(), true, 0);
|
||||
mqtt.publish(topic + "/meter/type", data->getMeterModel(), true, 0);
|
||||
mqtt.publish(topic + "/meter/clock", String(data->getMeterTimestamp()));
|
||||
mqtt.publish(topic + "/meter/import/reactive/accumulated", String(data->getReactiveImportCounter(), 3), true, 0);
|
||||
mqtt.publish(topic + "/meter/import/active/accumulated", String(data->getActiveImportCounter(), 3), true, 0);
|
||||
mqtt.publish(topic + "/meter/export/reactive/accumulated", String(data->getReactiveExportCounter(), 3), true, 0);
|
||||
mqtt.publish(topic + "/meter/export/active/accumulated", String(data->getActiveExportCounter(), 3), true, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RawMqttHandler::publishList4(AmsData* data, AmsData* meterState) {
|
||||
if(full || meterState->getL1ActiveImportPower() != data->getL1ActiveImportPower()) {
|
||||
mqtt->publish(topic + "/meter/import/l1", String(data->getL1ActiveImportPower(), 2));
|
||||
mqtt.publish(topic + "/meter/import/l1", String(data->getL1ActiveImportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL2ActiveImportPower() != data->getL2ActiveImportPower()) {
|
||||
mqtt->publish(topic + "/meter/import/l2", String(data->getL2ActiveImportPower(), 2));
|
||||
mqtt.publish(topic + "/meter/import/l2", String(data->getL2ActiveImportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL3ActiveImportPower() != data->getL3ActiveImportPower()) {
|
||||
mqtt->publish(topic + "/meter/import/l3", String(data->getL3ActiveImportPower(), 2));
|
||||
mqtt.publish(topic + "/meter/import/l3", String(data->getL3ActiveImportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL1ActiveExportPower() != data->getL1ActiveExportPower()) {
|
||||
mqtt->publish(topic + "/meter/export/l1", String(data->getL1ActiveExportPower(), 2));
|
||||
mqtt.publish(topic + "/meter/export/l1", String(data->getL1ActiveExportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL2ActiveExportPower() != data->getL2ActiveExportPower()) {
|
||||
mqtt->publish(topic + "/meter/export/l2", String(data->getL2ActiveExportPower(), 2));
|
||||
mqtt.publish(topic + "/meter/export/l2", String(data->getL2ActiveExportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL3ActiveExportPower() != data->getL3ActiveExportPower()) {
|
||||
mqtt->publish(topic + "/meter/export/l3", String(data->getL3ActiveExportPower(), 2));
|
||||
mqtt.publish(topic + "/meter/export/l3", String(data->getL3ActiveExportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getPowerFactor() != data->getPowerFactor()) {
|
||||
mqtt->publish(topic + "/meter/powerfactor", String(data->getPowerFactor(), 2));
|
||||
mqtt.publish(topic + "/meter/powerfactor", String(data->getPowerFactor(), 2));
|
||||
}
|
||||
if(full || meterState->getL1PowerFactor() != data->getL1PowerFactor()) {
|
||||
mqtt->publish(topic + "/meter/l1/powerfactor", String(data->getL1PowerFactor(), 2));
|
||||
mqtt.publish(topic + "/meter/l1/powerfactor", String(data->getL1PowerFactor(), 2));
|
||||
}
|
||||
if(full || meterState->getL2PowerFactor() != data->getL2PowerFactor()) {
|
||||
mqtt->publish(topic + "/meter/l2/powerfactor", String(data->getL2PowerFactor(), 2));
|
||||
mqtt.publish(topic + "/meter/l2/powerfactor", String(data->getL2PowerFactor(), 2));
|
||||
}
|
||||
if(full || meterState->getL3PowerFactor() != data->getL3PowerFactor()) {
|
||||
mqtt->publish(topic + "/meter/l3/powerfactor", String(data->getL3PowerFactor(), 2));
|
||||
mqtt.publish(topic + "/meter/l3/powerfactor", String(data->getL3PowerFactor(), 2));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RawMqttHandler::publishRealtime(EnergyAccounting* ea) {
|
||||
mqtt->publish(topic + "/realtime/import/hour", String(ea->getUseThisHour(), 3));
|
||||
mqtt->publish(topic + "/realtime/import/day", String(ea->getUseToday(), 2));
|
||||
mqtt->publish(topic + "/realtime/import/month", String(ea->getUseThisMonth(), 1));
|
||||
mqtt.publish(topic + "/realtime/import/hour", String(ea->getUseThisHour(), 3));
|
||||
mqtt.publish(topic + "/realtime/import/day", String(ea->getUseToday(), 2));
|
||||
mqtt.publish(topic + "/realtime/import/month", String(ea->getUseThisMonth(), 1));
|
||||
uint8_t peakCount = ea->getConfig()->hours;
|
||||
if(peakCount > 5) peakCount = 5;
|
||||
for(uint8_t i = 1; i <= peakCount; i++) {
|
||||
mqtt->publish(topic + "/realtime/import/peak/" + String(i, 10), String(ea->getPeak(i).value / 100.0, 10), true, 0);
|
||||
mqtt.publish(topic + "/realtime/import/peak/" + String(i, 10), String(ea->getPeak(i).value / 100.0, 10), true, 0);
|
||||
}
|
||||
mqtt->publish(topic + "/realtime/import/threshold", String(ea->getCurrentThreshold(), 10), true, 0);
|
||||
mqtt->publish(topic + "/realtime/import/monthmax", String(ea->getMonthMax(), 3), true, 0);
|
||||
mqtt->publish(topic + "/realtime/export/hour", String(ea->getProducedThisHour(), 3));
|
||||
mqtt->publish(topic + "/realtime/export/day", String(ea->getProducedToday(), 2));
|
||||
mqtt->publish(topic + "/realtime/export/month", String(ea->getProducedThisMonth(), 1));
|
||||
mqtt.publish(topic + "/realtime/import/threshold", String(ea->getCurrentThreshold(), 10), true, 0);
|
||||
mqtt.publish(topic + "/realtime/import/monthmax", String(ea->getMonthMax(), 3), true, 0);
|
||||
mqtt.publish(topic + "/realtime/export/hour", String(ea->getProducedThisHour(), 3));
|
||||
mqtt.publish(topic + "/realtime/export/day", String(ea->getProducedToday(), 2));
|
||||
mqtt.publish(topic + "/realtime/export/month", String(ea->getProducedThisMonth(), 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ bool RawMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw)
|
||||
TempSensorData* data = hw->getTempSensorData(i);
|
||||
if(data != NULL && data->lastValidRead > -85) {
|
||||
if(data->changed || full) {
|
||||
mqtt->publish(topic + "/temperature/" + toHex(data->address), String(data->lastValidRead, 2));
|
||||
mqtt.publish(topic + "/temperature/" + toHex(data->address), String(data->lastValidRead, 2));
|
||||
data->changed = false;
|
||||
}
|
||||
}
|
||||
@ -153,7 +153,7 @@ bool RawMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw)
|
||||
}
|
||||
|
||||
bool RawMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
if(topic.isEmpty() || !mqtt->connected())
|
||||
if(topic.isEmpty() || !mqtt.connected())
|
||||
return false;
|
||||
if(eapi->getValueForHour(0) == ENTSOE_NO_VALUE)
|
||||
return false;
|
||||
@ -236,58 +236,54 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
for(int i = 0; i < 34; i++) {
|
||||
float val = values[i];
|
||||
if(val == ENTSOE_NO_VALUE) {
|
||||
mqtt->publish(topic + "/price/" + String(i), "", true, 0);
|
||||
mqtt.publish(topic + "/price/" + String(i), "", true, 0);
|
||||
} else {
|
||||
mqtt->publish(topic + "/price/" + String(i), String(val, 4), true, 0);
|
||||
mqtt.publish(topic + "/price/" + String(i), String(val, 4), true, 0);
|
||||
}
|
||||
mqtt->loop();
|
||||
mqtt.loop();
|
||||
delay(10);
|
||||
}
|
||||
if(min != INT16_MAX) {
|
||||
mqtt->publish(topic + "/price/min", String(min, 4), true, 0);
|
||||
mqtt.publish(topic + "/price/min", String(min, 4), true, 0);
|
||||
}
|
||||
if(max != INT16_MIN) {
|
||||
mqtt->publish(topic + "/price/max", String(max, 4), true, 0);
|
||||
mqtt.publish(topic + "/price/max", String(max, 4), true, 0);
|
||||
}
|
||||
|
||||
if(min1hrIdx != -1) {
|
||||
mqtt->publish(topic + "/price/cheapest/1hr", String(ts1hr), true, 0);
|
||||
mqtt.publish(topic + "/price/cheapest/1hr", String(ts1hr), true, 0);
|
||||
}
|
||||
if(min3hrIdx != -1) {
|
||||
mqtt->publish(topic + "/price/cheapest/3hr", String(ts3hr), true, 0);
|
||||
mqtt.publish(topic + "/price/cheapest/3hr", String(ts3hr), true, 0);
|
||||
}
|
||||
if(min6hrIdx != -1) {
|
||||
mqtt->publish(topic + "/price/cheapest/6hr", String(ts6hr), true, 0);
|
||||
mqtt.publish(topic + "/price/cheapest/6hr", String(ts6hr), true, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RawMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) {
|
||||
if(topic.isEmpty() || !mqtt->connected())
|
||||
if(topic.isEmpty() || !mqtt.connected())
|
||||
return false;
|
||||
|
||||
mqtt->publish(topic + "/id", WiFi.macAddress(), true, 0);
|
||||
mqtt->publish(topic + "/uptime", String((uint32_t) (millis64()/1000)));
|
||||
mqtt.publish(topic + "/id", WiFi.macAddress(), true, 0);
|
||||
mqtt.publish(topic + "/uptime", String((uint32_t) (millis64()/1000)));
|
||||
float vcc = hw->getVcc();
|
||||
if(vcc > 0) {
|
||||
mqtt->publish(topic + "/vcc", String(vcc, 2));
|
||||
mqtt.publish(topic + "/vcc", String(vcc, 2));
|
||||
}
|
||||
mqtt->publish(topic + "/mem", String(ESP.getFreeHeap()));
|
||||
mqtt->publish(topic + "/rssi", String(hw->getWifiRssi()));
|
||||
mqtt.publish(topic + "/mem", String(ESP.getFreeHeap()));
|
||||
mqtt.publish(topic + "/rssi", String(hw->getWifiRssi()));
|
||||
if(hw->getTemperature() > -85) {
|
||||
mqtt->publish(topic + "/temperature", String(hw->getTemperature(), 2));
|
||||
mqtt.publish(topic + "/temperature", String(hw->getTemperature(), 2));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RawMqttHandler::loop() {
|
||||
bool ret = mqtt->loop();
|
||||
delay(10);
|
||||
yield();
|
||||
#if defined(ESP32)
|
||||
esp_task_wdt_reset();
|
||||
#elif defined(ESP8266)
|
||||
ESP.wdtFeed();
|
||||
#endif
|
||||
return ret;
|
||||
uint8_t RawMqttHandler::getFormat() {
|
||||
return full ? 3 : 2;
|
||||
}
|
||||
|
||||
bool RawMqttHandler::publishRaw(String data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
2
lib/SvelteUi/app/dist/index.css
vendored
2
lib/SvelteUi/app/dist/index.css
vendored
File diff suppressed because one or more lines are too long
20
lib/SvelteUi/app/dist/index.js
vendored
20
lib/SvelteUi/app/dist/index.js
vendored
File diff suppressed because one or more lines are too long
13
lib/SvelteUi/app/package-lock.json
generated
13
lib/SvelteUi/app/package-lock.json
generated
@ -20,6 +20,7 @@
|
||||
"svelte": "^3.49.0",
|
||||
"svelte-navigator": "^3.2.2",
|
||||
"svelte-preprocess": "^4.10.7",
|
||||
"svelte-qrcode": "^1.0.0",
|
||||
"tailwindcss": "^3.1.5",
|
||||
"vite": "^3.2.7"
|
||||
}
|
||||
@ -2592,6 +2593,12 @@
|
||||
"sourcemap-codec": "^1.4.8"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-qrcode": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-qrcode/-/svelte-qrcode-1.0.0.tgz",
|
||||
"integrity": "sha512-WrOvyyxtUzu32gVIDxcFMy0A7uUpbl/8yHaTNOsUaI8W5V4wa7AmReCjffhNY2aS42CqCLJ6qdwUoj/KxmeZzA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/svelte2tsx": {
|
||||
"version": "0.1.193",
|
||||
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.1.193.tgz",
|
||||
@ -4468,6 +4475,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"svelte-qrcode": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-qrcode/-/svelte-qrcode-1.0.0.tgz",
|
||||
"integrity": "sha512-WrOvyyxtUzu32gVIDxcFMy0A7uUpbl/8yHaTNOsUaI8W5V4wa7AmReCjffhNY2aS42CqCLJ6qdwUoj/KxmeZzA==",
|
||||
"dev": true
|
||||
},
|
||||
"svelte2tsx": {
|
||||
"version": "0.1.193",
|
||||
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.1.193.tgz",
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"svelte": "^3.49.0",
|
||||
"svelte-navigator": "^3.2.2",
|
||||
"svelte-preprocess": "^4.10.7",
|
||||
"svelte-qrcode": "^1.0.0",
|
||||
"tailwindcss": "^3.1.5",
|
||||
"vite": "^3.2.7"
|
||||
},
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
import { Link, navigate } from 'svelte-navigator';
|
||||
import SubnetOptions from './SubnetOptions.svelte';
|
||||
import TrashIcon from './TrashIcon.svelte';
|
||||
import QrCode from 'svelte-qrcode';
|
||||
|
||||
|
||||
export let sysinfo = {}
|
||||
@ -98,6 +99,9 @@
|
||||
},
|
||||
h: {
|
||||
t: '', h: '', n: ''
|
||||
},
|
||||
c: {
|
||||
es: null
|
||||
}
|
||||
};
|
||||
configurationStore.subscribe(update => {
|
||||
@ -607,6 +611,24 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if configuration.c.es != null}
|
||||
<div class="cnt">
|
||||
<input type="hidden" name="c" value="true"/>
|
||||
<strong class="text-sm">Cloud connections</strong>
|
||||
<div class="my-1">
|
||||
<label><input type="checkbox" class="rounded mb-1" name="ces" value="true" bind:checked={configuration.c.es}/> Energy Speedometer</label>
|
||||
{#if configuration.c.es}
|
||||
<div class="pl-5">MAC: {sysinfo.mac}</div>
|
||||
<div class="pl-5">Meter ID: {sysinfo.meter.id ? sysinfo.meter.id : "missing, required"}</div>
|
||||
{#if sysinfo.mac && sysinfo.meter.id}
|
||||
<div class="pl-2">
|
||||
<QrCode value='{'{'}"mac":"{sysinfo.mac}","meter":"{sysinfo.meter.id}"{'}'}'/>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if configuration.p.r.startsWith("10YNO") || configuration.p.r == '10Y1001A1001A48H'}
|
||||
<div class="cnt">
|
||||
<strong class="text-sm">Tariff thresholds</strong>
|
||||
|
||||
@ -41,7 +41,7 @@ export function metertype(mt) {
|
||||
case 10:
|
||||
return "Sagemcom";
|
||||
default:
|
||||
return "";
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -126,10 +126,10 @@
|
||||
Manufacturer: {metertype(sysinfo.meter.mfg)}
|
||||
</div>
|
||||
<div class="my-2">
|
||||
Model: {sysinfo.meter.model}
|
||||
Model: {sysinfo.meter.model ? sysinfo.meter.model : "unknown"}
|
||||
</div>
|
||||
<div class="my-2">
|
||||
ID: {sysinfo.meter.id}
|
||||
ID: {sysinfo.meter.id ? sysinfo.meter.id : "unknown"}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define _AMSWEBSERVER_h
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <MQTT.h>
|
||||
#include "AmsMqttHandler.h"
|
||||
#include "AmsConfiguration.h"
|
||||
#include "HwTools.h"
|
||||
#include "AmsData.h"
|
||||
@ -39,6 +39,7 @@ public:
|
||||
void setMqttEnabled(bool);
|
||||
void setEntsoeApi(EntsoeApi* eapi);
|
||||
void setPriceSettings(String region, String currency);
|
||||
void setMqttHandler(AmsMqttHandler* mqttHandler);
|
||||
|
||||
private:
|
||||
RemoteDebug* debugger;
|
||||
@ -54,7 +55,7 @@ private:
|
||||
AmsData* meterState;
|
||||
AmsDataStorage* ds;
|
||||
EnergyAccounting* ea = NULL;
|
||||
MQTTClient* mqtt = NULL;
|
||||
AmsMqttHandler* mqttHandler = NULL;
|
||||
bool uploading = false;
|
||||
File file;
|
||||
bool performRestart = false;
|
||||
|
||||
3
lib/SvelteUi/json/conf_cloud.json
Normal file
3
lib/SvelteUi/json/conf_cloud.json
Normal file
@ -0,0 +1,3 @@
|
||||
"c": {
|
||||
"es": %s
|
||||
}
|
||||
@ -2,4 +2,4 @@
|
||||
"t" : "%s",
|
||||
"h" : "%s",
|
||||
"n" : "%s"
|
||||
}
|
||||
},
|
||||
|
||||
@ -30,12 +30,13 @@
|
||||
#include "html/conf_domoticz_json.h"
|
||||
#include "html/conf_ha_json.h"
|
||||
#include "html/conf_ui_json.h"
|
||||
#include "html/conf_cloud_json.h"
|
||||
#include "html/firmware_html.h"
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <esp_task_wdt.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_clk.h>
|
||||
#include <esp32/clk.h>
|
||||
#endif
|
||||
|
||||
|
||||
@ -124,11 +125,6 @@ void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, Meter
|
||||
mqttEnabled = strlen(mqttConfig.host) > 0;
|
||||
}
|
||||
|
||||
|
||||
void AmsWebServer::setMqtt(MQTTClient* mqtt) {
|
||||
this->mqtt = mqtt;
|
||||
}
|
||||
|
||||
void AmsWebServer::setTimezone(Timezone* tz) {
|
||||
this->tz = tz;
|
||||
}
|
||||
@ -136,6 +132,9 @@ void AmsWebServer::setTimezone(Timezone* tz) {
|
||||
void AmsWebServer::setMqttEnabled(bool enabled) {
|
||||
mqttEnabled = enabled;
|
||||
}
|
||||
void AmsWebServer::setMqttHandler(AmsMqttHandler* mqttHandler) {
|
||||
this->mqttHandler = mqttHandler;
|
||||
}
|
||||
|
||||
void AmsWebServer::setEntsoeApi(EntsoeApi* eapi) {
|
||||
this->eapi = eapi;
|
||||
@ -418,9 +417,9 @@ void AmsWebServer::dataJson() {
|
||||
uint8_t mqttStatus;
|
||||
if(!mqttEnabled) {
|
||||
mqttStatus = 0;
|
||||
} else if(mqtt != NULL && mqtt->connected()) {
|
||||
} else if(mqttHandler != NULL && mqttHandler->connected()) {
|
||||
mqttStatus = 1;
|
||||
} else if(mqtt != NULL && mqtt->lastError() == 0) {
|
||||
} else if(mqttHandler != NULL && mqttHandler->lastError() == 0) {
|
||||
mqttStatus = 2;
|
||||
} else {
|
||||
mqttStatus = 3;
|
||||
@ -467,7 +466,7 @@ void AmsWebServer::dataJson() {
|
||||
hanStatus,
|
||||
wifiStatus,
|
||||
mqttStatus,
|
||||
mqtt == NULL ? 0 : (int) mqtt->lastError(),
|
||||
mqttHandler == NULL ? 0 : (int) mqttHandler->lastError(),
|
||||
price == ENTSOE_NO_VALUE ? "null" : String(price, 2).c_str(),
|
||||
meterState->getMeterType(),
|
||||
meterConfig->distributionSystem,
|
||||
@ -791,6 +790,8 @@ void AmsWebServer::configurationJson() {
|
||||
if(!checkSecurity(1))
|
||||
return;
|
||||
|
||||
SystemConfig sysConfig;
|
||||
config->getSystemConfig(sysConfig);
|
||||
NtpConfig ntpConfig;
|
||||
config->getNtpConfig(ntpConfig);
|
||||
WiFiConfig wifiConfig;
|
||||
@ -976,6 +977,14 @@ void AmsWebServer::configurationJson() {
|
||||
haconf.discoveryNameTag
|
||||
);
|
||||
server.sendContent(buf);
|
||||
snprintf_P(buf, BufferSize, CONF_CLOUD_JSON,
|
||||
#if defined(ENERGY_SPEEDOMETER_PASS)
|
||||
sysConfig.energyspeedometer == 7 ? "true" : "false"
|
||||
#else
|
||||
"null"
|
||||
#endif
|
||||
);
|
||||
server.sendContent(buf);
|
||||
server.sendContent_P(PSTR("}"));
|
||||
}
|
||||
|
||||
@ -1471,6 +1480,14 @@ void AmsWebServer::handleSave() {
|
||||
config->setEnergyAccountingConfig(eac);
|
||||
}
|
||||
|
||||
if(server.hasArg(F("c")) && server.arg(F("c")) == F("true")) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf_P(PSTR("Received cloud config\n"));
|
||||
SystemConfig sys;
|
||||
config->getSystemConfig(sys);
|
||||
sys.energyspeedometer = server.hasArg(F("ces")) && server.arg(F("ces")) == F("true") ? 7 : 0;
|
||||
config->setSystemConfig(sys);
|
||||
}
|
||||
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf_P(PSTR("Saving configuration now...\n"));
|
||||
|
||||
if (config->save()) {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
extra_configs = platformio-user.ini
|
||||
|
||||
[common]
|
||||
lib_deps = EEPROM, LittleFS, DNSServer, https://github.com/256dpi/arduino-mqtt.git, OneWireNg@0.10.0, DallasTemperature@3.9.1, EspSoftwareSerial@6.14.1, https://github.com/gskjold/RemoteDebug.git, Time@1.6.1, Timezone@1.2.4, FirmwareVersion, AmsConfiguration, AmsData, AmsDataStorage, HwTools, Uptime, AmsDecoder, EntsoePriceApi, EnergyAccounting, RawMqttHandler, JsonMqttHandler, DomoticzMqttHandler, HomeAssistantMqttHandler, SvelteUi
|
||||
lib_deps = EEPROM, LittleFS, DNSServer, https://github.com/256dpi/arduino-mqtt.git, OneWireNg@0.10.0, DallasTemperature@3.9.1, EspSoftwareSerial@6.14.1, https://github.com/gskjold/RemoteDebug.git, Time@1.6.1, Timezone@1.2.4, FirmwareVersion, AmsConfiguration, AmsData, AmsDataStorage, HwTools, Uptime, AmsDecoder, EntsoePriceApi, EnergyAccounting, AmsMqttHandler, RawMqttHandler, JsonMqttHandler, DomoticzMqttHandler, HomeAssistantMqttHandler, SvelteUi
|
||||
lib_ignore = OneWire
|
||||
extra_scripts =
|
||||
pre:scripts/addversion.py
|
||||
|
||||
@ -48,12 +48,13 @@ ADC_MODE(ADC_VCC);
|
||||
#include "RawMqttHandler.h"
|
||||
#include "DomoticzMqttHandler.h"
|
||||
#include "HomeAssistantMqttHandler.h"
|
||||
#include "PassthroughMqttHandler.h"
|
||||
|
||||
#include "Uptime.h"
|
||||
|
||||
#include "RemoteDebug.h"
|
||||
|
||||
#define debugV_P(x, ...) if (Debug.isActive(Debug.VERBOSE)) {Debug.printf_P(x, ##__VA_ARGS__);Debug.println();}
|
||||
#define debugV_P(x, ...) if (Debug.isActive(Debug.VERBOSE)) {Debug.printf_P(x, ##__VA_ARGS__);Debug.println();}
|
||||
#define debugD_P(x, ...) if (Debug.isActive(Debug.DEBUG)) {Debug.printf_P(x, ##__VA_ARGS__);Debug.println();}
|
||||
#define debugI_P(x, ...) if (Debug.isActive(Debug.INFO)) {Debug.printf_P(x, ##__VA_ARGS__);Debug.println();}
|
||||
#define debugW_P(x, ...) if (Debug.isActive(Debug.WARNING)) {Debug.printf_P(x, ##__VA_ARGS__);Debug.println();}
|
||||
@ -89,11 +90,32 @@ Timezone* tz = NULL;
|
||||
|
||||
AmsWebServer ws(commonBuffer, &Debug, &hw);
|
||||
|
||||
MQTTClient *mqtt = NULL;
|
||||
WiFiClient *mqttClient = NULL;
|
||||
WiFiClientSecure *mqttSecureClient = NULL;
|
||||
bool mqttEnabled = false;
|
||||
AmsMqttHandler* mqttHandler = NULL;
|
||||
|
||||
#if defined(ESP32)
|
||||
JsonMqttHandler* energySpeedometer = NULL;
|
||||
MqttConfig energySpeedometerConfig = {
|
||||
"mqtt.sandtime.energy",
|
||||
8883,
|
||||
"",
|
||||
"amsleser",
|
||||
"",
|
||||
#if defined(ENERGY_SPEEDOMETER_USER)
|
||||
ENERGY_SPEEDOMETER_USER,
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
#if defined(ENERGY_SPEEDOMETER_PASS)
|
||||
ENERGY_SPEEDOMETER_PASS,
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
0,
|
||||
true
|
||||
};
|
||||
#endif
|
||||
|
||||
Stream *hanSerial;
|
||||
SoftwareSerial *swSerial = NULL;
|
||||
HardwareSerial *hwSerial = NULL;
|
||||
@ -102,8 +124,6 @@ uint8_t rxBufferErrors = 0;
|
||||
SystemConfig sysConfig;
|
||||
GpioConfig gpioConfig;
|
||||
MeterConfig meterConfig;
|
||||
bool mqttEnabled = false;
|
||||
String topic = "ams";
|
||||
AmsData meterState;
|
||||
bool ntpEnabled = false;
|
||||
|
||||
@ -533,15 +553,49 @@ void loop() {
|
||||
#endif
|
||||
|
||||
if (mqttEnabled || config.isMqttChanged()) {
|
||||
if(mqtt == NULL || !mqtt->connected() || config.isMqttChanged()) {
|
||||
if(mqttHandler == NULL || !mqttHandler->connected() || config.isMqttChanged()) {
|
||||
MQTT_connect();
|
||||
config.ackMqttChange();
|
||||
}
|
||||
} else if(mqtt != NULL && mqtt->connected()) {
|
||||
mqttClient->stop();
|
||||
mqtt->disconnect();
|
||||
} else if(mqttHandler != NULL) {
|
||||
mqttHandler->disconnect();
|
||||
}
|
||||
|
||||
#if defined(ENERGY_SPEEDOMETER_PASS)
|
||||
if(sysConfig.energyspeedometer == 7) {
|
||||
if(!meterState.getMeterId().isEmpty()) {
|
||||
if(energySpeedometer == NULL) {
|
||||
uint16_t chipId;
|
||||
#if defined(ESP32)
|
||||
chipId = ( ESP.getEfuseMac() >> 32 ) % 0xFFFFFFFF;
|
||||
#else
|
||||
chipId = ESP.getChipId();
|
||||
#endif
|
||||
strcpy(energySpeedometerConfig.clientId, (String("ams") + String(chipId, HEX)).c_str());
|
||||
energySpeedometer = new JsonMqttHandler(energySpeedometerConfig, &Debug, (char*) commonBuffer, &hw);
|
||||
energySpeedometer->setCaVerification(false);
|
||||
}
|
||||
if(!energySpeedometer->connected()) {
|
||||
lwmqtt_err_t err = energySpeedometer->lastError();
|
||||
if(err > 0)
|
||||
debugE_P(PSTR("Energyspeedometer connector reporting error (%d)"), err);
|
||||
energySpeedometer->connect();
|
||||
energySpeedometer->publishSystem(&hw, eapi, &ea);
|
||||
}
|
||||
energySpeedometer->loop();
|
||||
delay(10);
|
||||
}
|
||||
} else if(energySpeedometer != NULL) {
|
||||
if(energySpeedometer->connected()) {
|
||||
energySpeedometer->disconnect();
|
||||
energySpeedometer->loop();
|
||||
} else {
|
||||
delete energySpeedometer;
|
||||
energySpeedometer = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
try {
|
||||
handlePriceApi(now);
|
||||
} catch(const std::exception& e) {
|
||||
@ -554,9 +608,9 @@ void loop() {
|
||||
debugW_P(PSTR("Used %dms to handle web"), millis()-start);
|
||||
}
|
||||
}
|
||||
if(mqtt != NULL) {
|
||||
if(mqttHandler != NULL) {
|
||||
start = millis();
|
||||
mqtt->loop();
|
||||
mqttHandler->loop();
|
||||
delay(10); // Needed to preserve power. After adding this, the voltage is super smooth on a HAN powered device
|
||||
end = millis();
|
||||
if(end - start > 1000) {
|
||||
@ -687,11 +741,23 @@ void handleNtpChange() {
|
||||
}
|
||||
|
||||
void handleSystem(unsigned long now) {
|
||||
if(config.isSystemConfigChanged()) {
|
||||
config.getSystemConfig(sysConfig);
|
||||
config.ackSystemConfigChanged();
|
||||
}
|
||||
|
||||
unsigned long start, end;
|
||||
if(now - lastSysupdate > 60000) {
|
||||
start = millis();
|
||||
if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) {
|
||||
mqttHandler->publishSystem(&hw, eapi, &ea);
|
||||
if(WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED) {
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->publishSystem(&hw, eapi, &ea);
|
||||
}
|
||||
#if defined(ENERGY_SPEEDOMETER_PASS)
|
||||
if(energySpeedometer != NULL) {
|
||||
energySpeedometer->publishSystem(&hw, eapi, &ea);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
lastSysupdate = now;
|
||||
end = millis();
|
||||
@ -738,7 +804,7 @@ void handleTemperature(unsigned long now) {
|
||||
if(hw.updateTemperatures()) {
|
||||
lastTemperatureRead = now;
|
||||
|
||||
if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) {
|
||||
if(mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED) {
|
||||
mqttHandler->publishTemperatures(&config, &hw);
|
||||
}
|
||||
}
|
||||
@ -753,7 +819,7 @@ void handlePriceApi(unsigned long now) {
|
||||
unsigned long start, end;
|
||||
if(eapi != NULL && ntpEnabled) {
|
||||
start = millis();
|
||||
if(eapi->loop() && mqtt != NULL && mqttHandler != NULL && mqtt->connected()) {
|
||||
if(eapi->loop() && mqttHandler != NULL) {
|
||||
end = millis();
|
||||
if(end - start > 1000) {
|
||||
debugW_P(PSTR("Used %dms to update prices"), millis()-start);
|
||||
@ -1078,7 +1144,7 @@ void errorBlink() {
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(mqttEnabled && mqtt != NULL && mqtt->lastError() != 0) {
|
||||
if(mqttHandler != NULL && mqttHandler->lastError() != 0) {
|
||||
debugW_P(PSTR("MQTT connection not available, double blink"));
|
||||
hw.ledBlink(LED_RED, 2); // If MQTT error, blink twice
|
||||
return;
|
||||
@ -1221,10 +1287,8 @@ bool readHanPort() {
|
||||
meterState.setLastError(pos);
|
||||
printHanReadError(pos);
|
||||
len += hanSerial->readBytes(hanBuffer+len, BUF_SIZE_HAN-len);
|
||||
if(mqttEnabled && mqtt != NULL && mqttHandler == NULL) {
|
||||
mqtt->publish(topic.c_str(), toHex(hanBuffer+pos, len));
|
||||
mqtt->loop();
|
||||
delay(10);
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->publishRaw(toHex(hanBuffer+pos, len));
|
||||
}
|
||||
while(hanSerial->available()) hanSerial->read(); // Make sure it is all empty, in case we overflowed buffer above
|
||||
len = 0;
|
||||
@ -1242,10 +1306,8 @@ bool readHanPort() {
|
||||
if(maxDetectedPayloadSize < pos) maxDetectedPayloadSize = pos;
|
||||
if(ctx.type == DATA_TAG_DLMS) {
|
||||
// If MQTT bytestream payload is selected (mqttHandler == NULL), send the payload to MQTT
|
||||
if(mqttEnabled && mqtt != NULL && mqttHandler == NULL) {
|
||||
mqtt->publish(topic.c_str(), toHex((byte*) payload, ctx.length));
|
||||
mqtt->loop();
|
||||
delay(10);
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->publishRaw(toHex((byte*) payload, ctx.length));
|
||||
}
|
||||
|
||||
debugV_P(PSTR("Using application data:"));
|
||||
@ -1300,7 +1362,7 @@ void handleDataSuccess(AmsData* data) {
|
||||
if(!hw.ledBlink(LED_GREEN, 1))
|
||||
hw.ledBlink(LED_INTERNAL, 1);
|
||||
|
||||
if(mqttEnabled && mqttHandler != NULL && mqtt != NULL) {
|
||||
if(mqttHandler != NULL) {
|
||||
#if defined(ESP32)
|
||||
esp_task_wdt_reset();
|
||||
#elif defined(ESP8266)
|
||||
@ -1308,10 +1370,14 @@ void handleDataSuccess(AmsData* data) {
|
||||
#endif
|
||||
yield();
|
||||
if(mqttHandler->publish(data, &meterState, &ea, eapi)) {
|
||||
mqtt->loop();
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
#if defined(ENERGY_SPEEDOMETER_PASS)
|
||||
if(energySpeedometer != NULL && energySpeedometer->publish(&meterState, &meterState, &ea, eapi)) {
|
||||
delay(10);
|
||||
}
|
||||
#endif
|
||||
|
||||
time_t now = time(nullptr);
|
||||
if(now < FirmwareVersion::BuildEpoch && data->getListType() >= 3) {
|
||||
@ -1418,23 +1484,8 @@ unsigned long lastWifiRetry = -WIFI_CONNECTION_TIMEOUT;
|
||||
|
||||
void WiFi_disconnect(unsigned long timeout) {
|
||||
if (Debug.isActive(RemoteDebug::INFO)) debugI_P(PSTR("Not connected to WiFi, closing resources"));
|
||||
if(mqtt != NULL) {
|
||||
mqtt->disconnect();
|
||||
mqtt->loop();
|
||||
delay(10);
|
||||
yield();
|
||||
delete mqtt;
|
||||
mqtt = NULL;
|
||||
ws.setMqtt(NULL);
|
||||
}
|
||||
|
||||
if(mqttClient != NULL) {
|
||||
mqttClient->stop();
|
||||
delete mqttClient;
|
||||
mqttClient = NULL;
|
||||
if(mqttSecureClient != NULL) {
|
||||
mqttSecureClient = NULL;
|
||||
}
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->disconnect();
|
||||
}
|
||||
|
||||
#if defined(ESP8266)
|
||||
@ -1647,16 +1698,6 @@ void WiFi_post_connect() {
|
||||
}
|
||||
}
|
||||
|
||||
void mqttMessageReceived(String &topic, String &payload) {
|
||||
debugI_P(PSTR("Received message for topic %s"), topic.c_str() );
|
||||
//if(meterConfig.source == METER_SOURCE_MQTT) {
|
||||
//DataParserContext ctx = {static_cast<uint8_t>(payload.length()/2)};
|
||||
//fromHex(hanBuffer, payload, ctx.length);
|
||||
//uint16_t pos = unwrapData(hanBuffer, ctx);
|
||||
// TODO: Run through DLMS/DMSR parser and apply AmsData
|
||||
//}
|
||||
}
|
||||
|
||||
int16_t unwrapData(uint8_t *buf, DataParserContext &context) {
|
||||
int16_t ret = 0;
|
||||
bool doRet = false;
|
||||
@ -1711,19 +1752,15 @@ int16_t unwrapData(uint8_t *buf, DataParserContext &context) {
|
||||
case DATA_TAG_HDLC:
|
||||
debugV_P(PSTR("HDLC frame:"));
|
||||
// If MQTT bytestream payload is selected (mqttHandler == NULL), send the payload to MQTT
|
||||
if(mqttEnabled && mqtt != NULL && mqttHandler == NULL) {
|
||||
mqtt->publish(topic.c_str(), toHex(buf, curLen));
|
||||
mqtt->loop();
|
||||
delay(10);
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->publishRaw(toHex(buf, curLen));
|
||||
}
|
||||
break;
|
||||
case DATA_TAG_MBUS:
|
||||
debugV_P(PSTR("MBUS frame:"));
|
||||
// If MQTT bytestream payload is selected (mqttHandler == NULL), send the payload to MQTT
|
||||
if(mqttEnabled && mqtt != NULL && mqttHandler == NULL) {
|
||||
mqtt->publish(topic.c_str(), toHex(buf, curLen));
|
||||
mqtt->loop();
|
||||
delay(10);
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->publishRaw(toHex(buf, curLen));
|
||||
}
|
||||
break;
|
||||
case DATA_TAG_GBT:
|
||||
@ -1740,10 +1777,8 @@ int16_t unwrapData(uint8_t *buf, DataParserContext &context) {
|
||||
break;
|
||||
case DATA_TAG_DSMR:
|
||||
debugV_P(PSTR("DSMR frame:"));
|
||||
if(mqttEnabled && mqtt != NULL && mqttHandler == NULL) {
|
||||
mqtt->publish(topic.c_str(), (char*) buf);
|
||||
mqtt->loop();
|
||||
delay(10);
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->publishRaw(String((char*)buf));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1777,191 +1812,57 @@ int16_t unwrapData(uint8_t *buf, DataParserContext &context) {
|
||||
|
||||
unsigned long lastMqttRetry = -10000;
|
||||
void MQTT_connect() {
|
||||
if(millis() - lastMqttRetry < (config.isMqttChanged() ? 5000 : 30000)) {
|
||||
yield();
|
||||
return;
|
||||
}
|
||||
lastMqttRetry = millis();
|
||||
|
||||
MqttConfig mqttConfig;
|
||||
if(!config.getMqttConfig(mqttConfig) || strlen(mqttConfig.host) == 0) {
|
||||
if(Debug.isActive(RemoteDebug::WARNING)) debugW_P(PSTR("No MQTT config"));
|
||||
mqttEnabled = false;
|
||||
ws.setMqttEnabled(false);
|
||||
mqttEnabled = false;
|
||||
return;
|
||||
}
|
||||
if(mqtt != NULL) {
|
||||
if(millis() - lastMqttRetry < (mqtt->lastError() == 0 || config.isMqttChanged() ? 5000 : 30000)) {
|
||||
yield();
|
||||
return;
|
||||
}
|
||||
lastMqttRetry = millis();
|
||||
|
||||
if(Debug.isActive(RemoteDebug::INFO)) {
|
||||
debugD_P(PSTR("Disconnecting MQTT before connecting"));
|
||||
}
|
||||
|
||||
mqtt->disconnect();
|
||||
if(config.isMqttChanged()) {
|
||||
if(mqttSecureClient != NULL) {
|
||||
mqttSecureClient->stop();
|
||||
delete mqttSecureClient;
|
||||
mqttSecureClient = NULL;
|
||||
} else {
|
||||
mqttClient->stop();
|
||||
}
|
||||
mqttClient = NULL;
|
||||
}
|
||||
yield();
|
||||
} else {
|
||||
mqtt = new MQTTClient(256);
|
||||
mqtt->dropOverflow(true);
|
||||
ws.setMqtt(mqtt);
|
||||
}
|
||||
|
||||
mqttEnabled = true;
|
||||
ws.setMqttEnabled(true);
|
||||
topic = String(mqttConfig.publishTopic);
|
||||
|
||||
if(mqttHandler != NULL) {
|
||||
if(mqttHandler != NULL && mqttHandler->getFormat() != mqttConfig.payloadFormat) {
|
||||
delete mqttHandler;
|
||||
mqttHandler = NULL;
|
||||
}
|
||||
|
||||
switch(mqttConfig.payloadFormat) {
|
||||
case 0:
|
||||
mqttHandler = new JsonMqttHandler(mqtt, (char*) commonBuffer, mqttConfig.clientId, mqttConfig.publishTopic, &hw);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
mqttHandler = new RawMqttHandler(mqtt, (char*) commonBuffer, mqttConfig.publishTopic, mqttConfig.payloadFormat == 2);
|
||||
break;
|
||||
case 3:
|
||||
DomoticzConfig domo;
|
||||
config.getDomoticzConfig(domo);
|
||||
mqttHandler = new DomoticzMqttHandler(mqtt, (char*) commonBuffer, domo);
|
||||
break;
|
||||
case 4:
|
||||
HomeAssistantConfig haconf;
|
||||
config.getHomeAssistantConfig(haconf);
|
||||
mqttHandler = new HomeAssistantMqttHandler(mqtt, (char*) commonBuffer, mqttConfig.clientId, mqttConfig.publishTopic, sysConfig.boardType, haconf, &hw);
|
||||
break;
|
||||
}
|
||||
|
||||
time_t epoch = time(nullptr);
|
||||
if(mqttConfig.ssl) {
|
||||
if(epoch < FirmwareVersion::BuildEpoch) {
|
||||
debugI_P(PSTR("NTP not ready for MQTT SSL"));
|
||||
return;
|
||||
}
|
||||
debugI_P(PSTR("MQTT SSL is configured (%dkb free heap)"), ESP.getFreeHeap());
|
||||
if(mqttSecureClient == NULL) {
|
||||
mqttSecureClient = new WiFiClientSecure();
|
||||
#if defined(ESP8266)
|
||||
mqttSecureClient->setBufferSizes(512, 512);
|
||||
debugD_P(PSTR("ESP8266 firmware does not have enough memory..."));
|
||||
return;
|
||||
#endif
|
||||
|
||||
if(LittleFS.begin()) {
|
||||
File file;
|
||||
|
||||
if(LittleFS.exists(FILE_MQTT_CA)) {
|
||||
debugI_P(PSTR("Found MQTT CA file (%dkb free heap)"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CA, (char*) "r");
|
||||
#if defined(ESP8266)
|
||||
BearSSL::X509List *serverTrustedCA = new BearSSL::X509List(file);
|
||||
mqttSecureClient->setTrustAnchors(serverTrustedCA);
|
||||
#elif defined(ESP32)
|
||||
if(mqttSecureClient->loadCACert(file, file.size())) {
|
||||
debugI_P(PSTR("CA accepted"));
|
||||
} else {
|
||||
debugW_P(PSTR("CA was rejected"));
|
||||
delete mqttSecureClient;
|
||||
mqttSecureClient = NULL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
file.close();
|
||||
|
||||
if(LittleFS.exists(FILE_MQTT_CERT) && LittleFS.exists(FILE_MQTT_KEY)) {
|
||||
#if defined(ESP8266)
|
||||
debugI_P(PSTR("Found MQTT certificate file (%dkb free heap)"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CERT, (char*) "r");
|
||||
BearSSL::X509List *serverCertList = new BearSSL::X509List(file);
|
||||
file.close();
|
||||
|
||||
debugI_P(PSTR("Found MQTT key file (%dkb free heap)"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_KEY, (char*) "r");
|
||||
BearSSL::PrivateKey *serverPrivKey = new BearSSL::PrivateKey(file);
|
||||
file.close();
|
||||
|
||||
debugD_P(PSTR("Setting client certificates (%dkb free heap)"), ESP.getFreeHeap());
|
||||
mqttSecureClient->setClientRSACert(serverCertList, serverPrivKey);
|
||||
#elif defined(ESP32)
|
||||
debugI_P(PSTR("Found MQTT certificate file (%dkb free heap)"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CERT, (char*) "r");
|
||||
mqttSecureClient->loadCertificate(file, file.size());
|
||||
file.close();
|
||||
|
||||
debugI_P(PSTR("Found MQTT key file (%dkb free heap)"), ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_KEY, (char*) "r");
|
||||
mqttSecureClient->loadPrivateKey(file, file.size());
|
||||
file.close();
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
debugI_P(PSTR("No CA, disabling certificate validation"));
|
||||
mqttSecureClient->setInsecure();
|
||||
}
|
||||
mqttClient = mqttSecureClient;
|
||||
|
||||
LittleFS.end();
|
||||
debugD_P(PSTR("MQTT SSL setup complete (%dkb free heap)"), ESP.getFreeHeap());
|
||||
}
|
||||
if(mqttHandler == NULL) {
|
||||
switch(mqttConfig.payloadFormat) {
|
||||
case 0:
|
||||
mqttHandler = new JsonMqttHandler(mqttConfig, &Debug, (char*) commonBuffer, &hw);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
mqttHandler = new RawMqttHandler(mqttConfig, &Debug, (char*) commonBuffer);
|
||||
break;
|
||||
case 3:
|
||||
DomoticzConfig domo;
|
||||
config.getDomoticzConfig(domo);
|
||||
mqttHandler = new DomoticzMqttHandler(mqttConfig, &Debug, (char*) commonBuffer, domo);
|
||||
break;
|
||||
case 4:
|
||||
HomeAssistantConfig haconf;
|
||||
config.getHomeAssistantConfig(haconf);
|
||||
mqttHandler = new HomeAssistantMqttHandler(mqttConfig, &Debug, (char*) commonBuffer, sysConfig.boardType, haconf, &hw);
|
||||
break;
|
||||
case 255:
|
||||
mqttHandler = new PassthroughMqttHandler(mqttConfig, &Debug, (char*) commonBuffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(mqttClient == NULL) {
|
||||
debugI_P(PSTR("No SSL, using client without SSL support"));
|
||||
mqttClient = new WiFiClient();
|
||||
ws.setMqttHandler(mqttHandler);
|
||||
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->connect();
|
||||
mqttHandler->publishSystem(&hw, eapi, &ea);
|
||||
}
|
||||
|
||||
if(Debug.isActive(RemoteDebug::INFO)) {
|
||||
debugI_P(PSTR("Connecting to MQTT %s:%d"), mqttConfig.host, mqttConfig.port);
|
||||
}
|
||||
|
||||
mqtt->begin(mqttConfig.host, mqttConfig.port, *mqttClient);
|
||||
|
||||
#if defined(ESP8266)
|
||||
if(mqttSecureClient) {
|
||||
time_t epoch = time(nullptr);
|
||||
debugD_P(PSTR("Setting NTP time %lu for secure MQTT connection"), epoch);
|
||||
mqttSecureClient->setX509Time(epoch);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Connect to a unsecure or secure MQTT server
|
||||
if ((strlen(mqttConfig.username) == 0 && mqtt->connect(mqttConfig.clientId)) ||
|
||||
(strlen(mqttConfig.username) > 0 && mqtt->connect(mqttConfig.clientId, mqttConfig.username, mqttConfig.password))) {
|
||||
if (Debug.isActive(RemoteDebug::INFO)) debugI_P(PSTR("Successfully connected to MQTT!"));
|
||||
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->publishSystem(&hw, eapi, &ea);
|
||||
}
|
||||
|
||||
// Subscribe to the chosen MQTT topic, if set in configuration
|
||||
if (strlen(mqttConfig.subscribeTopic) > 0) {
|
||||
mqtt->onMessage(mqttMessageReceived);
|
||||
mqtt->subscribe(String(mqttConfig.subscribeTopic) + "/#");
|
||||
debugI_P(PSTR(" Subscribing to [%s]\n"), mqttConfig.subscribeTopic);
|
||||
}
|
||||
} else {
|
||||
if (Debug.isActive(RemoteDebug::ERROR)) {
|
||||
debugE_P(PSTR("Failed to connect to MQTT: %d"), mqtt->lastError());
|
||||
#if defined(ESP8266)
|
||||
if(mqttSecureClient) {
|
||||
mqttSecureClient->getLastSSLError((char*) commonBuffer, BUF_SIZE_COMMON);
|
||||
Debug.println((char*) commonBuffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
void configFileParse() {
|
||||
|
||||
28
src/PassthroughMqttHandler.cpp
Normal file
28
src/PassthroughMqttHandler.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "PassthroughMqttHandler.h"
|
||||
|
||||
bool PassthroughMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, EntsoeApi* eapi) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PassthroughMqttHandler::publishTemperatures(AmsConfiguration*, HwTools*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PassthroughMqttHandler::publishPrices(EntsoeApi*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PassthroughMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PassthroughMqttHandler::publishRaw(String data) {
|
||||
bool ret = mqtt.publish(mqttConfig.publishTopic, data);
|
||||
loop();
|
||||
delay(10);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t PassthroughMqttHandler::getFormat() {
|
||||
return 255;
|
||||
}
|
||||
17
src/PassthroughMqttHandler.h
Normal file
17
src/PassthroughMqttHandler.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef _PASSTHROUGHMQTTHANDLER_H
|
||||
#define _PASSTHROUGHMQTTHANDLER_H
|
||||
|
||||
#include "AmsMqttHandler.h"
|
||||
|
||||
class PassthroughMqttHandler : public AmsMqttHandler {
|
||||
public:
|
||||
PassthroughMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf) : AmsMqttHandler(mqttConfig, debugger, buf) {};
|
||||
bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea, EntsoeApi* eapi);
|
||||
bool publishTemperatures(AmsConfiguration*, HwTools*);
|
||||
bool publishPrices(EntsoeApi*);
|
||||
bool publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea);
|
||||
bool publishRaw(String data);
|
||||
|
||||
uint8_t getFormat();
|
||||
};
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user