New meter config

This commit is contained in:
Gunnar Skjold
2021-11-06 19:30:58 +01:00
parent 8e9da8f255
commit 6d26102b8e
27 changed files with 156 additions and 2370 deletions

View File

@@ -182,7 +182,12 @@ bool AmsConfiguration::getMeterConfig(MeterConfig& config) {
bool AmsConfiguration::setMeterConfig(MeterConfig& config) {
MeterConfig existing;
if(getMeterConfig(existing)) {
meterChanged |= config.type != existing.type;
meterChanged |= config.baud != existing.baud;
meterChanged |= config.parity != existing.parity;
meterChanged |= config.invert != existing.invert;
meterChanged |= config.distributionSystem != existing.distributionSystem;
meterChanged |= config.mainFuse != existing.mainFuse;
meterChanged |= config.productionCapacity != existing.productionCapacity;
meterChanged |= strcmp((char*) config.encryptionKey, (char*) existing.encryptionKey);
meterChanged |= strcmp((char*) config.authenticationKey, (char*) existing.authenticationKey);
} else {
@@ -196,13 +201,14 @@ bool AmsConfiguration::setMeterConfig(MeterConfig& config) {
}
void AmsConfiguration::clearMeter(MeterConfig& config) {
config.type = 0;
config.baud = 2400;
config.parity = 11; // 8E1
config.invert = false;
config.distributionSystem = 0;
config.mainFuse = 0;
config.productionCapacity = 0;
memset(config.encryptionKey, 0, 16);
memset(config.authenticationKey, 0, 16);
config.substituteMissing = false;
}
bool AmsConfiguration::isMeterChanged() {
@@ -521,16 +527,6 @@ bool AmsConfiguration::hasConfig() {
EEPROM.end();
}
switch(configVersion) {
case 82:
configVersion = -1; // Prevent loop
if(loadConfig82(EEPROM_CONFIG_ADDRESS+1)) {
configVersion = EEPROM_CHECK_SUM;
return true;
} else {
configVersion = 0;
return false;
}
break;
case 83:
configVersion = -1; // Prevent loop
if(loadConfig83(EEPROM_CONFIG_ADDRESS+1)) {
@@ -544,20 +540,26 @@ bool AmsConfiguration::hasConfig() {
case 86:
configVersion = -1; // Prevent loop
if(relocateConfig86()) {
configVersion = EEPROM_CHECK_SUM;
return true;
configVersion = 87;
} else {
configVersion = 0;
return false;
}
case 87:
configVersion = -1; // Prevent loop
if(relocateConfig87()) {
configVersion = 88;
} else {
configVersion = 0;
return false;
}
break;
break;
case EEPROM_CHECK_SUM:
return true;
default:
configVersion = 0;
return false;
}
return configVersion == EEPROM_CHECK_SUM;
}
int AmsConfiguration::getConfigVersion() {
@@ -602,107 +604,6 @@ void AmsConfiguration::saveTempSensors() {
}
}
bool AmsConfiguration::loadConfig82(int address) {
ConfigObject82 c;
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(address, c);
EntsoeConfig entsoe;
clearEntsoe(entsoe);
EEPROM.put(CONFIG_ENTSOE_START, entsoe);
NtpConfig ntp;
clearNtp(ntp);
EEPROM.put(CONFIG_NTP_START, ntp);
DomoticzConfig domo {
c.domoELIDX,
c.domoVL1IDX,
c.domoVL2IDX,
c.domoVL3IDX,
c.domoCL1IDX
};
EEPROM.put(CONFIG_DOMOTICZ_START, domo);
GpioConfig gpio {
c.hanPin,
c.apPin,
c.ledPin,
c.ledInverted,
c.ledPinRed,
c.ledPinGreen,
c.ledPinBlue,
c.ledRgbInverted,
c.tempSensorPin,
0xFF,
c.vccPin,
0,
c.vccMultiplier,
c.vccBootLimit
};
EEPROM.put(CONFIG_GPIO_START, gpio);
DebugConfig debug {
c.debugTelnet,
c.debugSerial,
c.debugLevel
};
EEPROM.put(CONFIG_DEBUG_START, debug);
MeterConfig meter {
c.meterType,
c.distributionSystem,
c.mainFuse,
c.productionCapacity,
{0},
{0},
c.substituteMissing
};
EEPROM.put(CONFIG_METER_START, meter);
WebConfig web {
c.authSecurity
};
strcpy(web.username, c.authUser);
strcpy(web.password, c.authPassword);
EEPROM.put(CONFIG_WEB_START, web);
MqttConfig mqtt;
strcpy(mqtt.host, c.mqttHost);
mqtt.port = c.mqttPort;
strcpy(mqtt.clientId, c.mqttClientId);
strcpy(mqtt.publishTopic, c.mqttPublishTopic);
strcpy(mqtt.subscribeTopic, c.mqttSubscribeTopic);
strcpy(mqtt.username, c.mqttUser);
strcpy(mqtt.password, c.mqttPassword);
mqtt.payloadFormat = c.mqttPayloadFormat;
mqtt.ssl = c.mqttSsl;
EEPROM.put(CONFIG_MQTT_START, mqtt);
WiFiConfig wifi;
strcpy(wifi.ssid, c.wifiSsid);
strcpy(wifi.psk, c.wifiPassword);
strcpy(wifi.ip, c.wifiIp);
strcpy(wifi.gateway, c.wifiGw);
strcpy(wifi.subnet, c.wifiSubnet);
strcpy(wifi.dns1, c.wifiDns1);
strcpy(wifi.dns2, c.wifiDns2);
strcpy(wifi.hostname, c.wifiHostname);
wifi.mdns = true;
EEPROM.put(CONFIG_WIFI_START, wifi);
SystemConfig sys {
c.boardType
};
EEPROM.put(CONFIG_SYSTEM_START, sys);
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);
bool ret = EEPROM.commit();
EEPROM.end();
return ret;
}
bool AmsConfiguration::loadConfig83(int address) {
ConfigObject83 c;
EEPROM.begin(EEPROM_SIZE);
@@ -755,13 +656,14 @@ bool AmsConfiguration::loadConfig83(int address) {
EEPROM.put(CONFIG_DEBUG_START, debug);
MeterConfig meter {
c.meterType,
2400,
c.meterType == 3 || c.meterType == 4 ? 3 : 11,
false,
c.distributionSystem,
c.mainFuse,
c.productionCapacity,
{0},
{0},
c.substituteMissing
{0}
};
memcpy(meter.encryptionKey, c.meterEncryptionKey, 16);
memcpy(meter.authenticationKey, c.meterAuthenticationKey, 16);
@@ -825,6 +727,25 @@ bool AmsConfiguration::relocateConfig86() {
mqtt.payloadFormat = mqtt86.payloadFormat;
mqtt.ssl = mqtt86.ssl;
EEPROM.put(CONFIG_MQTT_START, mqtt);
EEPROM.put(EEPROM_CONFIG_ADDRESS, 87);
bool ret = EEPROM.commit();
EEPROM.end();
return ret;
}
bool AmsConfiguration::relocateConfig87() {
MeterConfig87 meter87;
MeterConfig meter;
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_METER_START_87, meter87);
meter.baud = 2400;
meter.parity = meter87.type == 3 || meter87.type == 4 ? 3 : 11;
meter.invert = false;
meter.distributionSystem = meter87.distributionSystem;
meter.mainFuse = meter87.mainFuse;
meter.productionCapacity = meter87.productionCapacity;
EEPROM.put(CONFIG_METER_START, meter);
EEPROM.put(EEPROM_CONFIG_ADDRESS, 88);
bool ret = EEPROM.commit();
EEPROM.end();
return ret;
@@ -986,11 +907,12 @@ void AmsConfiguration::print(Print* debugger)
MeterConfig meter;
if(getMeterConfig(meter)) {
debugger->println("--Meter configuration--");
debugger->printf("Type: %i\r\n", meter.type);
debugger->printf("Baud: %i\r\n", meter.baud);
debugger->printf("Parity: %i\r\n", meter.parity);
debugger->printf("Invert serial: %s\r\n", meter.invert ? "Yes" : "No");
debugger->printf("Distribution system: %i\r\n", meter.distributionSystem);
debugger->printf("Main fuse: %i\r\n", meter.mainFuse);
debugger->printf("Production Capacity: %i\r\n", meter.productionCapacity);
debugger->printf("Substitute missing: %s\r\n", meter.substituteMissing ? "Yes" : "No");
debugger->println("");
delay(10);
Serial.flush();

View File

@@ -4,14 +4,14 @@
#include "Arduino.h"
#define EEPROM_SIZE 1024 * 3
#define EEPROM_CHECK_SUM 87 // Used to check if config is stored. Change if structure changes
#define EEPROM_CHECK_SUM 88 // Used to check if config is stored. Change if structure changes
#define EEPROM_CONFIG_ADDRESS 0
#define EEPROM_TEMP_CONFIG_ADDRESS 2048
#define CONFIG_SYSTEM_START 8
#define CONFIG_WIFI_START 16
#define CONFIG_METER_START 224
#define CONFIG_WEB_START 648
#define CONFIG_METER_START 784
#define CONFIG_DEBUG_START 824
#define CONFIG_GPIO_START 832
#define CONFIG_DOMOTICZ_START 856
@@ -20,6 +20,7 @@
#define CONFIG_MQTT_START 1004
#define CONFIG_MQTT_START_86 224
#define CONFIG_METER_START_87 784
struct SystemConfig {
@@ -69,6 +70,17 @@ 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];
}; // 41
struct MeterConfig87 {
uint8_t type;
uint8_t distributionSystem;
uint8_t mainFuse;
@@ -190,60 +202,6 @@ struct ConfigObject83 {
uint8_t tempAnalogSensorPin;
};
struct ConfigObject82 {
uint8_t boardType;
char wifiSsid[32];
char wifiPassword[64];
char wifiIp[15];
char wifiGw[15];
char wifiSubnet[15];
char wifiDns1[15];
char wifiDns2[15];
char wifiHostname[32];
char mqttHost[128];
uint16_t mqttPort;
char mqttClientId[32];
char mqttPublishTopic[64];
char mqttSubscribeTopic[64];
char mqttUser[64];
char mqttPassword[64];
uint8_t mqttPayloadFormat;
bool mqttSsl;
uint8_t authSecurity;
char authUser[64];
char authPassword[64];
uint8_t meterType;
uint8_t distributionSystem;
uint8_t mainFuse;
uint8_t productionCapacity;
bool substituteMissing;
bool sendUnknown;
bool debugTelnet;
bool debugSerial;
uint8_t debugLevel;
uint8_t hanPin;
uint8_t apPin;
uint8_t ledPin;
bool ledInverted;
uint8_t ledPinRed;
uint8_t ledPinGreen;
uint8_t ledPinBlue;
bool ledRgbInverted;
uint8_t tempSensorPin;
uint8_t vccPin;
uint16_t vccMultiplier;
uint8_t vccBootLimit;
uint16_t domoELIDX;
uint16_t domoVL1IDX;
uint16_t domoVL2IDX;
uint16_t domoVL3IDX;
uint16_t domoCL1IDX;
};
struct TempSensorConfig {
uint8_t address[8];
char name[16];
@@ -334,9 +292,9 @@ private:
uint8_t tempSensorCount = 0;
TempSensorConfig** tempSensors;
bool loadConfig82(int address);
bool loadConfig83(int address);
bool relocateConfig86();
bool relocateConfig87();
int readString(int pAddress, char* pString[]);
int readInt(int pAddress, int *pValue);

View File

@@ -109,25 +109,28 @@ AmsData::AmsData(const char* d, bool substituteMissing) {
l3current = s32;
}
int vdiv = 1;
int voltage = l1voltage == 0 ? l2voltage == 0 ? l3voltage == 0 ? 0 : l3voltage : l2voltage : l1voltage;
while(voltage > 1000) {
vdiv *= 10;
voltage /= 10;
}
if(listType == 2) {
int vdiv = 1;
int voltage = l1voltage == 0 ? l2voltage == 0 ? l3voltage == 0 ? 0 : l3voltage : l2voltage : l1voltage;
while(voltage > 1000) {
vdiv *= 10;
voltage /= 10;
}
l1voltage = l1voltage != 0 ? l1voltage / vdiv : 0;
l2voltage = l2voltage != 0 ? l2voltage / vdiv : 0;
l3voltage = l3voltage != 0 ? l3voltage / vdiv : 0;
l1voltage = l1voltage != 0 ? l1voltage / vdiv : 0;
l2voltage = l2voltage != 0 ? l2voltage / vdiv : 0;
l3voltage = l3voltage != 0 ? l3voltage / vdiv : 0;
if(meterType == AmsTypeAidon) {
l1current = l1current != 0 ? l1current / 10.0 : 0;
l2current = l2current != 0 ? l2current / 10.0 : 0;
l3current = l3current != 0 ? l3current / 10.0 : 0;
} else if(meterType == AmsTypeKamstrup) {
l1current = l1current != 0 ? l1current / 100.0 : 0;
l2current = l2current != 0 ? l2current / 100.0 : 0;
l3current = l3current != 0 ? l3current / 100.0 : 0;
int adiv = 1;
int watt = (l1voltage * l1current) + (l2voltage * l2current) + (l3voltage * l3current);
while(watt / activeImportPower > 2) {
adiv *= 10;
watt /= 10;
}
l1current = l1current != 0 ? l1current / adiv : 0;
l2current = l2current != 0 ? l2current / adiv : 0;
l3current = l3current != 0 ? l3current / adiv : 0;
}
u32 = AMS_getUnsignedNumber(AMS_OBIS_ACTIVE_IMPORT_COUNT, ((char *) (d)));
@@ -170,8 +173,8 @@ AmsData::AmsData(const char* d, bool substituteMissing) {
twoPhase = (l1voltage > 0 && l2voltage > 0) || (l2voltage > 0 && l3voltage > 0) || (l3voltage > 0 && l1voltage > 0);
if(threePhase) {
if(substituteMissing) {
l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage;
if(substituteMissing && l2current == 0) {
l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage;
}
}

View File

@@ -3,7 +3,6 @@
#include "Arduino.h"
#include <Timezone.h>
#include "HanReader.h"
#define METER_TYPE_KAIFA 1
#define METER_TYPE_AIDON 2
@@ -14,7 +13,6 @@ class AmsData {
public:
AmsData();
AmsData(const char* d, bool substituteMissing);
AmsData(uint8_t meterType, bool substituteMissing, HanReader& hanReader);
void apply(AmsData& other);
@@ -61,11 +59,6 @@ private:
float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0;
float activeImportCounter = 0, reactiveImportCounter = 0, activeExportCounter = 0, reactiveExportCounter = 0;
bool threePhase = false, twoPhase = false, counterEstimated = false;
void extractFromKaifa(HanReader& hanReader, uint8_t listSize);
void extractFromAidon(HanReader& hanReader, uint8_t listSize);
void extractFromKamstrup(HanReader& hanReader, uint8_t listSize);
void extractFromOmnipower(HanReader& hanReader, uint8_t listSize);
};
#endif

View File

@@ -31,18 +31,12 @@ ADC_MODE(ADC_VCC);
#include "web/AmsWebServer.h"
#include "AmsConfiguration.h"
#include "HanReader.h"
#include "mqtt/AmsMqttHandler.h"
#include "mqtt/JsonMqttHandler.h"
#include "mqtt/RawMqttHandler.h"
#include "mqtt/DomoticzMqttHandler.h"
#include "Aidon.h"
#include "Kaifa.h"
#include "Kamstrup.h"
#include "Omnipower.h"
#include "Uptime.h"
#include "RemoteDebug.h"
@@ -67,8 +61,6 @@ AmsWebServer ws(&Debug, &hw);
MQTTClient mqtt(512);
AmsMqttHandler* mqttHandler = NULL;
HanReader hanReader;
Stream *hanSerial;
GpioConfig gpioConfig;
@@ -144,15 +136,16 @@ void setup() {
config.getMeterConfig(meterConfig);
if(gpioConfig.hanPin == 3) {
shared = true;
switch(meterConfig.type) {
case METER_TYPE_KAMSTRUP:
case METER_TYPE_OMNIPOWER:
Serial.begin(2400, SERIAL_8N1);
SerialConfig serialConfig;
switch(meterConfig.parity) {
case 3:
serialConfig = SERIAL_8N1;
break;
default:
Serial.begin(2400, SERIAL_8E1);
serialConfig = SERIAL_8E1;
break;
}
Serial.begin(meterConfig.baud, serialConfig);
}
if(!shared) {
@@ -449,7 +442,7 @@ void loop() {
if(config.isMeterChanged()) {
config.getMeterConfig(meterConfig);
setupHanPort(gpioConfig.hanPin, meterConfig.type);
setupHanPort(gpioConfig.hanPin, meterConfig.baud, meterConfig.parity, meterConfig.invert);
config.ackMeterChanged();
}
delay(1);
@@ -458,8 +451,8 @@ void loop() {
delay(1); // Needed for auto modem sleep
}
void setupHanPort(int pin, int newMeterType) {
debugI("Setting up HAN on pin %d for meter type %d", pin, newMeterType);
void setupHanPort(uint8_t pin, uint32_t baud, uint8_t parityOrdinal, bool invert) {
debugI("Setting up HAN on pin %d with baud %d and parity %d", pin, baud, parityOrdinal);
HardwareSerial *hwSerial = NULL;
if(pin == 3) {
@@ -482,42 +475,40 @@ void setupHanPort(int pin, int newMeterType) {
if(hwSerial != NULL) {
debugD("Hardware serial");
Serial.flush();
switch(newMeterType) {
case METER_TYPE_KAMSTRUP:
case METER_TYPE_OMNIPOWER:
hwSerial->begin(2400, SERIAL_8N1);
SerialConfig serialConfig;
switch(parityOrdinal) {
case 3:
serialConfig = SERIAL_8N1;
break;
default:
hwSerial->begin(2400, SERIAL_8E1);
serialConfig = SERIAL_8E1;
break;
}
hwSerial->begin(baud, serialConfig, SERIAL_FULL, -1, invert);
hanSerial = hwSerial;
} else {
debugD("Software serial");
Serial.flush();
SoftwareSerial *swSerial = new SoftwareSerial(pin);
switch(newMeterType) {
case METER_TYPE_KAMSTRUP:
case METER_TYPE_OMNIPOWER:
swSerial->begin(2400, SWSERIAL_8N1);
SoftwareSerialConfig serialConfig;
switch(parityOrdinal) {
case 3:
serialConfig = SWSERIAL_8N1;
break;
default:
swSerial->begin(2400, SWSERIAL_8E1);
serialConfig = SWSERIAL_8E1;
break;
}
SoftwareSerial *swSerial = new SoftwareSerial(pin, -1, invert);
swSerial->begin(baud, serialConfig);
hanSerial = swSerial;
Serial.begin(115200);
}
hanReader.setup(hanSerial, &Debug);
hanReader.setEncryptionKey(meterConfig.encryptionKey);
hanReader.setAuthenticationKey(meterConfig.authenticationKey);
// Compensate for the known Kaifa bug
hanReader.compensateFor09HeaderBug = (newMeterType == 1);
// Empty buffer before starting
while (hanSerial->available() > 0) {
hanSerial->read();
@@ -604,15 +595,16 @@ HDLCConfig* hc = NULL;
int currentMeterType = 0;
void readHanPort() {
uint8_t buf[BUF_SIZE];
if(!hanSerial->available()) return;
size_t len = hanSerial->readBytes(buf, BUF_SIZE); // TODO: read one byte at the time. This blocks up the GUI
if(len > 0) {
if(meterConfig.type == 4 && hc == NULL) {
int pos = HDLC_validate((uint8_t *) buf, len, hc);
if(pos == HDLC_ENCRYPTION_CONFIG_MISSING) {
hc = new HDLCConfig();
memcpy(hc->encryption_key, meterConfig.encryptionKey, 16);
memcpy(hc->authentication_key, meterConfig.authenticationKey, 16);
}
int pos = HDLC_validate((uint8_t *) buf, len, hc);
if(Debug.isActive(RemoteDebug::INFO)) {
if(Debug.isActive(RemoteDebug::DEBUG)) {
debugD("Frame dump:");
debugPrint(buf, 0, len);
if(hc != NULL) {
@@ -630,7 +622,7 @@ void readHanPort() {
debugI("Valid HDLC, start at %d", pos);
if(!hw.ledBlink(LED_GREEN, 1))
hw.ledBlink(LED_INTERNAL, 1);
AmsData data = AmsData(((char *) (buf)) + pos, meterConfig.substituteMissing);
AmsData data = AmsData(((char *) (buf)) + pos, true);
if(data.getListType() > 0) {
if(mqttEnabled && mqttHandler != NULL) {
if(mqttHandler->publish(&data, &meterState)) {
@@ -682,95 +674,6 @@ void debugPrint(byte *buffer, int start, int length) {
Debug.println("");
}
void oldReadHanPort() {
if (hanReader.read()) {
lastSuccessfulRead = millis();
delay(1);
if(meterConfig.type > 0) {
if(!hw.ledBlink(LED_GREEN, 1))
hw.ledBlink(LED_INTERNAL, 1);
AmsData data(meterConfig.type, meterConfig.substituteMissing, hanReader);
if(data.getListType() > 0) {
if(mqttEnabled && mqttHandler != NULL) {
if(mqttHandler->publish(&data, &meterState)) {
if(data.getListType() == 3 && eapi != NULL) {
mqttHandler->publishPrices(eapi);
}
if(data.getListType() >= 2) {
mqttHandler->publishSystem(&hw);
}
time_t now = time(nullptr);
if(now < EPOCH_2021_01_01 || data.getListType() == 3) {
if(data.getMeterTimestamp() > EPOCH_2021_01_01 || !ntpEnabled) {
debugI("Using timestamp from meter");
now = data.getMeterTimestamp();
} else if(data.getPackageTimestamp() > EPOCH_2021_01_01) {
debugI("Using timestamp from meter (DLMS)");
now = data.getPackageTimestamp();
}
if(now > EPOCH_2021_01_01) {
timeval tv { now, 0};
settimeofday(&tv, nullptr);
}
}
}
mqtt.loop();
delay(10);
}
meterState.apply(data);
}
} else {
// Auto detect meter if not set
for(int i = 1; i <= 3; i++) {
String list;
switch(i) {
case 1:
list = hanReader.getString((int) Kaifa_List1Phase::ListVersionIdentifier);
break;
case 2:
list = hanReader.getString((int) Aidon_List1Phase::ListVersionIdentifier);
break;
case 3:
list = hanReader.getString((int) Kamstrup_List1Phase::ListVersionIdentifier);
break;
}
if(!list.isEmpty()) {
list.toLowerCase();
if(list.startsWith("kfm")) {
meterConfig.type = 1;
config.setMeterConfig(meterConfig);
if(Debug.isActive(RemoteDebug::INFO)) debugI("Detected Kaifa meter");
break;
} else if(list.startsWith("aidon")) {
meterConfig.type = 2;
config.setMeterConfig(meterConfig);
if(Debug.isActive(RemoteDebug::INFO)) debugI("Detected Aidon meter");
break;
} else if(list.startsWith("kamstrup")) {
meterConfig.type = 3;
config.setMeterConfig(meterConfig);
if(Debug.isActive(RemoteDebug::INFO)) debugI("Detected Kamstrup meter");
break;
}
}
}
hanReader.compensateFor09HeaderBug = (meterConfig.type == 1);
}
}
// Switch parity if meter is still not detected
if(meterConfig.type == 0 && millis() - lastSuccessfulRead > 10000) {
lastSuccessfulRead = millis();
debugD("No data for current setting, switching parity");
Serial.flush();
if(++currentMeterType == 4) currentMeterType = 1;
setupHanPort(gpioConfig.hanPin, currentMeterType);
}
delay(1);
}
unsigned long wifiTimeout = WIFI_CONNECTION_TIMEOUT;
unsigned long lastWifiRetry = -WIFI_CONNECTION_TIMEOUT;
void WiFi_connect() {

View File

@@ -90,7 +90,7 @@ int HDLC_validate(const uint8_t* d, int len, HDLCConfig* config) {
// Encrypted APDU
// http://www.weigu.lu/tutorials/sensors2bus/04_encryption/index.html
if(config == NULL)
return -90;
return HDLC_ENCRYPTION_CONFIG_MISSING;
memcpy(config->system_title, d + headersize + 2, 8);
memcpy(config->initialization_vector, config->system_title, 8);

View File

@@ -5,6 +5,7 @@
#include <stdint.h>
#define HDLC_FLAG 0x7E
#define HDLC_ENCRYPTION_CONFIG_MISSING -90
struct HDLCConfig {
uint8_t encryption_key[32];

View File

@@ -391,10 +391,13 @@ void AmsWebServer::configMeterHtml() {
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
html.replace("{m}", String(meterConfig->mainFuse));
for(int i = 0; i<5; i++) {
html.replace("{m" + String(i) + "}", meterConfig->type == i ? "selected" : "");
}
html.replace("{b}", String(meterConfig->baud));
html.replace("{b2400}", meterConfig->baud == 2400 ? "selected" : "");
html.replace("{b115200}", meterConfig->baud == 115200 ? "selected" : "");
html.replace("{c}", String(meterConfig->baud));
html.replace("{c3}", meterConfig->parity == 3 ? "selected" : "");
html.replace("{c11}", meterConfig->parity == 11 ? "selected" : "");
html.replace("{i}", meterConfig->invert ? "checked" : "");
html.replace("{d}", String(meterConfig->distributionSystem));
for(int i = 0; i<3; i++) {
html.replace("{d" + String(i) + "}", meterConfig->distributionSystem == i ? "selected" : "");
@@ -405,7 +408,7 @@ void AmsWebServer::configMeterHtml() {
}
html.replace("{p}", String(meterConfig->productionCapacity));
if(meterConfig->type == METER_TYPE_OMNIPOWER) {
if(meterConfig->encryptionKey[0] != 0x00) {
String encryptionKeyHex = "0x";
encryptionKeyHex += toHex(meterConfig->encryptionKey, 16);
html.replace("{e}", encryptionKeyHex);
@@ -418,8 +421,6 @@ void AmsWebServer::configMeterHtml() {
html.replace("{a}", "");
}
html.replace("{s}", meterConfig->substituteMissing ? "checked" : "");
server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN);
server.send_P(200, "text/html", HEAD_HTML);
server.sendContent(html);
@@ -665,7 +666,7 @@ void AmsWebServer::dataJson() {
uint8_t hanStatus;
if(meterConfig->type == 0) {
if(meterConfig->baud == 0) {
hanStatus = 0;
} else if(now - meterState->getLastUpdateMillis() < 15000) {
hanStatus = 1;
@@ -910,7 +911,9 @@ void AmsWebServer::handleSave() {
if(server.hasArg("mc") && server.arg("mc") == "true") {
printD("Received meter config");
meterConfig->type = server.arg("m").toInt();
meterConfig->baud = server.arg("b").toInt();
meterConfig->parity = server.arg("c").toInt();
meterConfig->invert = server.hasArg("i") && server.arg("i") == "true";
meterConfig->distributionSystem = server.arg("d").toInt();
meterConfig->mainFuse = server.arg("f").toInt();
meterConfig->productionCapacity = server.arg("p").toInt();
@@ -926,7 +929,6 @@ void AmsWebServer::handleSave() {
authenticationKeyHex.replace("0x", "");
fromHex(meterConfig->authenticationKey, authenticationKeyHex, 16);
}
meterConfig->substituteMissing = server.hasArg("s") && server.arg("s") == "true";
config->setMeterConfig(*meterConfig);
}