Changes after testing

This commit is contained in:
Gunnar Skjold
2021-01-22 08:01:23 +01:00
parent ff84278edf
commit 54fb950513
17 changed files with 240 additions and 158 deletions

View File

@@ -473,35 +473,35 @@ void AmsConfiguration::ackEntsoeChange() {
}
void AmsConfiguration::clear() {
EEPROM.begin(EEPROM_SIZE);
MeterConfig meter;
clearMeter(meter);
setMeterConfig(meter);
EEPROM.put(CONFIG_METER_START, meter);
WiFiConfig wifi;
clearWifi(wifi);
setWiFiConfig(wifi);
EEPROM.put(CONFIG_WIFI_START, wifi);
MqttConfig mqtt;
clearMqtt(mqtt);
setMqttConfig(mqtt);
EEPROM.put(CONFIG_MQTT_START, mqtt);
WebConfig web;
clearAuth(web);
setWebConfig(web);
EEPROM.put(CONFIG_WEB_START, web);
DomoticzConfig domo;
clearDomo(domo);
setDomoticzConfig(domo);
EEPROM.put(CONFIG_DOMOTICZ_START, domo);
NtpConfig ntp;
clearNtp(ntp);
setNtpConfig(ntp);
EEPROM.put(CONFIG_NTP_START, domo);
EntsoeConfig entsoe;
clearEntsoe(entsoe);
setEntsoeConfig(entsoe);
EEPROM.put(CONFIG_ENTSOE_START, domo);
EEPROM.begin(EEPROM_SIZE);
EEPROM.put(EEPROM_CONFIG_ADDRESS, -1);
EEPROM.commit();
EEPROM.end();
@@ -547,10 +547,13 @@ int AmsConfiguration::getConfigVersion() {
}
void AmsConfiguration::loadTempSensors() {
this->tempSensors = new TempSensorConfig*[32];
EEPROM.begin(EEPROM_SIZE);
TempSensorConfig* tempSensors[32];
int address = EEPROM_TEMP_CONFIG_ADDRESS;
int c = 0;
int storedCount = EEPROM.read(address++);
Serial.print("SEnsors: ");
Serial.println(storedCount);
if(storedCount > 0 && storedCount <= 32) {
for(int i = 0; i < storedCount; i++) {
TempSensorConfig* tsc = new TempSensorConfig();
@@ -561,7 +564,12 @@ void AmsConfiguration::loadTempSensors() {
address += sizeof(*tsc);
}
}
this->tempSensors = new TempSensorConfig*[c];
for(int i = 0; i < c; i++) {
this->tempSensors[i] = tempSensors[i];
}
tempSensorCount = c;
EEPROM.end();
}
void AmsConfiguration::saveTempSensors() {
@@ -580,7 +588,14 @@ bool AmsConfiguration::loadConfig82(int address) {
ConfigObject82 c;
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(address, c);
EEPROM.end();
EntsoeConfig entsoe;
clearEntsoe(entsoe);
EEPROM.put(CONFIG_ENTSOE_START, entsoe);
NtpConfig ntp;
clearNtp(ntp);
EEPROM.put(CONFIG_NTP_START, ntp);
DomoticzConfig domo {
c.domoELIDX,
@@ -589,7 +604,7 @@ bool AmsConfiguration::loadConfig82(int address) {
c.domoVL3IDX,
c.domoCL1IDX
};
setDomoticzConfig(domo);
EEPROM.put(CONFIG_DOMOTICZ_START, domo);
GpioConfig gpio {
c.hanPin,
@@ -607,14 +622,14 @@ bool AmsConfiguration::loadConfig82(int address) {
c.vccMultiplier,
c.vccBootLimit
};
setGpioConfig(gpio);
EEPROM.put(CONFIG_GPIO_START, gpio);
DebugConfig debug {
c.debugTelnet,
c.debugSerial,
c.debugLevel
};
setDebugConfig(debug);
EEPROM.put(CONFIG_DEBUG_START, debug);
MeterConfig meter {
c.meterType,
@@ -625,14 +640,14 @@ bool AmsConfiguration::loadConfig82(int address) {
{0},
c.substituteMissing
};
setMeterConfig(meter);
EEPROM.put(CONFIG_METER_START, meter);
WebConfig web {
c.authSecurity
};
strcpy(web.username, c.authUser);
strcpy(web.password, c.authPassword);
setWebConfig(web);
EEPROM.put(CONFIG_WEB_START, web);
MqttConfig mqtt;
strcpy(mqtt.host, c.mqttHost);
@@ -644,7 +659,7 @@ bool AmsConfiguration::loadConfig82(int address) {
strcpy(mqtt.password, c.mqttPassword);
mqtt.payloadFormat = c.mqttPayloadFormat;
mqtt.ssl = c.mqttSsl;
setMqttConfig(mqtt);
EEPROM.put(CONFIG_MQTT_START, mqtt);
WiFiConfig wifi;
strcpy(wifi.ssid, c.wifiSsid);
@@ -656,20 +671,27 @@ bool AmsConfiguration::loadConfig82(int address) {
strcpy(wifi.dns2, c.wifiDns2);
strcpy(wifi.hostname, c.wifiHostname);
wifi.mdns = true;
setWiFiConfig(wifi);
EEPROM.put(CONFIG_WIFI_START, wifi);
SystemConfig sys {
c.boardType
};
setSystemConfig(sys);
return save();
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);
EEPROM.get(address, c);
EEPROM.end();
EntsoeConfig entsoe {"", "", "", 1000};
EEPROM.put(CONFIG_ENTSOE_START, entsoe);
NtpConfig ntp {
c.ntpEnable,
@@ -678,7 +700,7 @@ bool AmsConfiguration::loadConfig83(int address) {
c.ntpSummerOffset
};
strcpy(ntp.server, c.ntpServer);
setNtpConfig(ntp);
EEPROM.put(CONFIG_NTP_START, ntp);
DomoticzConfig domo {
c.domoELIDX,
@@ -687,7 +709,7 @@ bool AmsConfiguration::loadConfig83(int address) {
c.domoVL3IDX,
c.domoCL1IDX
};
setDomoticzConfig(domo);
EEPROM.put(CONFIG_DOMOTICZ_START, domo);
GpioConfig gpio {
c.hanPin,
@@ -705,14 +727,14 @@ bool AmsConfiguration::loadConfig83(int address) {
c.vccMultiplier,
c.vccBootLimit
};
setGpioConfig(gpio);
EEPROM.put(CONFIG_GPIO_START, gpio);
DebugConfig debug {
c.debugTelnet,
c.debugSerial,
c.debugLevel
};
setDebugConfig(debug);
EEPROM.put(CONFIG_DEBUG_START, debug);
MeterConfig meter {
c.meterType,
@@ -725,14 +747,14 @@ bool AmsConfiguration::loadConfig83(int address) {
};
memcpy(meter.encryptionKey, c.meterEncryptionKey, 16);
memcpy(meter.authenticationKey, c.meterAuthenticationKey, 16);
setMeterConfig(meter);
EEPROM.put(CONFIG_METER_START, meter);
WebConfig web {
c.authSecurity
};
strcpy(web.username, c.authUser);
strcpy(web.password, c.authPassword);
setWebConfig(web);
EEPROM.put(CONFIG_WEB_START, web);
MqttConfig mqtt;
strcpy(mqtt.host, c.mqttHost);
@@ -744,7 +766,7 @@ bool AmsConfiguration::loadConfig83(int address) {
strcpy(mqtt.password, c.mqttPassword);
mqtt.payloadFormat = c.mqttPayloadFormat;
mqtt.ssl = c.mqttSsl;
setMqttConfig(mqtt);
EEPROM.put(CONFIG_MQTT_START, mqtt);
WiFiConfig wifi;
strcpy(wifi.ssid, c.wifiSsid);
@@ -756,13 +778,18 @@ bool AmsConfiguration::loadConfig83(int address) {
strcpy(wifi.dns2, c.wifiDns2);
strcpy(wifi.hostname, c.wifiHostname);
wifi.mdns = c.mDnsEnable;
setWiFiConfig(wifi);
EEPROM.put(CONFIG_WIFI_START, wifi);
SystemConfig sys {
c.boardType
};
setSystemConfig(sys);
return save();
EEPROM.put(CONFIG_SYSTEM_START, sys);
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);
bool ret = EEPROM.commit();
EEPROM.end();
return ret;
}
bool AmsConfiguration::save() {
@@ -801,12 +828,21 @@ void AmsConfiguration::updateTempSensorConfig(uint8_t address[8], const char nam
}
}
if(!found) {
TempSensorConfig** tempSensors = new TempSensorConfig*[tempSensorCount+1];
if(this->tempSensors != NULL) {
for(int i = 0;i < tempSensorCount; i++) {
tempSensors[i] = this->tempSensors[i];
}
}
TempSensorConfig *data = new TempSensorConfig();
memcpy(data->address, address, 8);
strcpy(data->name, name);
data->common = common;
tempSensors[tempSensorCount] = data;
tempSensorCount++;
tempSensors[tempSensorCount++] = data;
if(this->tempSensors != NULL) {
delete this->tempSensors;
}
this->tempSensors = tempSensors;
}
}

View File

@@ -298,6 +298,8 @@ public:
bool isEntsoeChanged();
void ackEntsoeChange();
void loadTempSensors();
void saveTempSensors();
uint8_t getTempSensorCount();
TempSensorConfig* getTempSensorConfig(uint8_t address[8]);
void updateTempSensorConfig(uint8_t address[8], const char name[32], bool common);
@@ -316,9 +318,6 @@ private:
uint8_t tempSensorCount = 0;
TempSensorConfig** tempSensors;
void loadTempSensors();
void saveTempSensors();
bool loadConfig82(int address);
bool loadConfig83(int address);

View File

@@ -57,7 +57,7 @@ void AmsData::extractFromKaifa(HanReader& hanReader, uint8_t listSize) {
case (uint8_t)Kaifa::List3PhaseShort:
listId = hanReader.getString( (int)Kaifa_List3Phase::ListVersionIdentifier);
meterId = hanReader.getString( (int)Kaifa_List3Phase::MeterID);
meterType = hanReader.getString( (int)Kaifa_List3Phase::MeterType);
meterModel = hanReader.getString( (int)Kaifa_List3Phase::MeterType);
activeImportPower = hanReader.getUint( (int)Kaifa_List3Phase::ActiveImportPower);
reactiveImportPower = hanReader.getUint( (int)Kaifa_List3Phase::ReactiveImportPower);
activeExportPower = hanReader.getUint( (int)Kaifa_List3Phase::ActiveExportPower);
@@ -78,7 +78,7 @@ void AmsData::extractFromKaifa(HanReader& hanReader, uint8_t listSize) {
case (uint8_t)Kaifa::List1PhaseShort:
listId = hanReader.getString( (int)Kaifa_List1Phase::ListVersionIdentifier);
meterId = hanReader.getString( (int)Kaifa_List1Phase::MeterID);
meterType = hanReader.getString( (int)Kaifa_List1Phase::MeterType);
meterModel = hanReader.getString( (int)Kaifa_List1Phase::MeterType);
activeImportPower = hanReader.getUint( (int)Kaifa_List1Phase::ActiveImportPower);
reactiveImportPower = hanReader.getUint( (int)Kaifa_List1Phase::ReactiveImportPower);
activeExportPower = hanReader.getUint( (int)Kaifa_List1Phase::ActiveExportPower);
@@ -122,7 +122,7 @@ void AmsData::extractFromAidon(HanReader& hanReader, uint8_t listSize, bool subs
case (uint8_t)Aidon::List3PhaseShort:
listId = hanReader.getString( (uint8_t)Aidon_List3Phase::ListVersionIdentifier);
meterId = hanReader.getString( (uint8_t)Aidon_List3Phase::MeterID);
meterType = hanReader.getString( (uint8_t)Aidon_List3Phase::MeterType);
meterModel = hanReader.getString( (uint8_t)Aidon_List3Phase::MeterType);
activeImportPower = hanReader.getUint( (uint8_t)Aidon_List3Phase::ActiveImportPower);
reactiveImportPower = hanReader.getUint( (uint8_t)Aidon_List3Phase::ReactiveImportPower);
activeExportPower = hanReader.getUint( (uint8_t)Aidon_List3Phase::ActiveExportPower);
@@ -143,7 +143,7 @@ void AmsData::extractFromAidon(HanReader& hanReader, uint8_t listSize, bool subs
case (uint8_t)Aidon::List1PhaseShort:
listId = hanReader.getString( (uint8_t)Aidon_List1Phase::ListVersionIdentifier);
meterId = hanReader.getString( (uint8_t)Aidon_List1Phase::MeterID);
meterType = hanReader.getString( (uint8_t)Aidon_List1Phase::MeterType);
meterModel = hanReader.getString( (uint8_t)Aidon_List1Phase::MeterType);
activeImportPower = hanReader.getUint( (uint8_t)Aidon_List1Phase::ActiveImportPower);
reactiveImportPower = hanReader.getUint( (uint8_t)Aidon_List1Phase::ReactiveImportPower);
activeExportPower = hanReader.getUint( (uint8_t)Aidon_List1Phase::ActiveExportPower);
@@ -160,7 +160,7 @@ void AmsData::extractFromAidon(HanReader& hanReader, uint8_t listSize, bool subs
case (uint8_t)Aidon::List3PhaseITShort:
listId = hanReader.getString( (uint8_t)Aidon_List3PhaseIT::ListVersionIdentifier);
meterId = hanReader.getString( (uint8_t)Aidon_List3PhaseIT::MeterID);
meterType = hanReader.getString( (uint8_t)Aidon_List3PhaseIT::MeterType);
meterModel = hanReader.getString( (uint8_t)Aidon_List3PhaseIT::MeterType);
activeImportPower = hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::ActiveImportPower);
reactiveImportPower = hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::ReactiveImportPower);
activeExportPower = hanReader.getUint( (uint8_t)Aidon_List3PhaseIT::ActiveExportPower);
@@ -205,7 +205,7 @@ void AmsData::extractFromKamstrup(HanReader& hanReader, uint8_t listSize, bool s
case (uint8_t)Kamstrup::List1PhaseShort:
listId = hanReader.getString( (uint8_t)Kamstrup_List1Phase::ListVersionIdentifier);
meterId = hanReader.getString( (uint8_t)Kamstrup_List1Phase::MeterID);
meterType = hanReader.getString( (uint8_t)Kamstrup_List1Phase::MeterType);
meterModel = hanReader.getString( (uint8_t)Kamstrup_List1Phase::MeterType);
activeImportPower = hanReader.getInt( (uint8_t)Kamstrup_List1Phase::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (uint8_t)Kamstrup_List1Phase::ReactiveImportPower);
activeExportPower = hanReader.getInt( (uint8_t)Kamstrup_List1Phase::ActiveExportPower);
@@ -222,7 +222,7 @@ void AmsData::extractFromKamstrup(HanReader& hanReader, uint8_t listSize, bool s
case (uint8_t)Kamstrup::List3PhaseShort:
listId = hanReader.getString( (uint8_t)Kamstrup_List3Phase::ListVersionIdentifier);
meterId = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterID);
meterType = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterType);
meterModel = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterType);
activeImportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ReactiveImportPower);
activeExportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ActiveExportPower);
@@ -243,7 +243,7 @@ void AmsData::extractFromKamstrup(HanReader& hanReader, uint8_t listSize, bool s
case (uint8_t)Kamstrup::List3PhaseITShort:
listId = hanReader.getString( (uint8_t)Kamstrup_List3Phase::ListVersionIdentifier);
meterId = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterID);
meterType = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterType);
meterModel = hanReader.getString( (uint8_t)Kamstrup_List3Phase::MeterType);
activeImportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ReactiveImportPower);
activeExportPower = hanReader.getInt( (uint8_t)Kamstrup_List3Phase::ActiveExportPower);
@@ -321,7 +321,7 @@ void AmsData::apply(AmsData& other) {
case 2:
this->listId = other.getListId();
this->meterId = other.getMeterId();
this->meterType = other.getMeterType();
this->meterModel = other.getMeterModel();
this->reactiveImportPower = other.getReactiveImportPower();
this->activeExportPower = other.getActiveExportPower();
this->reactiveExportPower = other.getReactiveExportPower();
@@ -357,8 +357,8 @@ String AmsData::getMeterId() {
return this->meterId;
}
String AmsData::getMeterType() {
return this->meterType;
String AmsData::getMeterModel() {
return this->meterModel;
}
time_t AmsData::getMeterTimestamp() {

View File

@@ -25,7 +25,7 @@ public:
String getListId();
String getMeterId();
String getMeterType();
String getMeterModel();
time_t getMeterTimestamp();
@@ -53,7 +53,7 @@ private:
unsigned long lastUpdateMillis = 0;
uint8_t listType = 0;
time_t packageTimestamp = 0;
String listId, meterId, meterType;
String listId, meterId, meterModel;
time_t meterTimestamp = 0;
uint16_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0;
float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0;

View File

@@ -5,6 +5,8 @@
#define INVALID_BUTTON_PIN 0xFFFFFFFF
#define EPOCH_2021_01_01 1609459200
#include <SoftwareSerial.h>
#if defined(ESP8266)

View File

@@ -7,13 +7,13 @@
* electricity providers in other countries. It was originally based on ESP8266, but have also been
* adapted to work with ESP32.
*
* @author Roar Fredriksen (@roarfred)
* The original developer for this project
* https://github.com/roarfred/AmsToMqttBridge
*
* @author Gunnar Skjold (@gskjold)
* Maintainer of current code
* https://github.com/gskjold/AmsToMqttBridge
*
* @author Roar Fredriksen (@roarfred)
* The original developer for this project
* https://github.com/roarfred/AmsToMqttBridge
*/
#include "AmsToMqttBridge.h"
@@ -76,6 +76,7 @@ bool mqttEnabled = false;
uint8_t payloadFormat = 0;
String topic = "ams";
AmsData meterState;
bool ntpEnabled = false;
void setup() {
WiFiConfig wifi;
@@ -123,6 +124,7 @@ void setup() {
if(gpioConfig.apPin >= 0)
pinMode(gpioConfig.apPin, INPUT_PULLUP);
config.loadTempSensors();
hw.setup(&gpioConfig, &config);
hw.ledBlink(LED_INTERNAL, 1);
hw.ledBlink(LED_RED, 1);
@@ -206,7 +208,7 @@ void setup() {
WiFi.forceSleepBegin();
#endif
int i = 0;
while(hw.getVcc() < 3.2 && i < 3) {
while(hw.getVcc() > 1.0 && hw.getVcc() < 3.2 && i < 3) {
if(Debug.isActive(RemoteDebug::INFO)) debugI(" vcc not optimal, light sleep 10s");
#if defined(ESP8266)
delay(10000);
@@ -221,6 +223,7 @@ void setup() {
File firmwareFile = SPIFFS.open(FILE_FIRMWARE, "r");
debugD(" firmware size: %d", firmwareFile.size());
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
debugD(" available: %d", maxSketchSpace);
if (!Update.begin(maxSketchSpace, U_FLASH)) {
if(Debug.isActive(RemoteDebug::ERROR)) {
debugE("Unable to start firmware update");
@@ -260,10 +263,9 @@ void setup() {
NtpConfig ntp;
if(config.getNtpConfig(ntp)) {
if(ntp.enable) {
configTime(ntp.offset*10, ntp.summerOffset*10, ntp.server);
sntp_servermode_dhcp(ntp.dhcp ? 1 : 0);
}
configTime(ntp.offset*10, ntp.summerOffset*10, ntp.enable ? ntp.server : "");
sntp_servermode_dhcp(ntp.enable && ntp.dhcp ? 1 : 0);
ntpEnabled = ntp.enable;
TimeChangeRule std = {"STD", Last, Sun, Oct, 3, ntp.offset / 6};
TimeChangeRule dst = {"DST", Last, Sun, Mar, 2, (ntp.offset + ntp.summerOffset) / 6};
tz = new Timezone(dst, std);
@@ -376,16 +378,17 @@ void loop() {
}
if(config.isNtpChanged()) {
NtpConfig ntp;
if(config.getNtpConfig(ntp) && ntp.enable && strlen(ntp.server) > 0) {
configTime(ntp.offset*10, ntp.summerOffset*10, ntp.server);
sntp_servermode_dhcp(ntp.dhcp ? 1 : 0);
}
if(config.getNtpConfig(ntp)) {
configTime(ntp.offset*10, ntp.summerOffset*10, ntp.enable ? ntp.server : "");
sntp_servermode_dhcp(ntp.enable && ntp.dhcp ? 1 : 0);
ntpEnabled = ntp.enable;
if(tz != NULL) delete tz;
TimeChangeRule std = {"STD", Last, Sun, Oct, 3, ntp.offset / 6};
TimeChangeRule dst = {"DST", Last, Sun, Mar, 2, (ntp.offset + ntp.summerOffset) / 6};
tz = new Timezone(dst, std);
ws.setTimezone(tz);
if(tz != NULL) delete tz;
TimeChangeRule std = {"STD", Last, Sun, Oct, 3, ntp.offset / 6};
TimeChangeRule dst = {"DST", Last, Sun, Mar, 2, (ntp.offset + ntp.summerOffset) / 6};
tz = new Timezone(dst, std);
ws.setTimezone(tz);
}
config.ackNtpChange();
}
@@ -609,12 +612,26 @@ void readHanPort() {
if(data.getListType() > 0) {
if(mqttEnabled && mqttHandler != NULL) {
if(mqttHandler->publish(&data, &meterState)) {
if(eapi != NULL && data.getListType() == 3) {
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);

View File

@@ -4,8 +4,6 @@ void HwTools::setup(GpioConfig* config, AmsConfiguration* amsConf) {
this->config = config;
this->amsConf = amsConf;
this->tempSensorInit = false;
if(this->tempSensors == NULL)
this->tempSensors = new TempSensorData*[32];
if(sensorApi != NULL)
delete sensorApi;
if(oneWire != NULL)
@@ -81,7 +79,10 @@ uint8_t HwTools::getTempSensorCount() {
}
TempSensorData* HwTools::getTempSensorData(uint8_t i) {
return tempSensors[i];
if(i < sensorCount) {
return tempSensors[i];
}
return NULL;
}
bool HwTools::updateTemperatures() {
@@ -96,6 +97,10 @@ bool HwTools::updateTemperatures() {
DeviceAddress addr;
sensorApi->requestTemperatures();
int c = sensorApi->getDeviceCount();
if(this->tempSensors != NULL) {
delete this->tempSensors;
}
this->tempSensors = new TempSensorData*[c];
for(int i = 0; i < c; i++) {
bool found = false;
sensorApi->getAddress(addr, i);
@@ -119,7 +124,6 @@ bool HwTools::updateTemperatures() {
data->changed = data->lastValidRead != t;
data->lastValidRead = t;
}
tempSensors[sensorCount++] = data;
}
delay(10);

View File

@@ -36,7 +36,7 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState) {
hw->getTemperature(),
data->getListId().c_str(),
data->getMeterId().c_str(),
data->getMeterType().c_str(),
data->getMeterModel().c_str(),
data->getActiveImportPower(),
data->getReactiveImportPower(),
data->getActiveExportPower(),
@@ -61,7 +61,7 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState) {
hw->getTemperature(),
data->getListId().c_str(),
data->getMeterId().c_str(),
data->getMeterType().c_str(),
data->getMeterModel().c_str(),
data->getActiveImportPower(),
data->getReactiveImportPower(),
data->getActiveExportPower(),
@@ -94,14 +94,15 @@ bool JsonMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw)
for(int i = 0; i < count; i++) {
TempSensorData* data = hw->getTempSensorData(i);
TempSensorConfig* conf = config->getTempSensorConfig(data->address);
char* pos = buf+strlen(buf);
snprintf(pos, 26, "\"%s\":%.2f,",
toHex(data->address, 8).c_str(),
data->lastRead
);
data->changed = false;
delay(1);
if(data != NULL) {
char* pos = buf+strlen(buf);
snprintf(pos, 26, "\"%s\":%.2f,",
toHex(data->address, 8).c_str(),
data->lastRead
);
data->changed = false;
delay(1);
}
}
char* pos = buf+strlen(buf);
snprintf(count == 0 ? pos : pos-1, 8, "}}");

View File

@@ -13,7 +13,7 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState) {
case 3:
// ID and type belongs to List 2, but I see no need to send that every 10s
mqtt->publish(topic + "/meter/id", data->getMeterId());
mqtt->publish(topic + "/meter/type", data->getMeterType());
mqtt->publish(topic + "/meter/type", data->getMeterModel());
mqtt->publish(topic + "/meter/clock", String(data->getMeterTimestamp()));
mqtt->publish(topic + "/meter/import/reactive/accumulated", String(data->getReactiveImportCounter(), 2));
mqtt->publish(topic + "/meter/import/active/accumulated", String(data->getActiveImportCounter(), 2));
@@ -24,8 +24,8 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState) {
if(full || meterState->getMeterId() != data->getMeterId()) {
mqtt->publish(topic + "/meter/id", data->getMeterId());
}
if(full || meterState->getMeterType() != data->getMeterType()) {
mqtt->publish(topic + "/meter/type", data->getMeterType());
if(full || meterState->getMeterModel() != data->getMeterModel()) {
mqtt->publish(topic + "/meter/type", data->getMeterModel());
}
if(full || meterState->getL1Current() != data->getL1Current()) {
mqtt->publish(topic + "/meter/l1/current", String(data->getL1Current(), 2));
@@ -66,7 +66,7 @@ bool RawMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw)
uint8_t c = hw->getTempSensorCount();
for(int i = 0; i < c; i++) {
TempSensorData* data = hw->getTempSensorData(i);
if(data->lastValidRead > -85) {
if(data != NULL && data->lastValidRead > -85) {
if(data->changed || full) {
mqtt->publish(topic + "/temperature/" + toHex(data->address), String(data->lastValidRead, 2));
data->changed = false;

View File

@@ -30,6 +30,7 @@
#include "root/notfound_html.h"
#include "root/data_json.h"
#include "root/tempsensor_json.h"
#include "root/lowmem_html.h"
#include "base64.h"
@@ -45,9 +46,12 @@ void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, Meter
this->meterState = meterState;
this->mqtt = mqtt;
char jsuri[32];
snprintf(jsuri, 32, "/application-%s.js", VERSION);
server.on("/", HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on("/", HTTP_POST, std::bind(&AmsWebServer::handleSetup, this));
server.on("/application.js", HTTP_GET, std::bind(&AmsWebServer::applicationJs, this));
server.on(jsuri, HTTP_GET, std::bind(&AmsWebServer::applicationJs, this));
server.on("/temperature", HTTP_GET, std::bind(&AmsWebServer::temperature, this));
server.on("/temperature", HTTP_POST, std::bind(&AmsWebServer::temperaturePost, this));
server.on("/temperature.json", HTTP_GET, std::bind(&AmsWebServer::temperatureJson, this));
@@ -125,7 +129,6 @@ void AmsWebServer::loop() {
bool AmsWebServer::checkSecurity(byte level) {
bool access = WiFi.getMode() == WIFI_AP || webConfig.security < level;
if(!access && webConfig.security >= level && server.hasHeader("Authorization")) {
printD(" forcing web security");
String expectedAuth = String(webConfig.username) + ":" + String(webConfig.password);
String providedPwd = server.header("Authorization");
@@ -136,15 +139,10 @@ bool AmsWebServer::checkSecurity(byte level) {
}
if(!access) {
printD(" no access, requesting user/pass");
server.sendHeader("WWW-Authenticate", "Basic realm=\"Secure Area\"");
server.setContentLength(0);
server.send(401, "text/html", "");
}
if(access)
printD(" access granted");
else
printD(" access denied");
return access;
}
@@ -183,10 +181,15 @@ void AmsWebServer::temperaturePost() {
delay(1);
}
if (debugger->isActive(RemoteDebug::DEBUG)) config->print(debugger);
if(config->save()) {
printD("Successfully saved temperature sensors");
server.sendHeader("Location", String("/temperature"), true);
server.send (302, "text/plain", "");
} else {
printE("Error saving configuration");
String html = "<html><body><h1>Error saving configuration!</h1></form>";
server.send(500, "text/html", html);
}
}
@@ -204,6 +207,8 @@ void AmsWebServer::temperatureJson() {
for(int i = 0; i < count; i++) {
TempSensorData* data = hw->getTempSensorData(i);
if(data == NULL) continue;
TempSensorConfig* conf = config->getTempSensorConfig(data->address);
char* pos = buf+strlen(buf);
snprintf_P(pos, 72, TEMPSENSOR_JSON,
@@ -236,30 +241,38 @@ void AmsWebServer::price() {
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
String html = String((const __FlashStringHelper*) PRICE_HTML);
for(int i = 0; i < 24; i++) {
tmElements_t tm;
breakTime(tz->toLocal(time(nullptr)) + (SECS_PER_HOUR * i), tm);
char ts[5];
sprintf(ts, "%02d:00", tm.Hour);
html.replace("${time" + String(i) + "}", String(ts));
if(ESP.getFreeHeap() > 25000) {
String html = String((const __FlashStringHelper*) PRICE_HTML);
for(int i = 0; i < 24; i++) {
tmElements_t tm;
breakTime(tz->toLocal(time(nullptr)) + (SECS_PER_HOUR * i), tm);
char ts[5];
sprintf(ts, "%02d:00", tm.Hour);
html.replace("${time" + String(i) + "}", String(ts));
if(eapi != NULL) {
double price = eapi->getValueForHour(i);
if(price == ENTSOE_NO_VALUE) {
html.replace("${price" + String(i) + "}", "--");
if(eapi != NULL) {
double price = eapi->getValueForHour(i);
if(price == ENTSOE_NO_VALUE) {
html.replace("${price" + String(i) + "}", "--");
} else {
html.replace("${price" + String(i) + "}", String(price, 4));
}
} else {
html.replace("${price" + String(i) + "}", String(price, 4));
html.replace("${price" + String(i) + "}", "--");
}
} else {
html.replace("${price" + String(i) + "}", "--");
}
server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN);
server.send_P(200, "text/html", HEAD_HTML);
server.sendContent(html);
server.sendContent_P(FOOT_HTML);
} else {
server.setContentLength(LOWMEM_HTML_LEN + HEAD_HTML_LEN + FOOT_HTML_LEN);
server.send_P(200, "text/html", HEAD_HTML);
server.sendContent_P(LOWMEM_HTML);
server.sendContent_P(FOOT_HTML);
}
server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN);
server.send_P(200, "text/html", HEAD_HTML);
server.sendContent(html);
server.sendContent_P(FOOT_HTML);
}
void AmsWebServer::indexHtml() {
@@ -525,34 +538,41 @@ void AmsWebServer::configEntsoeHtml() {
EntsoeConfig entsoe;
config->getEntsoeConfig(entsoe);
String html = String((const __FlashStringHelper*) ENTSOE_HTML);
if(ESP.getFreeHeap() > 25000) {
String html = String((const __FlashStringHelper*) ENTSOE_HTML);
html.replace("{et}", entsoe.token);
html.replace("{em}", String(entsoe.multiplier / 1000.0, 3));
html.replace("{et}", entsoe.token);
html.replace("{em}", String(entsoe.multiplier / 1000.0, 3));
html.replace("{eaNo1}", strcmp(entsoe.area, "10YNO-1--------2") == 0 ? "selected" : "");
html.replace("{eaNo2}", strcmp(entsoe.area, "10YNO-2--------T") == 0 ? "selected" : "");
html.replace("{eaNo3}", strcmp(entsoe.area, "10YNO-3--------J") == 0 ? "selected" : "");
html.replace("{eaNo4}", strcmp(entsoe.area, "10YNO-4--------9") == 0 ? "selected" : "");
html.replace("{eaNo5}", strcmp(entsoe.area, "10Y1001A1001A48H") == 0 ? "selected" : "");
html.replace("{eaNo1}", strcmp(entsoe.area, "10YNO-1--------2") == 0 ? "selected" : "");
html.replace("{eaNo2}", strcmp(entsoe.area, "10YNO-2--------T") == 0 ? "selected" : "");
html.replace("{eaNo3}", strcmp(entsoe.area, "10YNO-3--------J") == 0 ? "selected" : "");
html.replace("{eaNo4}", strcmp(entsoe.area, "10YNO-4--------9") == 0 ? "selected" : "");
html.replace("{eaNo5}", strcmp(entsoe.area, "10Y1001A1001A48H") == 0 ? "selected" : "");
html.replace("{eaSe1}", strcmp(entsoe.area, "10Y1001A1001A44P") == 0 ? "selected" : "");
html.replace("{eaSe2}", strcmp(entsoe.area, "10Y1001A1001A45N") == 0 ? "selected" : "");
html.replace("{eaSe3}", strcmp(entsoe.area, "10Y1001A1001A46L") == 0 ? "selected" : "");
html.replace("{eaSe4}", strcmp(entsoe.area, "10Y1001A1001A47J") == 0 ? "selected" : "");
html.replace("{eaSe1}", strcmp(entsoe.area, "10Y1001A1001A44P") == 0 ? "selected" : "");
html.replace("{eaSe2}", strcmp(entsoe.area, "10Y1001A1001A45N") == 0 ? "selected" : "");
html.replace("{eaSe3}", strcmp(entsoe.area, "10Y1001A1001A46L") == 0 ? "selected" : "");
html.replace("{eaSe4}", strcmp(entsoe.area, "10Y1001A1001A47J") == 0 ? "selected" : "");
html.replace("{eaDk1}", strcmp(entsoe.area, "10YDK-1--------W") == 0 ? "selected" : "");
html.replace("{eaDk2}", strcmp(entsoe.area, "10YDK-2--------M") == 0 ? "selected" : "");
html.replace("{eaDk1}", strcmp(entsoe.area, "10YDK-1--------W") == 0 ? "selected" : "");
html.replace("{eaDk2}", strcmp(entsoe.area, "10YDK-2--------M") == 0 ? "selected" : "");
html.replace("{ecNOK}", strcmp(entsoe.area, "NOK") == 0 ? "selected" : "");
html.replace("{ecSEK}", strcmp(entsoe.area, "SEK") == 0 ? "selected" : "");
html.replace("{ecDKK}", strcmp(entsoe.area, "DKK") == 0 ? "selected" : "");
html.replace("{ecEUR}", strcmp(entsoe.area, "EUR") == 0 ? "selected" : "");
html.replace("{ecNOK}", strcmp(entsoe.area, "NOK") == 0 ? "selected" : "");
html.replace("{ecSEK}", strcmp(entsoe.area, "SEK") == 0 ? "selected" : "");
html.replace("{ecDKK}", strcmp(entsoe.area, "DKK") == 0 ? "selected" : "");
html.replace("{ecEUR}", strcmp(entsoe.area, "EUR") == 0 ? "selected" : "");
server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN);
server.send_P(200, "text/html", HEAD_HTML);
server.sendContent(html);
server.sendContent_P(FOOT_HTML);
server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN);
server.send_P(200, "text/html", HEAD_HTML);
server.sendContent(html);
server.sendContent_P(FOOT_HTML);
} else {
server.setContentLength(LOWMEM_HTML_LEN + HEAD_HTML_LEN + FOOT_HTML_LEN);
server.send_P(200, "text/html", HEAD_HTML);
server.sendContent_P(LOWMEM_HTML);
server.sendContent_P(FOOT_HTML);
}
}
void AmsWebServer::configWebHtml() {
@@ -1185,7 +1205,6 @@ void AmsWebServer::uploadPost() {
void AmsWebServer::uploadFile(const char* path) {
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START){
String filename = upload.filename;
if(uploading) {
printE("Upload already in progress");
String html = "<html><body><h1>Upload already in progress!</h1></form>";
@@ -1196,18 +1215,23 @@ void AmsWebServer::uploadFile(const char* path) {
server.send(500, "text/html", html);
} else {
uploading = true;
printD("handleFileUpload Name: %s", filename.c_str());
if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("handleFileUpload file: %s\n", path);
}
file = SPIFFS.open(path, "w");
filename = String();
file.write(upload.buf, upload.currentSize);
}
} else if(upload.status == UPLOAD_FILE_WRITE) {
if(file)
file.write(upload.buf, upload.currentSize);
} else if(upload.status == UPLOAD_FILE_END) {
if(file) {
file.flush();
file.close();
SPIFFS.end();
printD("handleFileUpload Size: %d", upload.totalSize);
if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("handleFileUpload Size: %lu\n", upload.totalSize);
}
} else {
server.send(500, "text/plain", "500: couldn't create file");
}