Merge branch 'master' into dev-v2.2

This commit is contained in:
Gunnar Skjold 2022-11-01 19:07:00 +01:00
commit 65a09dcecf
19 changed files with 818 additions and 741 deletions

View File

@ -33,6 +33,7 @@ If applicable, add screenshots to help explain your problem.
**Relevant firmware information:**
- Version: [e.g. 2.1.0]
- MQTT: [yes/no]
- MQTT payload type: [e.g. JSON]
- HAN GPIO: [e.g. GPIO5]
- HAN baud and parity: [e.g. 2400 8E1]
- Temperature sensors [e.g. 3xDS18B20]

View File

@ -20,6 +20,7 @@ A clear and concise description of what the problem is.
**Relevant firmware information:**
- Version: [e.g. 2.1.0]
- MQTT: [yes/no]
- MQTT payload type: [e.g. JSON]
- HAN GPIO: [e.g. GPIO5]
- HAN baud and parity: [e.g. 2400 8E1]
- Temperature sensors [e.g. 3xDS18B20]

View File

@ -54,7 +54,8 @@ struct WiFiConfig {
char hostname[32];
bool mdns;
uint8_t power;
}; // 210
uint8_t sleep;
}; // 211
struct MqttConfig86 {
char host[128];

View File

@ -24,6 +24,7 @@ bool AmsConfiguration::getWiFiConfig(WiFiConfig& config) {
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_WIFI_START, config);
EEPROM.end();
if(config.sleep > 2) config.sleep = 1;
return true;
} else {
clearWifi(config);
@ -33,6 +34,7 @@ bool AmsConfiguration::getWiFiConfig(WiFiConfig& config) {
bool AmsConfiguration::setWiFiConfig(WiFiConfig& config) {
WiFiConfig existing;
if(config.sleep > 2) config.sleep = 1;
if(getWiFiConfig(existing)) {
wifiChanged |= strcmp(config.ssid, existing.ssid) != 0;
wifiChanged |= strcmp(config.psk, existing.psk) != 0;
@ -45,6 +47,7 @@ bool AmsConfiguration::setWiFiConfig(WiFiConfig& config) {
}
wifiChanged |= strcmp(config.hostname, existing.hostname) != 0;
wifiChanged |= config.power != existing.power;
wifiChanged |= config.sleep != existing.sleep;
} else {
wifiChanged = true;
}
@ -70,6 +73,7 @@ void AmsConfiguration::clearWifi(WiFiConfig& config) {
#endif
strcpy(config.hostname, (String("ams-") + String(chipId, HEX)).c_str());
config.mdns = true;
config.sleep = 0xFF;
}
void AmsConfiguration::clearWifiIp(WiFiConfig& config) {
@ -510,6 +514,7 @@ bool AmsConfiguration::getEnergyAccountingConfig(EnergyAccountingConfig& config)
if(config.thresholds[9] != 255) {
clearEnergyAccountingConfig(config);
}
if(config.hours > 5) config.hours = 5;
return true;
} else {
return false;
@ -549,6 +554,7 @@ void AmsConfiguration::clearEnergyAccountingConfig(EnergyAccountingConfig& confi
config.thresholds[7] = 100;
config.thresholds[8] = 150;
config.thresholds[9] = 255;
config.hours = 3;
}
bool AmsConfiguration::isEnergyAccountingChanged() {

View File

@ -7,20 +7,20 @@
struct DayDataPoints {
uint8_t version;
int16_t hImport[24];
uint16_t hImport[24];
time_t lastMeterReadTime;
uint32_t activeImport;
uint32_t activeExport;
int16_t hExport[24];
uint16_t hExport[24];
}; // 112 bytes
struct MonthDataPoints {
uint8_t version;
int16_t dImport[31];
uint16_t dImport[31];
time_t lastMeterReadTime;
uint32_t activeImport;
uint32_t activeExport;
int16_t dExport[31];
uint16_t dExport[31];
}; // 141 bytes
class AmsDataStorage {

View File

@ -657,7 +657,7 @@ var fetch = function() {
if(ip) {
var v = parseInt(json.i);
var pct = (v*100)/parseInt(json.im);
var pct = Math.min((v*100)/parseInt(json.im), 100);
var append = "W";
if(v > 1000 && !swatt) {
v = (v/1000).toFixed(1);
@ -683,7 +683,7 @@ var fetch = function() {
$('.rim').hide();
if(xp) {
var v = parseInt(json.e);
var pct = (v*100)/(om*1000);
var pct = Math.min((v*100)/(om*1000), 100);
var append = "W";
if(v > 1000 && !swatt) {
v = (v/1000).toFixed(1);
@ -723,21 +723,21 @@ var fetch = function() {
var u1 = parseFloat(json.u1);
t += u1;
c++;
var pct = (Math.max(parseFloat(json.u1)-195.5, 1)*100/69);
var pct = Math.min(Math.max(parseFloat(json.u1)-195.5, 1)*100/69, 100);
arr[r++] = [ds == 1 ? 'L1-L2' : 'L1', u1, "color: " + voltcol(pct) + ";opacity: 0.9;", u1 + "V"];
}
if(json.u2) {
var u2 = parseFloat(json.u2);
t += u2;
c++;
var pct = (Math.max(parseFloat(json.u2)-195.5, 1)*100/69);
var pct = Math.min(Math.max(parseFloat(json.u2)-195.5, 1)*100/69, 100);
arr[r++] = [ds == 1 ? 'L1-L3' : 'L2', u2, "color: " + voltcol(pct) + ";opacity: 0.9;", u2 + "V"];
}
if(json.u3) {
var u3 = parseFloat(json.u3);
t += u3;
c++;
var pct = (Math.max(parseFloat(json.u3)-195.5, 1)*100/69);
var pct = Math.min(Math.max(parseFloat(json.u3)-195.5, 1)*100/69, 100);
arr[r++] = [ds == 1 ? 'L2-L3' : 'L3', u3, "color: " + voltcol(pct) + ";opacity: 0.9;", u3 + "V"];
}
v = t/c;
@ -762,19 +762,19 @@ var fetch = function() {
if(json.i1 || json.u1) {
var i1 = parseFloat(json.i1);
dA = true;
var pct = (parseFloat(json.i1)/parseInt(json.mf))*100;
var pct = Math.min((parseFloat(json.i1)/parseInt(json.mf))*100, 100);
arr[r++] = ['L1', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i1 + "A"];
}
if(json.i2 || json.u2) {
var i2 = parseFloat(json.i2);
dA = true;
var pct = (parseFloat(json.i2)/parseInt(json.mf))*100;
var pct = Math.min((parseFloat(json.i2)/parseInt(json.mf))*100, 100);
arr[r++] = ['L2', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i2 + "A"];
}
if(json.i3 || json.u3) {
var i3 = parseFloat(json.i3);
dA = true;
var pct = (parseFloat(json.i3)/parseInt(json.mf))*100;
var pct = Math.min((parseFloat(json.i3)/parseInt(json.mf))*100, 100);
arr[r++] = ['L3', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i3 + "A"];
}
if(dA) {

View File

@ -37,7 +37,7 @@
</div>
</div>
<div class="row" id="i">
<div class="col-xl-3 col-lg-4 form-group">
<div class="col-xl-3 col-lg-4 col-md-6 form-group">
<div class="input-group input-group-sm">
<div class="input-group-prepend">
<span class="input-group-text">IP</span>
@ -45,7 +45,7 @@
<input type="text" name="i" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{i}"/>
</div>
</div>
<div class="col-xl-3 col-lg-4 form-group">
<div class="col-xl-3 col-lg-4 col-md-6 form-group">
<div class="input-group input-group-sm">
<div class="input-group-prepend">
<span class="input-group-text">Netmask</span>
@ -53,7 +53,7 @@
<input type="text" name="sn" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{sn}"/>
</div>
</div>
<div class="col-xl-3 col-lg-4 form-group">
<div class="col-xl-3 col-lg-4 col-md-6 form-group">
<div class="input-group input-group-sm">
<div class="input-group-prepend">
<span class="input-group-text">Gateway</span>
@ -61,7 +61,7 @@
<input type="text" name="g" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{g}"/>
</div>
</div>
<div class="col-xl-4 col-lg-5 form-group">
<div class="col-xl-4 col-lg-5 col-md-6 form-group">
<div class="input-group input-group-sm">
<div class="input-group-prepend">
<span class="input-group-text">DNS 1</span>
@ -69,7 +69,7 @@
<input type="text" name="d1" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{d1}"/>
</div>
</div>
<div class="col-xl-4 col-lg-5 form-group">
<div class="col-xl-4 col-lg-5 col-md-6 form-group">
<div class="input-group input-group-sm">
<div class="input-group-prepend">
<span class="input-group-text">DNS 2</span>
@ -89,7 +89,21 @@
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-4 col-sm-6 form-group">
<div class="input-group input-group-sm">
<div class="input-group-prepend">
<span class="input-group-text">Power saving</span>
</div>
<select name="z" class="form-control">
<option value="255">Default</option>
<option value="0" {z0}>Off</option>
<option value="1" {z1}>Minimum</option>
<option value="2" {z2}>Maximum</option>
</select>
</div>
</div>
</div>
</div>
<hr/>
<div class="row form-group">

View File

@ -2,6 +2,7 @@ static const char HEADER_CACHE_CONTROL[] PROGMEM = "Cache-Control";
static const char HEADER_PRAGMA[] PROGMEM = "Pragma";
static const char HEADER_EXPIRES[] PROGMEM = "Expires";
static const char HEADER_AUTHENTICATE[] PROGMEM = "WWW-Authenticate";
static const char HEADER_LOCATION[] PROGMEM = "Location";
static const char CACHE_CONTROL_NO_CACHE[] PROGMEM = "no-cache, no-store, must-revalidate";
static const char CACHE_1HR[] PROGMEM = "public, max-age=3600";

File diff suppressed because it is too large Load Diff

View File

@ -237,7 +237,7 @@ float EnergyAccounting::getMonthMax() {
uint32_t maxHour = 0.0;
bool included[5] = { false, false, false, false, false };
while(count < config->hours && count <= 5) {
for(uint8_t x = 0;x < min((uint8_t) 5, config->hours); x++) {
uint8_t maxIdx = 0;
uint16_t maxVal = 0;
for(uint8_t i = 0; i < 5; i++) {
@ -248,8 +248,10 @@ float EnergyAccounting::getMonthMax() {
maxIdx = i;
}
}
included[maxIdx] = true;
count++;
if(maxVal > 0) {
included[maxIdx] = true;
count++;
}
}
for(uint8_t i = 0; i < 5; i++) {
@ -265,7 +267,7 @@ float EnergyAccounting::getPeak(uint8_t num) {
uint8_t count = 0;
bool included[5] = { false, false, false, false, false };
while(count < config->hours && count <= 5) {
for(uint8_t x = 0;x < min((uint8_t) 5, config->hours); x++) {
uint8_t maxIdx = 0;
uint16_t maxVal = 0;
for(uint8_t i = 0; i < 5; i++) {
@ -275,8 +277,10 @@ float EnergyAccounting::getPeak(uint8_t num) {
maxIdx = i;
}
}
included[maxIdx] = true;
count++;
if(maxVal > 0) {
included[maxIdx] = true;
count++;
}
}
uint8_t pos = 0;

View File

@ -3,5 +3,5 @@
"tPO" : %.2f,
"tQI" : %.2f,
"tQO" : %.2f,
"rtc" : %lld
"rtc" : %lu
}

View File

@ -2,7 +2,7 @@
"id" : "%s",
"name" : "%s",
"up" : %u,
"t" : %lld,
"t" : %lu,
"vcc" : %.3f,
"rssi": %d,
"temp": %.2f,

View File

@ -2,7 +2,7 @@
"id" : "%s",
"name" : "%s",
"up" : %u,
"t" : %lld,
"t" : %lu,
"vcc" : %.3f,
"rssi": %d,
"temp": %.2f,

View File

@ -2,7 +2,7 @@
"id" : "%s",
"name" : "%s",
"up" : %u,
"t" : %lld,
"t" : %lu,
"vcc" : %.3f,
"rssi": %d,
"temp": %.2f,
@ -24,7 +24,7 @@
"tPO" : %.3f,
"tQI" : %.3f,
"tQO" : %.3f,
"rtc" : %lld
"rtc" : %lu
},
"realtime" : {
"h" : %.2f,

View File

@ -2,7 +2,7 @@
"id" : "%s",
"name" : "%s",
"up" : %u,
"t" : %lld,
"t" : %lu,
"vcc" : %.3f,
"rssi": %d,
"temp": %.2f,
@ -34,7 +34,7 @@
"tPO" : %.2f,
"tQI" : %.2f,
"tQO" : %.2f,
"rtc" : %lld
"rtc" : %lu
},
"realtime" : {
"h" : %.2f,

View File

@ -92,7 +92,9 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState, EnergyAccountin
}
mqtt->publish(topic + "/realtime/import/hour", String(ea->getUseThisHour(), 3));
mqtt->publish(topic + "/realtime/import/day", String(ea->getUseToday(), 2));
for(uint8_t i = 1; i <= ea->getConfig()->hours; i++) {
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), 10), true, 0);
}
mqtt->publish(topic + "/realtime/import/threshold", String(ea->getCurrentThreshold(), 10), true, 0);

View File

@ -307,7 +307,7 @@ void setup() {
}
debugI(" flashing");
File firmwareFile = LittleFS.open(FILE_FIRMWARE, "r");
File firmwareFile = LittleFS.open(FILE_FIRMWARE, (char*) "r");
debugD(" firmware size: %d", firmwareFile.size());
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
debugD(" available: %d", maxSketchSpace);
@ -358,7 +358,7 @@ void setup() {
NtpConfig ntp;
if(config.getNtpConfig(ntp)) {
configTime(ntp.offset*10, ntp.summerOffset*10, ntp.enable ? strlen(ntp.server) > 0 ? ntp.server : "pool.ntp.org" : ""); // Add NTP server by default if none is configured
configTime(ntp.offset*10, ntp.summerOffset*10, ntp.enable ? strlen(ntp.server) > 0 ? ntp.server : (char*) F("pool.ntp.org") : (char*) F("")); // Add NTP server by default if none is configured
sntp_servermode_dhcp(ntp.enable && ntp.dhcp ? 1 : 0);
ntpEnabled = ntp.enable;
TimeChangeRule std = {"STD", Last, Sun, Oct, 3, ntp.offset / 6};
@ -473,7 +473,7 @@ void loop() {
if(strlen(wifi.hostname) > 0 && wifi.mdns) {
debugD("mDNS is enabled, using host: %s", wifi.hostname);
if(MDNS.begin(wifi.hostname)) {
MDNS.addService("http", "tcp", 80);
MDNS.addService(F("http"), F("tcp"), 80);
} else {
debugE("Failed to set up mDNS!");
}
@ -607,7 +607,7 @@ void loop() {
}
void setupHanPort(uint8_t pin, uint32_t baud, uint8_t parityOrdinal, bool invert) {
if(Debug.isActive(RemoteDebug::INFO)) Debug.printf("(setupHanPort) Setting up HAN on pin %d with baud %d and parity %d\n", pin, baud, parityOrdinal);
if(Debug.isActive(RemoteDebug::INFO)) Debug.printf((char*) F("(setupHanPort) Setting up HAN on pin %d with baud %d and parity %d\n"), pin, baud, parityOrdinal);
HardwareSerial *hwSerial = NULL;
if(pin == 3 || pin == 113) {
@ -658,14 +658,11 @@ void setupHanPort(uint8_t pin, uint32_t baud, uint8_t parityOrdinal, bool invert
#if defined(CONFIG_IDF_TARGET_ESP32S2)
hwSerial->begin(baud, serialConfig, -1, -1, invert);
hwSerial->setRxBufferSize(768);
uart_set_pin(UART_NUM_1, UART_PIN_NO_CHANGE, pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
#elif defined(ESP32)
hwSerial->begin(baud, serialConfig, -1, -1, invert);
hwSerial->setRxBufferSize(768);
#else
hwSerial->begin(baud, serialConfig, SERIAL_FULL, 1, invert);
hwSerial->setRxBufferSize(768);
#endif
#if defined(ESP8266)
@ -765,14 +762,14 @@ void swapWifiMode() {
if (mode != WIFI_AP || !config.hasConfig()) {
if(Debug.isActive(RemoteDebug::INFO)) debugI("Swapping to AP mode");
WiFi.softAP("AMS2MQTT");
WiFi.softAP((char*) F("AMS2MQTT"));
WiFi.mode(WIFI_AP);
if(dnsServer == NULL) {
dnsServer = new DNSServer();
}
dnsServer->setErrorReplyCode(DNSReplyCode::NoError);
dnsServer->start(53, "*", WiFi.softAPIP());
dnsServer->start(53, (char*) F("*"), WiFi.softAPIP());
} else {
if(Debug.isActive(RemoteDebug::INFO)) debugI("Swapping to STA mode");
if(dnsServer != NULL) {
@ -813,7 +810,7 @@ bool readHanPort() {
hanBuffer[len++] = hanSerial->read();
ctx.length = len;
pos = unwrapData((uint8_t *) hanBuffer, ctx);
if(pos >= 0) {
if(ctx.type > 0 && pos >= 0) {
if(ctx.type == DATA_TAG_DLMS) {
debugV("Received valid DLMS at %d", pos);
} else if(ctx.type == DATA_TAG_DSMR) {
@ -829,6 +826,7 @@ bool readHanPort() {
if(pos == DATA_PARSE_INCOMPLETE) {
return false;
} else if(pos == DATA_PARSE_UNKNOWN_DATA) {
debugV("Unknown data payload:");
len = len + hanSerial->readBytes(hanBuffer+len, BUF_SIZE_HAN-len);
debugPrint(hanBuffer, 0, len);
len = 0;
@ -978,13 +976,13 @@ void printHanReadError(int pos) {
void debugPrint(byte *buffer, int start, int length) {
for (int i = start; i < start + length; i++) {
if (buffer[i] < 0x10)
Debug.print("0");
Debug.print(F("0"));
Debug.print(buffer[i], HEX);
Debug.print(" ");
Debug.print(F(" "));
if ((i - start + 1) % 16 == 0)
Debug.println("");
else if ((i - start + 1) % 4 == 0)
Debug.print(" ");
Debug.print(F(" "));
yield(); // Let other get some resources too
}
@ -1057,7 +1055,6 @@ void WiFi_connect() {
}
#endif
WiFi.mode(WIFI_STA);
WiFi.setSleep(WIFI_PS_MAX_MODEM);
#if defined(ESP32)
if(wifi.power >= 195)
WiFi.setTxPower(WIFI_POWER_19_5dBm);
@ -1099,7 +1096,7 @@ void WiFi_connect() {
if(strlen(wifi.dns2) > 0) {
dns2.fromString(wifi.dns2);
} else if(dns1.toString().isEmpty()) {
dns2.fromString("208.67.220.220"); // Add OpenDNS as second by default if nothing is configured
dns2.fromString(F("208.67.220.220")); // Add OpenDNS as second by default if nothing is configured
}
if(!WiFi.config(ip, gw, sn, dns1, dns2)) {
debugE("Static IP configuration is invalid, not using");
@ -1118,6 +1115,9 @@ void WiFi_connect() {
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
if(WiFi.begin(wifi.ssid, wifi.psk)) {
if(wifi.sleep <= 2) {
WiFi.setSleep(wifi.sleep);
}
yield();
} else {
if (Debug.isActive(RemoteDebug::ERROR)) debugI("Unable to start WiFi");
@ -1176,7 +1176,7 @@ int16_t unwrapData(uint8_t *buf, DataParserContext &context) {
if(res >= 0) doRet = true;
break;
default:
debugE("Ended up in default case while unwrapping...");
debugE("Ended up in default case while unwrapping...(tag %02X)", tag);
return DATA_PARSE_UNKNOWN_DATA;
}
lastTag = tag;
@ -1327,7 +1327,7 @@ void MQTT_connect() {
if(LittleFS.exists(FILE_MQTT_CA)) {
debugI("Found MQTT CA file (%dkb free heap)", ESP.getFreeHeap());
file = LittleFS.open(FILE_MQTT_CA, "r");
file = LittleFS.open(FILE_MQTT_CA, (char*) "r");
#if defined(ESP8266)
BearSSL::X509List *serverTrustedCA = new BearSSL::X509List(file);
mqttSecureClient->setTrustAnchors(serverTrustedCA);
@ -1340,12 +1340,12 @@ void MQTT_connect() {
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");
file = LittleFS.open(FILE_MQTT_CERT, (char*) "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");
file = LittleFS.open(FILE_MQTT_KEY, (char*) "r");
BearSSL::PrivateKey *serverPrivKey = new BearSSL::PrivateKey(file);
file.close();
@ -1353,12 +1353,12 @@ void MQTT_connect() {
mqttSecureClient->setClientRSACert(serverCertList, serverPrivKey);
#elif defined(ESP32)
debugI("Found MQTT certificate file (%dkb free heap)", ESP.getFreeHeap());
file = LittleFS.open(FILE_MQTT_CERT, "r");
file = LittleFS.open(FILE_MQTT_CERT, (char*) "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");
file = LittleFS.open(FILE_MQTT_KEY, (char*) "r");
mqttSecureClient->loadPrivateKey(file, file.size());
file.close();
#endif
@ -1424,7 +1424,7 @@ void configFileParse() {
return;
}
File file = LittleFS.open(FILE_CFG, "r");
File file = LittleFS.open(FILE_CFG, (char*) "r");
bool lSys = false;
bool lWiFi = false;
@ -1454,195 +1454,196 @@ void configFileParse() {
char* buf = (char*) commonBuffer;
memset(buf, 0, 1024);
while((size = file.readBytesUntil('\n', buf, 1024)) > 0) {
if(strncmp(buf, "boardType ", 10) == 0) {
if(strncmp_P(buf, PSTR("boardType "), 10) == 0) {
if(!lSys) { config.getSystemConfig(sys); lSys = true; };
sys.boardType = String(buf+10).toInt();
} else if(strncmp(buf, "ssid ", 5) == 0) {
} else if(strncmp_P(buf, PSTR("ssid "), 5) == 0) {
if(!lWiFi) { config.getWiFiConfig(wifi); lWiFi = true; };
memcpy(wifi.ssid, buf+5, size-5);
} else if(strncmp(buf, "psk ", 4) == 0) {
} else if(strncmp_P(buf, PSTR("psk "), 4) == 0) {
if(!lWiFi) { config.getWiFiConfig(wifi); lWiFi = true; };
memcpy(wifi.psk, buf+4, size-4);
} else if(strncmp(buf, "ip ", 3) == 0) {
} else if(strncmp_P(buf, PSTR("ip "), 3) == 0) {
if(!lWiFi) { config.getWiFiConfig(wifi); lWiFi = true; };
memcpy(wifi.ip, buf+3, size-3);
} else if(strncmp(buf, "gateway ", 8) == 0) {
} else if(strncmp_P(buf, PSTR("gateway "), 8) == 0) {
if(!lWiFi) { config.getWiFiConfig(wifi); lWiFi = true; };
memcpy(wifi.gateway, buf+8, size-8);
} else if(strncmp(buf, "subnet ", 7) == 0) {
} else if(strncmp_P(buf, PSTR("subnet "), 7) == 0) {
if(!lWiFi) { config.getWiFiConfig(wifi); lWiFi = true; };
memcpy(wifi.subnet, buf+7, size-7);
} else if(strncmp(buf, "dns1 ", 5) == 0) {
} else if(strncmp_P(buf, PSTR("dns1 "), 5) == 0) {
if(!lWiFi) { config.getWiFiConfig(wifi); lWiFi = true; };
memcpy(wifi.dns1, buf+5, size-5);
} else if(strncmp(buf, "dns2 ", 5) == 0) {
} else if(strncmp_P(buf, PSTR("dns2 "), 5) == 0) {
if(!lWiFi) { config.getWiFiConfig(wifi); lWiFi = true; };
memcpy(wifi.dns2, buf+5, size-5);
} else if(strncmp(buf, "hostname ", 9) == 0) {
} else if(strncmp_P(buf, PSTR("hostname "), 9) == 0) {
if(!lWiFi) { config.getWiFiConfig(wifi); lWiFi = true; };
memcpy(wifi.hostname, buf+9, size-9);
} else if(strncmp(buf, "mdns ", 5) == 0) {
} else if(strncmp_P(buf, PSTR("mdns "), 5) == 0) {
if(!lWiFi) { config.getWiFiConfig(wifi); lWiFi = true; };
wifi.mdns = String(buf+5).toInt() == 1;;
} else if(strncmp(buf, "mqttHost ", 9) == 0) {
} else if(strncmp_P(buf, PSTR("mqttHost "), 9) == 0) {
if(!lMqtt) { config.getMqttConfig(mqtt); lMqtt = true; };
memcpy(mqtt.host, buf+9, size-9);
} else if(strncmp(buf, "mqttPort ", 9) == 0) {
} else if(strncmp_P(buf, PSTR("mqttPort "), 9) == 0) {
if(!lMqtt) { config.getMqttConfig(mqtt); lMqtt = true; };
mqtt.port = String(buf+9).toInt();
} else if(strncmp(buf, "mqttClientId ", 13) == 0) {
} else if(strncmp_P(buf, PSTR("mqttClientId "), 13) == 0) {
if(!lMqtt) { config.getMqttConfig(mqtt); lMqtt = true; };
memcpy(mqtt.clientId, buf+13, size-13);
} else if(strncmp(buf, "mqttPublishTopic ", 17) == 0) {
} else if(strncmp_P(buf, PSTR("mqttPublishTopic "), 17) == 0) {
if(!lMqtt) { config.getMqttConfig(mqtt); lMqtt = true; };
memcpy(mqtt.publishTopic, buf+17, size-17);
} else if(strncmp(buf, "mqttUsername ", 13) == 0) {
} else if(strncmp_P(buf, PSTR("mqttUsername "), 13) == 0) {
if(!lMqtt) { config.getMqttConfig(mqtt); lMqtt = true; };
memcpy(mqtt.username, buf+13, size-13);
} else if(strncmp(buf, "mqttPassword ", 13) == 0) {
} else if(strncmp_P(buf, PSTR("mqttPassword "), 13) == 0) {
if(!lMqtt) { config.getMqttConfig(mqtt); lMqtt = true; };
memcpy(mqtt.password, buf+13, size-13);
} else if(strncmp(buf, "mqttPayloadFormat ", 18) == 0) {
} else if(strncmp_P(buf, PSTR("mqttPayloadFormat "), 18) == 0) {
if(!lMqtt) { config.getMqttConfig(mqtt); lMqtt = true; };
mqtt.payloadFormat = String(buf+18).toInt();
} else if(strncmp(buf, "mqttSsl ", 8) == 0) {
} else if(strncmp_P(buf, PSTR("mqttSsl "), 8) == 0) {
if(!lMqtt) { config.getMqttConfig(mqtt); lMqtt = true; };
mqtt.ssl = String(buf+8).toInt() == 1;;
} else if(strncmp(buf, "webSecurity ", 12) == 0) {
} else if(strncmp_P(buf, PSTR("webSecurity "), 12) == 0) {
if(!lWeb) { config.getWebConfig(web); lWeb = true; };
web.security = String(buf+12).toInt();
} else if(strncmp(buf, "webUsername ", 12) == 0) {
} else if(strncmp_P(buf, PSTR("webUsername "), 12) == 0) {
if(!lWeb) { config.getWebConfig(web); lWeb = true; };
memcpy(web.username, buf+12, size-12);
} else if(strncmp(buf, "webPassword ", 12) == 0) {
} else if(strncmp_P(buf, PSTR("webPassword "), 12) == 0) {
if(!lWeb) { config.getWebConfig(web); lWeb = true; };
memcpy(web.username, buf+12, size-12);
} else if(strncmp(buf, "meterBaud ", 10) == 0) {
} else if(strncmp_P(buf, PSTR("meterBaud "), 10) == 0) {
if(!lMeter) { config.getMeterConfig(meter); lMeter = true; };
meter.baud = String(buf+10).toInt();
} else if(strncmp(buf, "meterParity ", 12) == 0) {
} else if(strncmp_P(buf, PSTR("meterParity "), 12) == 0) {
if(!lMeter) { config.getMeterConfig(meter); lMeter = true; };
if(strncmp(buf+12, "7N1", 3) == 0) meter.parity = 2;
if(strncmp(buf+12, "8N1", 3) == 0) meter.parity = 3;
if(strncmp(buf+12, "7E1", 3) == 0) meter.parity = 10;
if(strncmp(buf+12, "8E1", 3) == 0) meter.parity = 11;
} else if(strncmp(buf, "meterInvert ", 12) == 0) {
if(strncmp_P(buf+12, PSTR("7N1"), 3) == 0) meter.parity = 2;
if(strncmp_P(buf+12, PSTR("8N1"), 3) == 0) meter.parity = 3;
if(strncmp_P(buf+12, PSTR("7E1"), 3) == 0) meter.parity = 10;
if(strncmp_P(buf+12, PSTR("8E1"), 3) == 0) meter.parity = 11;
} else if(strncmp_P(buf, PSTR("meterInvert "), 12) == 0) {
if(!lMeter) { config.getMeterConfig(meter); lMeter = true; };
meter.invert = String(buf+12).toInt() == 1;;
} else if(strncmp(buf, "meterDistributionSystem ", 24) == 0) {
} else if(strncmp_P(buf, PSTR("meterDistributionSystem "), 24) == 0) {
if(!lMeter) { config.getMeterConfig(meter); lMeter = true; };
meter.distributionSystem = String(buf+24).toInt();
} else if(strncmp(buf, "meterMainFuse ", 14) == 0) {
} else if(strncmp_P(buf, PSTR("meterMainFuse "), 14) == 0) {
if(!lMeter) { config.getMeterConfig(meter); lMeter = true; };
meter.mainFuse = String(buf+14).toInt();
} else if(strncmp(buf, "meterProductionCapacity ", 24) == 0) {
} else if(strncmp_P(buf, PSTR("meterProductionCapacity "), 24) == 0) {
if(!lMeter) { config.getMeterConfig(meter); lMeter = true; };
meter.productionCapacity = String(buf+24).toInt();
} else if(strncmp(buf, "meterEncryptionKey ", 19) == 0) {
} else if(strncmp_P(buf, PSTR("meterEncryptionKey "), 19) == 0) {
if(!lMeter) { config.getMeterConfig(meter); lMeter = true; };
fromHex(meter.encryptionKey, String(buf+19), 16);
} else if(strncmp(buf, "meterAuthenticationKey ", 23) == 0) {
} else if(strncmp_P(buf, PSTR("meterAuthenticationKey "), 23) == 0) {
if(!lMeter) { config.getMeterConfig(meter); lMeter = true; };
fromHex(meter.authenticationKey, String(buf+19), 16);
} else if(strncmp(buf, "gpioHanPin ", 11) == 0) {
} else if(strncmp_P(buf, PSTR("gpioHanPin "), 11) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.hanPin = String(buf+11).toInt();
} else if(strncmp(buf, "gpioApPin ", 10) == 0) {
} else if(strncmp_P(buf, PSTR("gpioApPin "), 10) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.apPin = String(buf+10).toInt();
} else if(strncmp(buf, "gpioLedPin ", 11) == 0) {
} else if(strncmp_P(buf, PSTR("gpioLedPin "), 11) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.ledPin = String(buf+11).toInt();
} else if(strncmp(buf, "gpioLedInverted ", 16) == 0) {
} else if(strncmp_P(buf, PSTR("gpioLedInverted "), 16) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.ledInverted = String(buf+16).toInt() == 1;
} else if(strncmp(buf, "gpioLedPinRed ", 14) == 0) {
} else if(strncmp_P(buf, PSTR("gpioLedPinRed "), 14) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.ledPinRed = String(buf+14).toInt();
} else if(strncmp(buf, "gpioLedPinGreen ", 16) == 0) {
} else if(strncmp_P(buf, PSTR("gpioLedPinGreen "), 16) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.ledPinGreen = String(buf+16).toInt();
} else if(strncmp(buf, "gpioLedPinBlue ", 15) == 0) {
} else if(strncmp_P(buf, PSTR("gpioLedPinBlue "), 15) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.ledPinBlue = String(buf+15).toInt();
} else if(strncmp(buf, "gpioLedRgbInverted ", 19) == 0) {
} else if(strncmp_P(buf, PSTR("gpioLedRgbInverted "), 19) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.ledRgbInverted = String(buf+19).toInt() == 1;
} else if(strncmp(buf, "gpioTempSensorPin ", 18) == 0) {
} else if(strncmp_P(buf, PSTR("gpioTempSensorPin "), 18) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.tempSensorPin = String(buf+18).toInt();
} else if(strncmp(buf, "gpioTempAnalogSensorPin ", 24) == 0) {
} else if(strncmp_P(buf, PSTR("gpioTempAnalogSensorPin "), 24) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.tempAnalogSensorPin = String(buf+24).toInt();
} else if(strncmp(buf, "gpioVccPin ", 11) == 0) {
} else if(strncmp_P(buf, PSTR("gpioVccPin "), 11) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.vccPin = String(buf+11).toInt();
} else if(strncmp(buf, "gpioVccOffset ", 14) == 0) {
} else if(strncmp_P(buf, PSTR("gpioVccOffset "), 14) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.vccOffset = String(buf+14).toDouble() * 100;
} else if(strncmp(buf, "gpioVccMultiplier ", 18) == 0) {
} else if(strncmp_P(buf, PSTR("gpioVccMultiplier "), 18) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.vccMultiplier = String(buf+18).toDouble() * 1000;
} else if(strncmp(buf, "gpioVccBootLimit ", 17) == 0) {
} else if(strncmp_P(buf, PSTR("gpioVccBootLimit "), 17) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.vccBootLimit = String(buf+17).toDouble() * 10;
} else if(strncmp(buf, "gpioVccResistorGnd ", 19) == 0) {
} else if(strncmp_P(buf, PSTR("gpioVccResistorGnd "), 19) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.vccResistorGnd = String(buf+19).toInt();
} else if(strncmp(buf, "gpioVccResistorVcc ", 19) == 0) {
} else if(strncmp_P(buf, PSTR("gpioVccResistorVcc "), 19) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.vccResistorVcc = String(buf+19).toInt();
} else if(strncmp(buf, "domoticzElidx ", 14) == 0) {
} else if(strncmp_P(buf, PSTR("domoticzElidx "), 14) == 0) {
if(!lDomo) { config.getDomoticzConfig(domo); lDomo = true; };
domo.elidx = String(buf+14).toInt();
} else if(strncmp(buf, "domoticzVl1idx ", 15) == 0) {
} else if(strncmp_P(buf, PSTR("domoticzVl1idx "), 15) == 0) {
if(!lDomo) { config.getDomoticzConfig(domo); lDomo = true; };
domo.vl1idx = String(buf+15).toInt();
} else if(strncmp(buf, "domoticzVl2idx ", 15) == 0) {
} else if(strncmp_P(buf, PSTR("domoticzVl2idx "), 15) == 0) {
if(!lDomo) { config.getDomoticzConfig(domo); lDomo = true; };
domo.vl2idx = String(buf+15).toInt();
} else if(strncmp(buf, "domoticzVl3idx ", 15) == 0) {
} else if(strncmp_P(buf, PSTR("domoticzVl3idx "), 15) == 0) {
if(!lDomo) { config.getDomoticzConfig(domo); lDomo = true; };
domo.vl3idx = String(buf+15).toInt();
} else if(strncmp(buf, "domoticzCl1idx ", 15) == 0) {
} else if(strncmp_P(buf, PSTR("domoticzCl1idx "), 15) == 0) {
if(!lDomo) { config.getDomoticzConfig(domo); lDomo = true; };
domo.cl1idx = String(buf+15).toInt();
} else if(strncmp(buf, "ntpEnable ", 10) == 0) {
} else if(strncmp_P(buf, PSTR("ntpEnable "), 10) == 0) {
if(!lNtp) { config.getNtpConfig(ntp); lNtp = true; };
ntp.enable = String(buf+10).toInt() == 1;
} else if(strncmp(buf, "ntpDhcp ", 8) == 0) {
} else if(strncmp_P(buf, PSTR("ntpDhcp "), 8) == 0) {
if(!lNtp) { config.getNtpConfig(ntp); lNtp = true; };
ntp.dhcp = String(buf+8).toInt() == 1;
} else if(strncmp(buf, "ntpOffset ", 10) == 0) {
} else if(strncmp_P(buf, PSTR("ntpOffset "), 10) == 0) {
if(!lNtp) { config.getNtpConfig(ntp); lNtp = true; };
ntp.offset = String(buf+10).toInt() / 10;
} else if(strncmp(buf, "ntpSummerOffset ", 16) == 0) {
} else if(strncmp_P(buf, PSTR("ntpSummerOffset "), 16) == 0) {
if(!lNtp) { config.getNtpConfig(ntp); lNtp = true; };
ntp.summerOffset = String(buf+16).toInt() / 10;
} else if(strncmp(buf, "ntpServer ", 10) == 0) {
} else if(strncmp_P(buf, PSTR("ntpServer "), 10) == 0) {
if(!lNtp) { config.getNtpConfig(ntp); lNtp = true; };
memcpy(ntp.server, buf+10, size-10);
} else if(strncmp(buf, "entsoeToken ", 12) == 0) {
} else if(strncmp_P(buf, PSTR("entsoeToken "), 12) == 0) {
if(!lEntsoe) { config.getEntsoeConfig(entsoe); lEntsoe = true; };
memcpy(entsoe.token, buf+12, size-12);
} else if(strncmp(buf, "entsoeArea ", 11) == 0) {
} else if(strncmp_P(buf, PSTR("entsoeArea "), 11) == 0) {
if(!lEntsoe) { config.getEntsoeConfig(entsoe); lEntsoe = true; };
memcpy(entsoe.area, buf+11, size-11);
} else if(strncmp(buf, "entsoeCurrency ", 15) == 0) {
} else if(strncmp_P(buf, PSTR("entsoeCurrency "), 15) == 0) {
if(!lEntsoe) { config.getEntsoeConfig(entsoe); lEntsoe = true; };
memcpy(entsoe.currency, buf+15, size-15);
} else if(strncmp(buf, "entsoeMultiplier ", 17) == 0) {
} else if(strncmp_P(buf, PSTR("entsoeMultiplier "), 17) == 0) {
if(!lEntsoe) { config.getEntsoeConfig(entsoe); lEntsoe = true; };
entsoe.multiplier = String(buf+17).toDouble() * 1000;
} else if(strncmp(buf, "thresholds ", 11) == 0) {
} else if(strncmp_P(buf, PSTR("thresholds "), 11) == 0) {
if(!lEac) { config.getEnergyAccountingConfig(eac); lEac = true; };
int i = 0;
char * pch = strtok (buf+11," ");
while (pch != NULL) {
while (pch != NULL && i < 10) {
eac.thresholds[i++] = String(pch).toInt();
pch = strtok (NULL, " ");
}
} else if(strncmp(buf, "dayplot ", 8) == 0) {
eac.hours = String(pch).toInt();
} else if(strncmp_P(buf, PSTR("dayplot "), 8) == 0) {
int i = 0;
DayDataPoints day = { 4 }; // Use a version we know the multiplier of the data points
char * pch = strtok (buf+8," ");
@ -1665,7 +1666,7 @@ void configFileParse() {
}
ds.setDayData(day);
sDs = true;
} else if(strncmp(buf, "monthplot ", 10) == 0) {
} else if(strncmp_P(buf, PSTR("monthplot "), 10) == 0) {
int i = 0;
MonthDataPoints month = { 5 }; // Use a version we know the multiplier of the data points
char * pch = strtok (buf+10," ");
@ -1688,7 +1689,7 @@ void configFileParse() {
}
ds.setMonthData(month);
sDs = true;
} else if(strncmp(buf, "energyaccounting ", 17) == 0) {
} else if(strncmp_P(buf, PSTR("energyaccounting "), 17) == 0) {
uint8_t i = 0;
EnergyAccountingData ead = { 4, 0,
0, 0, 0,
@ -1753,6 +1754,7 @@ void configFileParse() {
if(lDomo) config.setDomoticzConfig(domo);
if(lNtp) config.setNtpConfig(ntp);
if(lEntsoe) config.setEntsoeConfig(entsoe);
if(lEac) config.setEnergyAccountingConfig(eac);
if(sDs) ds.save();
if(sEa) ea.save();
config.save();

View File

@ -1,6 +1,6 @@
#include "LNG.h"
#include "lwip/def.h"
#include "ams/Cosem.h"
#include "ams/ntohll.h"
LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx, RemoteDebug* debugger) {
LngHeader* h = (LngHeader*) payload;
@ -11,9 +11,10 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da
uint8_t* ptr = (uint8_t*) &h[1];
uint8_t* data = ptr + (18*h->arrayLength); // Skip descriptors
uint16_t o170 = 0, o270 = 0;
uint16_t o181 = 0, o182 = 0;
uint16_t o281 = 0, o282 = 0;
uint64_t o170 = 0, o270 = 0;
uint64_t o180 = 0, o280 = 0;
uint64_t o181 = 0, o182 = 0;
uint64_t o281 = 0, o282 = 0;
LngObisDescriptor* descriptor = (LngObisDescriptor*) ptr;
for(uint8_t x = 0; x < h->arrayLength-1; x++) {
ptr = (uint8_t*) &descriptor[1];
@ -24,39 +25,41 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da
if(descriptor->obis[2] == 1) {
if(descriptor->obis[3] == 7) {
if(descriptor->obis[4] == 0) {
o170 = ntohl(item->dlu.data);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
o170 = getNumber(item);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o170);
}
} else if(descriptor->obis[3] == 8) {
if(descriptor->obis[4] == 0) {
activeImportCounter = ntohl(item->dlu.data) / 1000.0;
o180 = getNumber(item);
listType = listType >= 3 ? listType : 3;
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o180);
activeImportCounter = o180 / 1000.0;
} else if(descriptor->obis[4] == 1) {
o181 = ntohl(item->dlu.data);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
o181 = getNumber(item);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o181);
} else if(descriptor->obis[4] == 2) {
o182 = ntohl(item->dlu.data);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
o182 = getNumber(item);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o182);
}
}
} else if(descriptor->obis[2] == 2) {
if(descriptor->obis[3] == 7) {
if(descriptor->obis[4] == 0) {
o270 = ntohl(item->dlu.data);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
o270 = getNumber(item);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o270);
}
} else if(descriptor->obis[3] == 8) {
if(descriptor->obis[4] == 0) {
activeExportCounter = ntohl(item->dlu.data) / 1000.0;
o280 = getNumber(item);
listType = listType >= 3 ? listType : 3;
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o280);
activeExportCounter = o280 / 1000.0;
} else if(descriptor->obis[4] == 1) {
o281 = ntohl(item->dlu.data);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
o281 = getNumber(item);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o281);
} else if(descriptor->obis[4] == 2) {
o282 = ntohl(item->dlu.data);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
o282 = getNumber(item);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu", o282);
}
}
} else if(descriptor->obis[2] == 96) {
@ -101,11 +104,49 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da
if((*data) == 0x09) {
data += (*(data+1))+2;
} else {
} else if((*data) == 0x15) {
data += 9;
} else if((*data) == 0x06) {
data += 5;
} else if((*data) == 0x12) {
data += 3;
}
lastUpdateMillis = millis();
}
}
}
}
uint64_t LNG::getNumber(CosemData* item) {
if(item != NULL) {
uint64_t ret = 0.0;
switch(item->base.type) {
case CosemTypeLongSigned: {
int16_t i16 = ntohs(item->ls.data);
return i16;
}
case CosemTypeLongUnsigned: {
uint16_t u16 = ntohs(item->lu.data);
return u16;
}
case CosemTypeDLongSigned: {
int32_t i32 = ntohl(item->dlu.data);
return i32;
}
case CosemTypeDLongUnsigned: {
uint32_t u32 = ntohl(item->dlu.data);
return u32;
}
case CosemTypeLong64Signed: {
int64_t i64 = ntohll(item->l64s.data);
return i64;
}
case CosemTypeLong64Unsigned: {
uint64_t u64 = ntohll(item->l64u.data);
return u64;
}
}
return ret;
}
return 0.0;
}

View File

@ -4,6 +4,7 @@
#include "AmsData.h"
#include "AmsConfiguration.h"
#include "ams/DataParser.h"
#include "ams/Cosem.h"
#include "RemoteDebug.h"
struct LngHeader {
@ -25,6 +26,7 @@ struct LngObisDescriptor {
class LNG : public AmsData {
public:
LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, DataParserContext &ctx, RemoteDebug* debugger);
uint64_t getNumber(CosemData* item);
};
#endif