Merge branch 'master' into hub-prices

This commit is contained in:
Gunnar Skjold 2022-12-02 19:04:14 +01:00
commit e34da5fd83
7 changed files with 166 additions and 37 deletions

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) {
@ -671,6 +675,14 @@ bool AmsConfiguration::hasConfig() {
configVersion = 0;
return false;
}
case 95:
configVersion = -1; // Prevent loop
if(relocateConfig95()) {
configVersion = 96;
} else {
configVersion = 0;
return false;
}
case EEPROM_CHECK_SUM:
return true;
default:
@ -848,6 +860,23 @@ bool AmsConfiguration::relocateConfig94() {
return ret;
}
bool AmsConfiguration::relocateConfig95() {
MeterConfig meter;
MeterConfig95 meter95;
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_METER_START, meter);
EEPROM.get(CONFIG_METER_START, meter95);
meter.wattageMultiplier = meter95.wattageMultiplier;
meter.voltageMultiplier = meter95.voltageMultiplier;
meter.amperageMultiplier = meter95.amperageMultiplier;
meter.accumulatedMultiplier = meter95.accumulatedMultiplier;
EEPROM.put(CONFIG_METER_START, meter);
EEPROM.put(EEPROM_CONFIG_ADDRESS, 96);
bool ret = EEPROM.commit();
EEPROM.end();
return ret;
}
bool AmsConfiguration::save() {
EEPROM.begin(EEPROM_SIZE);
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);

View File

@ -4,7 +4,7 @@
#include "Arduino.h"
#define EEPROM_SIZE 1024*3
#define EEPROM_CHECK_SUM 95 // Used to check if config is stored. Change if structure changes
#define EEPROM_CHECK_SUM 96 // Used to check if config is stored. Change if structure changes
#define EEPROM_CONFIG_ADDRESS 0
#define EEPROM_TEMP_CONFIG_ADDRESS 2048
@ -54,7 +54,8 @@ struct WiFiConfig {
char hostname[32];
bool mdns;
uint8_t power;
}; // 210
uint8_t sleep;
}; // 211
struct MqttConfig86 {
char host[128];
@ -87,6 +88,23 @@ struct WebConfig {
}; // 129
struct MeterConfig {
uint32_t baud;
uint8_t parity;
bool invert;
uint8_t distributionSystem;
uint8_t mainFuse;
uint8_t productionCapacity;
uint8_t encryptionKey[16];
uint8_t authenticationKey[16];
uint32_t wattageMultiplier;
uint32_t voltageMultiplier;
uint32_t amperageMultiplier;
uint32_t accumulatedMultiplier;
uint8_t source;
uint8_t parser;
}; // 50
struct MeterConfig95 {
uint32_t baud;
uint8_t parity;
bool invert;
@ -269,6 +287,7 @@ private:
bool relocateConfig92(); // 2.0.3
bool relocateConfig93(); // 2.1.0
bool relocateConfig94(); // 2.1.4
bool relocateConfig95(); // 2.1.13
void saveToFs();
bool loadFromFs(uint8_t version);

View File

@ -805,7 +805,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) {
@ -821,6 +821,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;
@ -1049,7 +1050,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);
@ -1110,6 +1110,19 @@ void WiFi_connect() {
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
if(WiFi.begin(wifi.ssid, wifi.psk)) {
if(wifi.sleep <= 2) {
switch(wifi.sleep) {
case 0:
WiFi.setSleep(WIFI_PS_NONE);
break;
case 1:
WiFi.setSleep(WIFI_PS_MIN_MODEM);
break;
case 2:
WiFi.setSleep(WIFI_PS_MAX_MODEM);
break;
}
}
yield();
} else {
if (Debug.isActive(RemoteDebug::ERROR)) debugI("Unable to start WiFi");
@ -1168,7 +1181,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;

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

View File

@ -444,6 +444,9 @@ void AmsWebServer::configWifiHtml() {
html.replace(F("{h}"), wifi.hostname);
html.replace(F("{m}"), wifi.mdns ? F("checked") : F(""));
html.replace(F("{w}"), String(wifi.power / 10.0, 1));
html.replace(F("{z0}"), wifi.sleep == 0 ? "selected" : "");
html.replace(F("{z1}"), wifi.sleep == 1 ? "selected" : "");
html.replace(F("{z2}"), wifi.sleep == 2 ? "selected" : "");
#if defined(ESP32)
html.replace(F("{wm}"), "19.5");
#elif defined(ESP8266)
@ -1014,9 +1017,11 @@ void AmsWebServer::handleSetup() {
DebugConfig debugConfig;
config->getDebugConfig(debugConfig);
config->clear();
WiFiConfig wifi;
config->clearWifi(wifi);
switch(sys.boardType) {
case 0: // roarfred
gpioConfig->hanPin = 3;
@ -1041,6 +1046,7 @@ void AmsWebServer::handleSetup() {
gpioConfig->ledInverted = true;
gpioConfig->tempSensorPin = 5;
gpioConfig->vccBootLimit = 33;
wifi.sleep = 1;
break;
case 3: // Pow UART0
gpioConfig->hanPin = 3;
@ -1050,6 +1056,7 @@ void AmsWebServer::handleSetup() {
gpioConfig->ledPinRed = 13;
gpioConfig->ledPinGreen = 14;
gpioConfig->ledRgbInverted = true;
wifi.sleep = 1;
break;
case 4: // Pow GPIO12
gpioConfig->hanPin = 12;
@ -1059,6 +1066,7 @@ void AmsWebServer::handleSetup() {
gpioConfig->ledPinRed = 13;
gpioConfig->ledPinGreen = 14;
gpioConfig->ledRgbInverted = true;
wifi.sleep = 1;
break;
case 5: // Pow-K+ UART2
gpioConfig->hanPin = 16;
@ -1069,6 +1077,7 @@ void AmsWebServer::handleSetup() {
gpioConfig->vccPin = 10;
gpioConfig->vccResistorGnd = 22;
gpioConfig->vccResistorVcc = 33;
wifi.sleep = 1;
break;
case 6: // Pow-P1
gpioConfig->hanPin = 16;
@ -1089,6 +1098,7 @@ void AmsWebServer::handleSetup() {
gpioConfig->vccPin = 10;
gpioConfig->vccResistorGnd = 22;
gpioConfig->vccResistorVcc = 33;
wifi.sleep = 2;
break;
case 101: // D1
gpioConfig->hanPin = 5;
@ -1125,18 +1135,17 @@ void AmsWebServer::handleSetup() {
break;
case 50: // S2
gpioConfig->hanPin = 18;
wifi.sleep = 1;
break;
case 51: // S2-mini
gpioConfig->hanPin = 18;
gpioConfig->ledPin = 15;
gpioConfig->ledInverted = false;
gpioConfig->apPin = 0;
wifi.sleep = 1;
break;
}
WiFiConfig wifi;
config->clearWifi(wifi);
strcpy(wifi.ssid, server.arg(F("wifiSsid")).c_str());
strcpy(wifi.psk, server.arg(F("wifiPassword")).c_str());
@ -1257,7 +1266,9 @@ void AmsWebServer::handleSave() {
if(server.hasArg(F("h")) && !server.arg(F("h")).isEmpty()) {
strcpy(wifi.hostname, server.arg(F("h")).c_str());
}
wifi.mdns = server.arg(F("m")) == F("true");
wifi.power = server.arg(F("w")).toFloat() * 10;
wifi.sleep = server.arg(F("z")).toInt();
config->setWiFiConfig(wifi);
}

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">