mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-04-28 21:08:15 +00:00
Merge branch 'master' into dev-v2.2
This commit is contained in:
@@ -65,10 +65,11 @@ ADC_MODE(ADC_VCC);
|
||||
#include "RemoteDebug.h"
|
||||
|
||||
#define BUF_SIZE_COMMON (2048)
|
||||
#define BUF_SIZE_HAN (1024)
|
||||
#define BUF_SIZE_HAN (1280)
|
||||
|
||||
#include "IEC6205621.h"
|
||||
#include "IEC6205675.h"
|
||||
#include "LNG.h"
|
||||
|
||||
#include "ams/DataParsers.h"
|
||||
|
||||
@@ -118,7 +119,6 @@ DLMSParser *dlmsParser = NULL;
|
||||
DSMRParser *dsmrParser = NULL;
|
||||
|
||||
void setup() {
|
||||
WiFiConfig wifi;
|
||||
Serial.begin(115200);
|
||||
|
||||
if(!config.getGpioConfig(gpioConfig)) {
|
||||
@@ -245,7 +245,6 @@ void setup() {
|
||||
}
|
||||
|
||||
Debug.setSerialEnabled(true);
|
||||
DebugConfig debug;
|
||||
delay(1);
|
||||
|
||||
float vcc = hw.getVcc();
|
||||
@@ -435,6 +434,10 @@ void loop() {
|
||||
}
|
||||
}
|
||||
|
||||
if(now > 10000 && now - lastErrorBlink > 3000) {
|
||||
errorBlink();
|
||||
}
|
||||
|
||||
// Only do normal stuff if we're not booted as AP
|
||||
if (WiFi.getMode() != WIFI_AP) {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
@@ -505,13 +508,10 @@ void loop() {
|
||||
MDNS.update();
|
||||
#endif
|
||||
|
||||
if(now > 10000 && now - lastErrorBlink > 3000) {
|
||||
errorBlink();
|
||||
}
|
||||
|
||||
if (mqttEnabled || config.isMqttChanged()) {
|
||||
if(mqtt == NULL || !mqtt->connected() || config.isMqttChanged()) {
|
||||
MQTT_connect();
|
||||
config.ackMqttChange();
|
||||
}
|
||||
} else if(mqtt != NULL && mqtt->connected()) {
|
||||
mqttClient->stop();
|
||||
@@ -589,11 +589,11 @@ void loop() {
|
||||
if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) {
|
||||
mqttHandler->publishTemperatures(&config, &hw);
|
||||
}
|
||||
debugD("Used %d ms to update temperature", millis()-start);
|
||||
debugD("Used %ld ms to update temperature", millis()-start);
|
||||
}
|
||||
if(now - lastSysupdate > 10000) {
|
||||
if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) {
|
||||
mqttHandler->publishSystem(&hw);
|
||||
mqttHandler->publishSystem(&hw, eapi, &ea);
|
||||
}
|
||||
lastSysupdate = now;
|
||||
}
|
||||
@@ -723,22 +723,25 @@ void errorBlink() {
|
||||
if(lastError == 3)
|
||||
lastError = 0;
|
||||
lastErrorBlink = millis();
|
||||
for(;lastError < 3;lastError++) {
|
||||
switch(lastError) {
|
||||
while(lastError < 3) {
|
||||
switch(lastError++) {
|
||||
case 0:
|
||||
if(lastErrorBlink - meterState.getLastUpdateMillis() > 30000) {
|
||||
debugW("No HAN data received last 30s, single blink");
|
||||
hw.ledBlink(LED_RED, 1); // If no message received from AMS in 30 sec, blink once
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(mqttEnabled && mqtt != NULL && mqtt->lastError() != 0) {
|
||||
debugW("MQTT connection not available, double blink");
|
||||
hw.ledBlink(LED_RED, 2); // If MQTT error, blink twice
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(WiFi.getMode() != WIFI_AP && WiFi.status() != WL_CONNECTED) {
|
||||
debugW("WiFi not connected, tripe blink");
|
||||
hw.ledBlink(LED_RED, 3); // If WiFi not connected, blink three times
|
||||
return;
|
||||
}
|
||||
@@ -825,6 +828,11 @@ bool readHanPort() {
|
||||
}
|
||||
if(pos == DATA_PARSE_INCOMPLETE) {
|
||||
return false;
|
||||
} else if(pos == DATA_PARSE_UNKNOWN_DATA) {
|
||||
len = len + hanSerial->readBytes(hanBuffer+len, BUF_SIZE_HAN-len);
|
||||
debugPrint(hanBuffer, 0, len);
|
||||
len = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(pos == DATA_PARSE_INTERMEDIATE_SEGMENT) {
|
||||
@@ -848,20 +856,26 @@ bool readHanPort() {
|
||||
}
|
||||
|
||||
AmsData data;
|
||||
char* payload = ((char *) (hanBuffer)) + 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(hanBuffer+pos, ctx.length));
|
||||
mqtt->publish(topic.c_str(), toHex((byte*) payload, ctx.length));
|
||||
mqtt->loop();
|
||||
}
|
||||
|
||||
debugV("Using application data:");
|
||||
if(Debug.isActive(RemoteDebug::VERBOSE)) debugPrint(hanBuffer+pos, 0, ctx.length);
|
||||
if(Debug.isActive(RemoteDebug::VERBOSE)) debugPrint((byte*) payload, 0, ctx.length);
|
||||
|
||||
// TODO: Split IEC6205675 into DataParserKaifa and DataParserObis. This way we can add other means of parsing, for those other proprietary formats
|
||||
data = IEC6205675(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, ctx);
|
||||
// Rudimentary detector for L&G proprietary format
|
||||
if(payload[0] == CosemTypeStructure && payload[2] == CosemTypeArray && payload[1] == payload[3]) {
|
||||
data = LNG(payload, meterState.getMeterType(), &meterConfig, ctx, &Debug);
|
||||
} else {
|
||||
// TODO: Split IEC6205675 into DataParserKaifa and DataParserObis. This way we can add other means of parsing, for those other proprietary formats
|
||||
data = IEC6205675(payload, meterState.getMeterType(), &meterConfig, ctx);
|
||||
}
|
||||
} else if(ctx.type == DATA_TAG_DSMR) {
|
||||
data = IEC6205621(((char *) (hanBuffer)) + pos);
|
||||
data = IEC6205621(payload);
|
||||
}
|
||||
len = 0;
|
||||
|
||||
@@ -977,17 +991,34 @@ void debugPrint(byte *buffer, int start, int length) {
|
||||
Debug.println("");
|
||||
}
|
||||
|
||||
unsigned long wifiTimeout = WIFI_CONNECTION_TIMEOUT;
|
||||
unsigned long lastWifiRetry = -WIFI_CONNECTION_TIMEOUT;
|
||||
void WiFi_connect() {
|
||||
if(millis() - lastWifiRetry < wifiTimeout) {
|
||||
delay(50);
|
||||
return;
|
||||
}
|
||||
lastWifiRetry = millis();
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
if(WiFi.status() == WL_DISCONNECTED) {
|
||||
if(millis() - lastWifiRetry < WIFI_CONNECTION_TIMEOUT) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(WiFi.getMode() != WIFI_OFF) {
|
||||
switch(WiFi.status()) {
|
||||
case WL_NO_SSID_AVAIL:
|
||||
debugE("WiFi error, no SSID available");
|
||||
break;
|
||||
case WL_CONNECT_FAILED:
|
||||
debugE("WiFi error, connection failed");
|
||||
break;
|
||||
case WL_CONNECTION_LOST:
|
||||
debugE("WiFi error, connection lost");
|
||||
break;
|
||||
#if defined(ESP8266)
|
||||
case WL_WRONG_PASSWORD:
|
||||
debugE("WiFi error, wrong password");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
debugE("WiFi error, %d", WiFi.status());
|
||||
break;
|
||||
}
|
||||
if(wifiReconnectCount > 3) {
|
||||
ESP.restart();
|
||||
return;
|
||||
@@ -1021,11 +1052,13 @@ void WiFi_connect() {
|
||||
WiFi.softAPdisconnect(true);
|
||||
WiFi.enableAP(false);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
#if defined(ESP8266)
|
||||
WiFi.forceSleepBegin();
|
||||
#endif
|
||||
yield();
|
||||
wifiTimeout = 5000;
|
||||
return;
|
||||
}
|
||||
wifiTimeout = WIFI_CONNECTION_TIMEOUT;
|
||||
lastWifiRetry = millis();
|
||||
|
||||
WiFiConfig wifi;
|
||||
if(!config.getWiFiConfig(wifi) || strlen(wifi.ssid) == 0) {
|
||||
@@ -1043,7 +1076,7 @@ void WiFi_connect() {
|
||||
}
|
||||
#endif
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.setSleep(WIFI_PS_MIN_MODEM);
|
||||
WiFi.setSleep(WIFI_PS_MAX_MODEM);
|
||||
#if defined(ESP32)
|
||||
if(wifi.power >= 195)
|
||||
WiFi.setTxPower(WIFI_POWER_19_5dBm);
|
||||
@@ -1113,16 +1146,16 @@ void WiFi_connect() {
|
||||
|
||||
void mqttMessageReceived(String &topic, String &payload) {
|
||||
debugI("Received message for topic %s", topic.c_str() );
|
||||
if(meterConfig.source == METER_SOURCE_MQTT) {
|
||||
DataParserContext ctx = {payload.length()/2};
|
||||
fromHex(hanBuffer, payload, ctx.length);
|
||||
uint16_t pos = unwrapData(hanBuffer, ctx);
|
||||
//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;
|
||||
int16_t ret = 0;
|
||||
bool doRet = false;
|
||||
uint16_t end = BUF_SIZE_HAN;
|
||||
uint8_t tag = (*buf);
|
||||
@@ -1243,7 +1276,6 @@ void MQTT_connect() {
|
||||
if(Debug.isActive(RemoteDebug::WARNING)) debugW("No MQTT config");
|
||||
mqttEnabled = false;
|
||||
ws.setMqttEnabled(false);
|
||||
config.ackMqttChange();
|
||||
return;
|
||||
}
|
||||
if(mqtt != NULL) {
|
||||
@@ -1258,20 +1290,19 @@ void MQTT_connect() {
|
||||
}
|
||||
|
||||
mqtt->disconnect();
|
||||
if(config.isMqttChanged()) {
|
||||
if(mqttSecureClient != NULL) {
|
||||
mqttSecureClient->stop();
|
||||
delete mqttSecureClient;
|
||||
mqttSecureClient = NULL;
|
||||
} else {
|
||||
mqttClient->stop();
|
||||
}
|
||||
mqttClient = NULL;
|
||||
}
|
||||
yield();
|
||||
} else {
|
||||
uint16_t size = 256;
|
||||
switch(mqttConfig.payloadFormat) {
|
||||
case 0: // JSON
|
||||
case 4: // Home Assistant
|
||||
size = 768;
|
||||
break;
|
||||
case 255: // Raw frame
|
||||
size = 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
mqtt = new MQTTClient(size);
|
||||
mqtt = new MQTTClient(1024);
|
||||
ws.setMqtt(mqtt);
|
||||
}
|
||||
|
||||
@@ -1306,54 +1337,54 @@ void MQTT_connect() {
|
||||
debugI("MQTT SSL is configured (%dkb free heap)", ESP.getFreeHeap());
|
||||
if(mqttSecureClient == NULL) {
|
||||
mqttSecureClient = new WiFiClientSecure();
|
||||
}
|
||||
#if defined(ESP8266)
|
||||
mqttSecureClient->setBufferSizes(512, 512);
|
||||
#endif
|
||||
|
||||
if(LittleFS.begin()) {
|
||||
File file;
|
||||
#if defined(ESP8266)
|
||||
mqttSecureClient->setBufferSizes(512, 512);
|
||||
#endif
|
||||
|
||||
if(LittleFS.begin()) {
|
||||
File file;
|
||||
|
||||
if(LittleFS.exists(FILE_MQTT_CA)) {
|
||||
debugI("Found MQTT CA file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CA, "r");
|
||||
#if defined(ESP8266)
|
||||
BearSSL::X509List *serverTrustedCA = new BearSSL::X509List(file);
|
||||
mqttSecureClient->setTrustAnchors(serverTrustedCA);
|
||||
#elif defined(ESP32)
|
||||
mqttSecureClient->loadCACert(file, file.size());
|
||||
#endif
|
||||
file.close();
|
||||
if(LittleFS.exists(FILE_MQTT_CA)) {
|
||||
debugI("Found MQTT CA file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CA, "r");
|
||||
#if defined(ESP8266)
|
||||
BearSSL::X509List *serverTrustedCA = new BearSSL::X509List(file);
|
||||
mqttSecureClient->setTrustAnchors(serverTrustedCA);
|
||||
#elif defined(ESP32)
|
||||
mqttSecureClient->loadCACert(file, file.size());
|
||||
#endif
|
||||
file.close();
|
||||
}
|
||||
|
||||
if(LittleFS.exists(FILE_MQTT_CERT) && LittleFS.exists(FILE_MQTT_KEY)) {
|
||||
#if defined(ESP8266)
|
||||
debugI("Found MQTT certificate file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CERT, "r");
|
||||
BearSSL::X509List *serverCertList = new BearSSL::X509List(file);
|
||||
file.close();
|
||||
|
||||
debugI("Found MQTT key file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_KEY, "r");
|
||||
BearSSL::PrivateKey *serverPrivKey = new BearSSL::PrivateKey(file);
|
||||
file.close();
|
||||
|
||||
debugD("Setting client certificates (%dkb free heap)", ESP.getFreeHeap());
|
||||
mqttSecureClient->setClientRSACert(serverCertList, serverPrivKey);
|
||||
#elif defined(ESP32)
|
||||
debugI("Found MQTT certificate file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CERT, "r");
|
||||
mqttSecureClient->loadCertificate(file, file.size());
|
||||
file.close();
|
||||
|
||||
debugI("Found MQTT key file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_KEY, "r");
|
||||
mqttSecureClient->loadPrivateKey(file, file.size());
|
||||
file.close();
|
||||
#endif
|
||||
}
|
||||
LittleFS.end();
|
||||
debugD("MQTT SSL setup complete (%dkb free heap)", ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
if(LittleFS.exists(FILE_MQTT_CERT) && LittleFS.exists(FILE_MQTT_KEY)) {
|
||||
#if defined(ESP8266)
|
||||
debugI("Found MQTT certificate file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CERT, "r");
|
||||
BearSSL::X509List *serverCertList = new BearSSL::X509List(file);
|
||||
file.close();
|
||||
|
||||
debugI("Found MQTT key file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_KEY, "r");
|
||||
BearSSL::PrivateKey *serverPrivKey = new BearSSL::PrivateKey(file);
|
||||
file.close();
|
||||
|
||||
debugD("Setting client certificates (%dkb free heap)", ESP.getFreeHeap());
|
||||
mqttSecureClient->setClientRSACert(serverCertList, serverPrivKey);
|
||||
#elif defined(ESP32)
|
||||
debugI("Found MQTT certificate file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_CERT, "r");
|
||||
mqttSecureClient->loadCertificate(file, file.size());
|
||||
file.close();
|
||||
|
||||
debugI("Found MQTT key file (%dkb free heap)", ESP.getFreeHeap());
|
||||
file = LittleFS.open(FILE_MQTT_KEY, "r");
|
||||
mqttSecureClient->loadPrivateKey(file, file.size());
|
||||
file.close();
|
||||
#endif
|
||||
}
|
||||
LittleFS.end();
|
||||
debugD("MQTT SSL setup complete (%dkb free heap)", ESP.getFreeHeap());
|
||||
}
|
||||
mqttClient = mqttSecureClient;
|
||||
} else if(mqttClient == NULL) {
|
||||
@@ -1369,7 +1400,7 @@ void MQTT_connect() {
|
||||
#if defined(ESP8266)
|
||||
if(mqttSecureClient) {
|
||||
time_t epoch = time(nullptr);
|
||||
debugD("Setting NTP time %i for secure MQTT connection", epoch);
|
||||
debugD("Setting NTP time %lld for secure MQTT connection", epoch);
|
||||
mqttSecureClient->setX509Time(epoch);
|
||||
}
|
||||
#endif
|
||||
@@ -1378,10 +1409,9 @@ void MQTT_connect() {
|
||||
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("Successfully connected to MQTT!");
|
||||
config.ackMqttChange();
|
||||
|
||||
if(mqttHandler != NULL) {
|
||||
mqttHandler->publishSystem(&hw);
|
||||
mqttHandler->publishSystem(&hw, eapi, &ea);
|
||||
}
|
||||
|
||||
// Subscribe to the chosen MQTT topic, if set in configuration
|
||||
|
||||
Reference in New Issue
Block a user