Support encrypted meters and added vcc offset

This commit is contained in:
Gunnar Skjold
2020-07-31 10:15:11 +02:00
parent 47ddf57547
commit 620e355a27
36 changed files with 12041 additions and 137 deletions

View File

@@ -242,6 +242,7 @@ uint8_t AmsConfiguration::getMeterType() {
}
void AmsConfiguration::setMeterType(uint8_t meterType) {
meterChanged |= config.meterType != meterType;
config.meterType = meterType;
}
@@ -269,6 +270,24 @@ void AmsConfiguration::setProductionCapacity(uint8_t productionCapacity) {
config.productionCapacity = productionCapacity;
}
uint8_t* AmsConfiguration::getMeterEncryptionKey() {
return config.meterEncryptionKey;
}
void AmsConfiguration::setMeterEncryptionKey(uint8_t* meterEncryptionKey) {
meterChanged |= strcmp((char*) config.meterEncryptionKey, (char*) meterEncryptionKey);
memcpy(config.meterEncryptionKey, meterEncryptionKey, 16);
}
uint8_t* AmsConfiguration::getMeterAuthenticationKey() {
return config.meterAuthenticationKey;
}
void AmsConfiguration::setMeterAuthenticationKey(uint8_t* meterAuthenticationKey) {
meterChanged |= strcmp((char*) config.meterAuthenticationKey, (char*) meterAuthenticationKey);
memcpy(config.meterAuthenticationKey, meterAuthenticationKey, 16);
}
bool AmsConfiguration::isSubstituteMissing() {
return config.substituteMissing;
}
@@ -294,6 +313,14 @@ void AmsConfiguration::clearMeter() {
setSendUnknown(false);
}
bool AmsConfiguration::isMeterChanged() {
return meterChanged;
}
void AmsConfiguration::ackMeterChanged() {
meterChanged = false;
}
bool AmsConfiguration::isDebugTelnet() {
return config.debugTelnet;
@@ -388,6 +415,7 @@ uint8_t AmsConfiguration::getHanPin() {
void AmsConfiguration::setHanPin(uint8_t hanPin) {
if(!pinUsed(hanPin)) {
meterChanged |= config.hanPin != hanPin;
config.hanPin = hanPin;
}
}
@@ -482,8 +510,16 @@ void AmsConfiguration::setVccPin(uint8_t vccPin) {
}
}
double AmsConfiguration::getVccOffset() {
return config.vccOffset > 0 ? config.vccOffset / 100.0 : 0;
}
void AmsConfiguration::setVccOffset(double vccOffset) {
config.vccOffset = vccOffset == 0 ? 0 : max(-350, min((int)(vccOffset * 100.0), 350));
}
double AmsConfiguration::getVccMultiplier() {
return config.vccMultiplier / 1000.0;
return config.vccMultiplier > 0 ? config.vccMultiplier / 1000.0 : 0;
}
void AmsConfiguration::setVccMultiplier(double vccMultiplier) {
@@ -491,7 +527,7 @@ void AmsConfiguration::setVccMultiplier(double vccMultiplier) {
}
double AmsConfiguration::getVccBootLimit() {
return config.vccBootLimit / 10.0;
return config.vccBootLimit > 0 ? config.vccBootLimit / 10.0 : 0;
}
void AmsConfiguration::setVccBootLimit(double vccBootLimit) {
@@ -532,12 +568,9 @@ bool AmsConfiguration::hasConfig() {
EEPROM.end();
}
switch(configVersion) {
case 71:
case 72:
case 75:
case 80:
case 81:
case 82:
case 83:
return true;
default:
configVersion = 0;
@@ -557,13 +590,13 @@ bool AmsConfiguration::load() {
int cs = EEPROM.read(address);
address++;
switch(cs) {
case 80: // v1.1
success = loadConfig80(address);
break;
case 81: // v1.2
success = loadConfig81(address);
break;
case 82: // v1.3
success = loadConfig82(address);
break;
case 83: // v1.4
EEPROM.get(address, config);
success = true;
break;
@@ -572,85 +605,65 @@ bool AmsConfiguration::load() {
if(config.apPin >= 0)
pinMode(config.apPin, INPUT_PULLUP);
meterChanged = true;
return success;
}
bool AmsConfiguration::loadConfig80(int address) {
char* temp;
bool AmsConfiguration::loadConfig82(int address) {
ConfigObject82 config82;
EEPROM.get(address, config82);
config.boardType = config82.boardType;
strcpy(config.wifiSsid, config82.wifiSsid);
strcpy(config.wifiPassword, config82.wifiPassword);
strcpy(config.wifiIp, config82.wifiIp);
strcpy(config.wifiGw, config82.wifiGw);
strcpy(config.wifiSubnet, config82.wifiSubnet);
strcpy(config.wifiDns1, config82.wifiDns1);
strcpy(config.wifiDns2, config82.wifiDns2);
strcpy(config.wifiHostname, config82.wifiHostname);
strcpy(config.mqttHost, config82.mqttHost);
config.mqttPort = config82.mqttPort;
strcpy(config.mqttClientId, config82.mqttClientId);
strcpy(config.mqttPublishTopic, config82.mqttPublishTopic);
strcpy(config.mqttSubscribeTopic, config82.mqttSubscribeTopic);
strcpy(config.mqttUser, config82.mqttUser);
strcpy(config.mqttPassword, config82.mqttPassword);
config.mqttPayloadFormat = config82.mqttPayloadFormat;
config.mqttSsl = config82.mqttSsl;
config.authSecurity = config82.authSecurity;
strcpy(config.authUser, config82.authUser);
strcpy(config.authPassword, config82.authPassword);
config.meterType = config82.meterType;
config.distributionSystem = config82.distributionSystem;
config.mainFuse = config82.mainFuse;
config.productionCapacity = config82.productionCapacity;
config.substituteMissing = config82.substituteMissing;
config.sendUnknown = config82.sendUnknown;
address += readString(address, &temp);
setWifiSsid(temp);
address += readString(address, &temp);
setWifiPassword(temp);
address += readString(address, &temp);
setWifiIp(temp);
address += readString(address, &temp);
setWifiGw(temp);
address += readString(address, &temp);
setWifiSubnet(temp);
config.debugTelnet = config82.debugTelnet;
config.debugSerial = config82.debugSerial;
config.debugLevel = config82.debugLevel;
bool mqtt = false;
address += readBool(address, &mqtt);
if(mqtt) {
address += readString(address, &temp);
setMqttHost(temp);
int port;
address += readInt(address, &port);
setMqttPort(port);
address += readString(address, &temp);
setMqttClientId(temp);
address += readString(address, &temp);
setMqttPublishTopic(temp);
address += readString(address, &temp);
setMqttSubscribeTopic(temp);
config.hanPin = config82.hanPin;
config.apPin = config82.apPin;
config.ledPin = config82.ledPin;
config.ledInverted = config82.ledInverted;
config.ledPinRed = config82.ledPinRed;
config.ledPinGreen = config82.ledPinGreen;
config.ledPinBlue = config82.ledPinBlue;
config.ledRgbInverted = config82.ledRgbInverted;
config.tempSensorPin = config82.tempSensorPin;
config.vccPin = config82.vccPin;
config.vccMultiplier = config82.vccMultiplier;
config.vccBootLimit = config82.vccBootLimit;
bool secure = false;
address += readBool(address, &secure);
if (secure)
{
address += readString(address, &temp);
setMqttUser(temp);
address += readString(address, &temp);
setMqttPassword(temp);
} else {
setMqttUser("");
setMqttPassword("");
}
} else {
clearMqtt();
}
setMqttPayloadFormat(0);
byte b;
address += readByte(address, &b);
setAuthSecurity(b);
if (b > 0) {
address += readString(address, &temp);
setAuthUser(temp);
address += readString(address, &temp);
setAuthPassword(temp);
} else {
clearAuth();
}
int i;
address += readInt(address, &i);
setMeterType(i);
address += readInt(address, &i);
setDistributionSystem(i);
address += readInt(address, &i);
setMainFuse(i);
address += readInt(address, &i);
setProductionCapacity(i);
ackWifiChange();
setDebugLevel(3); // 3=Info
setDebugTelnet(false);
setDebugSerial(false);
return true;
config.domoELIDX = config82.domoELIDX;
config.domoVL1IDX = config82.domoVL1IDX;
config.domoVL2IDX = config82.domoVL2IDX;
config.domoVL3IDX = config82.domoVL3IDX;
config.domoCL1IDX = config82.domoCL1IDX;
}
bool AmsConfiguration::loadConfig81(int address) {
@@ -852,13 +865,13 @@ void AmsConfiguration::print(Print* debugger)
debugger->printf("Vcc multiplier: %f\r\n", this->getVccMultiplier());
debugger->printf("Vcc boot limit: %f\r\n", this->getVccBootLimit());
//if(this->getDomoELIDX() > 0) {
debugger->printf("Domoticz ELIDX: %i\r\n", this->getDomoELIDX());
debugger->printf("Domoticz VL1IDX: %i\r\n", this->getDomoVL1IDX());
debugger->printf("Domoticz VL2IDX: %i\r\n", this->getDomoVL2IDX());
debugger->printf("Domoticz VL3IDX: %i\r\n", this->getDomoVL3IDX());
debugger->printf("Domoticz CL1IDX: %i\r\n", this->getDomoCL1IDX());
//}
if(this->getDomoELIDX() > 0) {
debugger->printf("Domoticz ELIDX: %i\r\n", this->getDomoELIDX());
debugger->printf("Domoticz VL1IDX: %i\r\n", this->getDomoVL1IDX());
debugger->printf("Domoticz VL2IDX: %i\r\n", this->getDomoVL2IDX());
debugger->printf("Domoticz VL3IDX: %i\r\n", this->getDomoVL3IDX());
debugger->printf("Domoticz CL1IDX: %i\r\n", this->getDomoCL1IDX());
}
debugger->println("-----------------------------------------------");
}

View File

@@ -9,6 +9,63 @@ struct ConfigObject {
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;
uint8_t meterEncryptionKey[16];
uint8_t meterAuthenticationKey[16];
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;
int16_t vccOffset;
uint16_t vccMultiplier;
uint8_t vccBootLimit;
uint16_t domoELIDX;
uint16_t domoVL1IDX;
uint16_t domoVL2IDX;
uint16_t domoVL3IDX;
uint16_t domoCL1IDX;
};
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];
@@ -129,12 +186,19 @@ public:
void setMainFuse(uint8_t mainFuse);
uint8_t getProductionCapacity();
void setProductionCapacity(uint8_t productionCapacity);
uint8_t* getMeterEncryptionKey();
void setMeterEncryptionKey(uint8_t* meterEncryptionKey);
uint8_t* getMeterAuthenticationKey();
void setMeterAuthenticationKey(uint8_t* meterAuthenticationKey);
bool isSubstituteMissing();
void setSubstituteMissing(bool substituteMissing);
bool isSendUnknown();
void setSendUnknown(bool sendUnknown);
void clearMeter();
bool isMeterChanged();
void ackMeterChanged();
bool isDebugTelnet();
void setDebugTelnet(bool debugTelnet);
bool isDebugSerial();
@@ -166,6 +230,8 @@ public:
void setTempSensorPin(uint8_t tempSensorPin);
uint8_t getVccPin();
void setVccPin(uint8_t vccPin);
double getVccOffset();
void setVccOffset(double vccOffset);
double getVccMultiplier();
void setVccMultiplier(double vccMultiplier);
double getVccBootLimit();
@@ -220,6 +286,8 @@ private:
0, // Distribution system
0, // Main fuse
0, // Production capacity
{}, // Encryption key
{}, // Authentication key
false, // Substitute
false, // Send unknown
false, // Debug telnet
@@ -235,6 +303,7 @@ private:
true, // Inverted
0xFF, // Temp sensor
0xFF, // Vcc
0, // Offset
100, // Multiplier
0, // Boot limit
//Domoticz
@@ -243,16 +312,16 @@ private:
0, // VL2IDX
0, // VL3IDX
0 // CL1IDX
// 786 bytes
// 822 bytes
};
bool wifiChanged, mqttChanged, domoChanged;
bool wifiChanged, mqttChanged, meterChanged = true, domoChanged;
const int EEPROM_SIZE = 790; // Config size + 4 bytes for config version
const int EEPROM_CHECK_SUM = 82; // Used to check if config is stored. Change if structure changes
const int EEPROM_SIZE = 1024; // Config size + 4 bytes for config version
const int EEPROM_CHECK_SUM = 83; // Used to check if config is stored. Change if structure changes
const int EEPROM_CONFIG_ADDRESS = 0;
bool loadConfig80(int address);
bool loadConfig81(int address);
bool loadConfig82(int address);
int readString(int pAddress, char* pString[]);
int readInt(int pAddress, int *pValue);

View File

@@ -2,6 +2,7 @@
#include "Kaifa.h"
#include "Aidon.h"
#include "Kamstrup.h"
#include "Omnipower.h"
AmsData::AmsData() {}
@@ -20,7 +21,9 @@ AmsData::AmsData(int meterType, bool substituteMissing, HanReader& hanReader) {
case METER_TYPE_KAMSTRUP:
extractFromKamstrup(hanReader, listSize, substituteMissing);
break;
case METER_TYPE_OMNIPOWER:
extractFromOmnipower(hanReader, listSize);
break;
}
}
@@ -258,6 +261,31 @@ void AmsData::extractFromKamstrup(HanReader& hanReader, int listSize, bool subst
}
}
void AmsData::extractFromOmnipower(HanReader& hanReader, int listSize) {
switch(listSize) {
case (int)Omnipower::DLMS:
meterTimestamp = hanReader.getTime( (int)Omnipower_DLMS::MeterClock);
activeImportCounter = ((double) hanReader.getInt((int)Omnipower_DLMS::CumulativeActiveImportEnergy)) / 100;
activeExportCounter = ((double) hanReader.getInt((int)Omnipower_DLMS::CumulativeActiveExportEnergy)) / 100;
reactiveImportCounter = ((double) hanReader.getInt((int)Omnipower_DLMS::CumulativeReactiveImportEnergy)) / 100;
reactiveExportCounter = ((double) hanReader.getInt((int)Omnipower_DLMS::CumulativeReactiveExportEnergy)) / 100;
listId = hanReader.getString( (int)Omnipower_DLMS::ListVersionIdentifier);
activeImportPower = hanReader.getInt( (int)Omnipower_DLMS::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (int)Omnipower_DLMS::ReactiveImportPower);
activeExportPower = hanReader.getInt( (int)Omnipower_DLMS::ActiveExportPower);
reactiveExportPower = hanReader.getInt( (int)Omnipower_DLMS::ReactiveExportPower);
l1current = ((double) hanReader.getInt((int)Omnipower_DLMS::CurrentL1)) / 100;
l2current = ((double) hanReader.getInt((int)Omnipower_DLMS::CurrentL2)) / 100;
l3current = ((double) hanReader.getInt((int)Omnipower_DLMS::CurrentL3)) / 100;
l1voltage = hanReader.getInt( (int)Omnipower_DLMS::VoltageL1);
l2voltage = hanReader.getInt( (int)Omnipower_DLMS::VoltageL2);
l3voltage = hanReader.getInt( (int)Omnipower_DLMS::VoltageL3);
listType = 3;
break;
}
threePhase = l3voltage != 0;
}
void AmsData::apply(AmsData& other) {
this->lastUpdateMillis = other.getLastUpdateMillis();
this->packageTimestamp = other.getPackageTimestamp();

View File

@@ -8,6 +8,7 @@
#define METER_TYPE_KAIFA 1
#define METER_TYPE_AIDON 2
#define METER_TYPE_KAMSTRUP 3
#define METER_TYPE_OMNIPOWER 4
class AmsData {
public:
@@ -62,6 +63,7 @@ private:
void extractFromKaifa(HanReader& hanReader, int listSize);
void extractFromAidon(HanReader& hanReader, int listSize, bool substituteMissing);
void extractFromKamstrup(HanReader& hanReader, int listSize, bool substituteMissing);
void extractFromOmnipower(HanReader& hanReader, int listSize);
};
#endif

View File

@@ -50,6 +50,7 @@ ADC_MODE(ADC_VCC);
#include "Aidon.h"
#include "Kaifa.h"
#include "Kamstrup.h"
#include "Omnipower.h"
#include "Uptime.h"
@@ -74,7 +75,6 @@ MQTTClient mqtt(512);
HanReader hanReader;
Stream *hanSerial;
int hanSerialPin = 0;
void setup() {
if(config.hasConfig()) {
@@ -147,10 +147,14 @@ void setup() {
hw.ledBlink(LED_BLUE, 1);
if(config.getHanPin() == 3) {
if(config.getMeterType() == 3) {
Serial.begin(2400, SERIAL_8N1);
} else {
Serial.begin(2400, SERIAL_8E1);
switch(config.getMeterType()) {
case METER_TYPE_KAMSTRUP:
case METER_TYPE_OMNIPOWER:
Serial.begin(2400, SERIAL_8N1);
break;
default:
Serial.begin(2400, SERIAL_8E1);
break;
}
} else {
Serial.begin(115200);
@@ -377,8 +381,9 @@ void loop() {
}
}
if(hanSerialPin != config.getHanPin()) {
if(config.isMeterChanged()) {
setupHanPort(config.getHanPin(), config.getMeterType());
config.ackMeterChanged();
}
if(now - lastRead > 100) {
@@ -390,8 +395,8 @@ void loop() {
delay(1); // Needed for auto modem sleep
}
void setupHanPort(int pin, int meterType) {
debugI("Setting up HAN on pin %d for meter type %d", pin, meterType);
void setupHanPort(int pin, int newMeterType) {
debugI("Setting up HAN on pin %d for meter type %d", pin, newMeterType);
HardwareSerial *hwSerial = NULL;
if(pin == 3) {
@@ -414,33 +419,41 @@ void setupHanPort(int pin, int meterType) {
if(hwSerial != NULL) {
debugD("Hardware serial");
Serial.flush();
if(meterType == 3) {
hwSerial->begin(2400, SERIAL_8N1);
} else {
hwSerial->begin(2400, SERIAL_8E1);
switch(newMeterType) {
case METER_TYPE_KAMSTRUP:
case METER_TYPE_OMNIPOWER:
hwSerial->begin(2400, SERIAL_8N1);
break;
default:
hwSerial->begin(2400, SERIAL_8E1);
break;
}
hanSerialPin = pin;
hanSerial = hwSerial;
} else {
debugD("Software serial");
Serial.flush();
SoftwareSerial *swSerial = new SoftwareSerial(pin);
if(meterType == 3) {
swSerial->begin(2400, SWSERIAL_8N1);
} else {
swSerial->begin(2400, SWSERIAL_8E1);
switch(newMeterType) {
case METER_TYPE_KAMSTRUP:
case METER_TYPE_OMNIPOWER:
swSerial->begin(2400, SWSERIAL_8N1);
break;
default:
swSerial->begin(2400, SWSERIAL_8E1);
break;
}
hanSerialPin = pin;
hanSerial = swSerial;
Serial.begin(115200);
}
hanReader.setup(hanSerial, &Debug);
hanReader.setEncryptionKey(config.getMeterEncryptionKey());
hanReader.setAuthenticationKey(config.getMeterAuthenticationKey());
// Compensate for the known Kaifa bug
hanReader.compensateFor09HeaderBug = (config.getMeterType() == 1);
hanReader.compensateFor09HeaderBug = (newMeterType == 1);
// Empty buffer before starting
while (hanSerial->available() > 0) {
@@ -770,33 +783,41 @@ void readHanPort() {
}
} else {
// Auto detect meter if not set
for(int i = 1; i <= 3; i++) {
for(int i = 1; i <= 4; i++) {
String list;
switch(i) {
case 1:
case METER_TYPE_KAIFA:
list = hanReader.getString((int) Kaifa_List1Phase::ListVersionIdentifier);
break;
case 2:
case METER_TYPE_AIDON:
list = hanReader.getString((int) Aidon_List1Phase::ListVersionIdentifier);
break;
case 3:
case METER_TYPE_KAMSTRUP:
list = hanReader.getString((int) Kamstrup_List1Phase::ListVersionIdentifier);
break;
case METER_TYPE_OMNIPOWER:
list = hanReader.getString((int) Omnipower_DLMS::ListVersionIdentifier);
break;
}
if(!list.isEmpty()) {
list.toLowerCase();
if(list.startsWith("kfm")) {
config.setMeterType(1);
config.setMeterType(METER_TYPE_KAIFA);
if(Debug.isActive(RemoteDebug::INFO)) debugI("Detected Kaifa meter");
break;
} else if(list.startsWith("aidon")) {
config.setMeterType(2);
config.setMeterType(METER_TYPE_AIDON);
if(Debug.isActive(RemoteDebug::INFO)) debugI("Detected Aidon meter");
break;
} else if(list.startsWith("kamstrup")) {
config.setMeterType(3);
if(Debug.isActive(RemoteDebug::INFO)) debugI("Detected Kamstrup meter");
break;
switch(i) {
case METER_TYPE_KAMSTRUP:
config.setMeterType(METER_TYPE_KAMSTRUP);
if(Debug.isActive(RemoteDebug::INFO)) debugI("Detected Kamstrup meter");
break;
case METER_TYPE_OMNIPOWER:
config.setMeterType(METER_TYPE_OMNIPOWER);
if(Debug.isActive(RemoteDebug::INFO)) debugI("Detected Kamstrup meter");
break;
}
}
}
}

View File

@@ -25,6 +25,10 @@ void HwTools::setVccPin(int vccPin) {
}
}
void HwTools::setVccOffset(double vccOffset) {
this->vccOffset = vccOffset;
}
void HwTools::setVccMultiplier(double vccMultiplier) {
this->vccMultiplier = vccMultiplier;
}
@@ -43,7 +47,7 @@ double HwTools::getVcc() {
#endif
}
return volts > 0.0 ? volts * vccMultiplier : 0.0;
return vccOffset + (volts > 0.0 ? volts * vccMultiplier : 0.0);
}
double HwTools::getTemperature() {

View File

@@ -22,6 +22,7 @@ class HwTools {
public:
void setTempSensorPin(int tempSensorPin);
void setVccPin(int vccPin);
void setVccOffset(double vccOffset);
void setVccMultiplier(double vccMultiplier);
double getVcc();
double getTemperature();
@@ -38,6 +39,7 @@ private:
uint8_t vccPin = -1;
uint8_t ledPin = -1, ledPinRed = -1, ledPinGreen = -1, ledPinBlue = -1;
bool ledInverted, ledRgbInverted;
double vccOffset = 0.0;
double vccMultiplier = 1.0;
bool tempSensorInit, hasTempSensor;
OneWire *oneWire;

View File

@@ -127,7 +127,7 @@ void AmsWebServer::indexHtml() {
for(int i = 0; i<255; i++) {
html.replace("${config.boardType" + String(i) + "}", config->getBoardType() == i ? "selected" : "");
}
for(int i = 0; i<4; i++) {
for(int i = 0; i<5; i++) {
html.replace("${config.meterType" + String(i) + "}", config->getMeterType() == i ? "selected" : "");
}
html.replace("${config.wifiSsid}", config->getWifiSsid());
@@ -218,7 +218,7 @@ void AmsWebServer::configMeterHtml() {
server.sendHeader("Pragma", "no-cache");
html.replace("${config.meterType}", String(config->getMainFuse()));
for(int i = 0; i<4; i++) {
for(int i = 0; i<5; i++) {
html.replace("${config.meterType" + String(i) + "}", config->getMeterType() == i ? "selected" : "");
}
html.replace("${config.distributionSystem}", String(config->getDistributionSystem()));
@@ -230,6 +230,31 @@ void AmsWebServer::configMeterHtml() {
html.replace("${config.mainFuse" + String(i) + "}", config->getMainFuse() == i ? "selected" : "");
}
html.replace("${config.productionCapacity}", String(config->getProductionCapacity()));
byte encryptionKey[16];
memcpy(encryptionKey, config->getMeterEncryptionKey(), 16);
String encryptionKeyHex = "0x";
for(int i = 0; i < sizeof(encryptionKey); i++) {
if(encryptionKey[i] < 0x10) {
encryptionKeyHex += '0';
}
encryptionKeyHex += String(encryptionKey[i], HEX);
}
encryptionKeyHex.toUpperCase();
html.replace("${config.meterEncryptionKey}", encryptionKeyHex);
byte authenticationKey[16];
memcpy(authenticationKey, config->getMeterAuthenticationKey(), 16);
String authenticationKeyHex = "0x";
for(int i = 0; i < sizeof(authenticationKey); i++) {
if(authenticationKey[i] < 0x10) {
authenticationKeyHex += '0';
}
authenticationKeyHex += String(authenticationKey[i], HEX);
}
authenticationKeyHex.toUpperCase();
html.replace("${config.meterAuthenticationKey}", authenticationKeyHex);
html.replace("${config.substituteMissing}", config->isSubstituteMissing() ? "checked" : "");
html.replace("${config.sendUnknown}", config->isSendUnknown() ? "checked" : "");
@@ -560,6 +585,7 @@ void AmsWebServer::handleSetup() {
config->setVccPin(0xFF);
config->setBoardType(server.arg("board").toInt());
config->setVccOffset(0.0);
config->setVccMultiplier(1.0);
config->setVccBootLimit(0);
switch(config->getBoardType()) {
@@ -665,6 +691,26 @@ void AmsWebServer::handleSave() {
config->setProductionCapacity(server.arg("productionCapacity").toInt());
config->setSubstituteMissing(server.hasArg("substituteMissing") && server.arg("substituteMissing") == "true");
config->setSendUnknown(server.hasArg("sendUnknown") && server.arg("sendUnknown") == "true");
String encryptionKeyHex = server.arg("meterEncryptionKey");
if(!encryptionKeyHex.isEmpty()) {
encryptionKeyHex.replace("0x", "");
uint8_t encryptionKey[16];
for(int i = 0; i < 32; i += 2) {
encryptionKey[i/2] = strtol(encryptionKeyHex.substring(i, i+2).c_str(), 0, 16);
}
config->setMeterEncryptionKey(encryptionKey);
}
String authenticationKeyHex = server.arg("meterAuthenticationKey");
if(!authenticationKeyHex.isEmpty()) {
authenticationKeyHex.replace("0x", "");
uint8_t authenticationKey[16];
for(int i = 0; i < 32; i += 2) {
authenticationKey[i/2] = strtol(authenticationKeyHex.substring(i, i+2).c_str(), 0, 16);
}
config->setMeterAuthenticationKey(authenticationKey);
}
}
if(server.hasArg("wifiConfig") && server.arg("wifiConfig") == "true") {
@@ -741,6 +787,7 @@ void AmsWebServer::handleSave() {
config->setApPin(server.hasArg("apPin") && !server.arg("apPin").isEmpty() ? server.arg("apPin").toInt() : 0xFF);
config->setTempSensorPin(server.hasArg("tempSensorPin") && !server.arg("tempSensorPin").isEmpty() ?server.arg("tempSensorPin").toInt() : 0xFF);
config->setVccPin(server.hasArg("vccPin") && !server.arg("vccPin").isEmpty() ? server.arg("vccPin").toInt() : 0xFF);
config->setVccOffset(server.hasArg("vccOffset") && !server.arg("vccOffset").isEmpty() ? server.arg("vccOffset").toDouble() : 0.0);
config->setVccMultiplier(server.hasArg("vccMultiplier") && !server.arg("vccMultiplier").isEmpty() ? server.arg("vccMultiplier").toDouble() : 1.0);
config->setVccBootLimit(server.hasArg("vccBootLimit") && !server.arg("vccBootLimit").isEmpty() ? server.arg("vccBootLimit").toDouble() : 0.0);
@@ -778,6 +825,7 @@ void AmsWebServer::handleSave() {
hw->setLedRgb(config->getLedPinRed(), config->getLedPinGreen(), config->getLedPinBlue(), config->isLedRgbInverted());
hw->setTempSensorPin(config->getTempSensorPin());
hw->setVccPin(config->getVccPin());
hw->setVccOffset(config->getVccOffset());
hw->setVccMultiplier(config->getVccMultiplier());
}
} else {
@@ -813,6 +861,7 @@ void AmsWebServer::configSystemHtml() {
html.replace("${config.tempSensorPin}", config->getTempSensorPin() == 0xFF ? "" : String(config->getTempSensorPin()));
html.replace("${config.vccPin}", config->getVccPin() == 0xFF ? "" : String(config->getVccPin()));
html.replace("${config.vccOffset}", config->getVccOffset() > 0 ? String(config->getVccOffset(), 2) : "");
html.replace("${config.vccMultiplier}", config->getVccMultiplier() > 0 ? String(config->getVccMultiplier(), 2) : "");
html.replace("${config.vccBootLimit}", config->getVccBootLimit() > 0.0 ? String(config->getVccBootLimit(), 1) : "");