Compare commits

..

15 Commits

Author SHA1 Message Date
Gunnar Skjold
bdee066c33 Fixed reboot loop 2023-01-18 21:14:40 +01:00
Gunnar Skjold
dd23a0fa60 Fixed reboot look 2023-01-18 20:48:27 +01:00
Gunnar Skjold
e8fc6d48bf Fixed issue where GPIO setup becomes invalid 2023-01-18 17:11:01 +01:00
Gunnar Skjold
4b15ac74fc Update FUNDING.yml 2023-01-17 18:05:44 +01:00
Gunnar Skjold
8d448533c7 Fixed config export for esp32 2022-12-19 18:36:04 +01:00
Gunnar Skjold
43cb9a0000 Fixed DSMR CRC check 2022-12-19 18:14:12 +01:00
Gunnar Skjold
8f057e687c Merge pull request #387 from lassebm/lg-e360-fixes
Landis+Gyr E360 fixes
2022-12-19 16:45:52 +01:00
Lasse Bang Mikkelsen
5b4f680114 Align Landis+Gyr naming 2022-12-17 12:38:18 +01:00
Lasse Bang Mikkelsen
fabdfbadf4 Add support for Landis+Gyr meters using "LGF" manufacturer ID 2022-12-16 20:20:40 +01:00
Lasse Bang Mikkelsen
afa47ea633 Use list type 4 when phase active import/export power is available 2022-12-16 20:19:15 +01:00
Gunnar Skjold
c40e20c8e9 Extract active import/export per phase from DSMR 2022-12-15 18:25:13 +01:00
Gunnar Skjold
6b0d540f39 Added 300 baud 2022-12-07 11:51:45 +01:00
Gunnar Skjold
33bd3da310 Various fix for realtime values 2022-12-06 15:45:43 +01:00
Gunnar Skjold
a239e1a63d Fix on special case for Kaifa MA304T3 2022-12-06 08:28:30 +01:00
Gunnar Skjold
1ef5703971 Fixed changing mdns settings 2022-12-01 18:06:19 +01:00
14 changed files with 94 additions and 80 deletions

2
.github/FUNDING.yml vendored
View File

@@ -1 +1 @@
custom: ["https://paypal.me/gskjold"] custom: ["https://amsleser.no"]

View File

@@ -10,7 +10,7 @@ enum AmsType {
AmsTypeKaifa = 0x02, AmsTypeKaifa = 0x02,
AmsTypeKamstrup = 0x03, AmsTypeKamstrup = 0x03,
AmsTypeIskra = 0x08, AmsTypeIskra = 0x08,
AmsTypeLandis = 0x09, AmsTypeLandisGyr = 0x09,
AmsTypeSagemcom = 0x0A, AmsTypeSagemcom = 0x0A,
AmsTypeLng = 0x0B, AmsTypeLng = 0x0B,
AmsTypeCustom = 0x88, AmsTypeCustom = 0x88,

View File

@@ -21,7 +21,7 @@ bool AmsDataStorage::update(AmsData* data) {
} }
time_t now = time(nullptr); time_t now = time(nullptr);
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Time is: %lld\n", (int64_t) now); if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Time is: %lu\n", (int32_t) now);
if(tz == NULL) { if(tz == NULL) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Timezone is missing\n"); if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Timezone is missing\n");
return false; return false;
@@ -30,18 +30,18 @@ bool AmsDataStorage::update(AmsData* data) {
if(data->getMeterTimestamp() > BUILD_EPOCH) { if(data->getMeterTimestamp() > BUILD_EPOCH) {
now = data->getMeterTimestamp(); now = data->getMeterTimestamp();
if(debugger->isActive(RemoteDebug::DEBUG)) { if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("(AmsDataStorage) Using meter timestamp, which is: %lld\n", (int64_t) now); debugger->printf("(AmsDataStorage) Using meter timestamp, which is: %lu\n", (int32_t) now);
} }
} else if(data->getPackageTimestamp() > BUILD_EPOCH) { } else if(data->getPackageTimestamp() > BUILD_EPOCH) {
now = data->getPackageTimestamp(); now = data->getPackageTimestamp();
if(debugger->isActive(RemoteDebug::DEBUG)) { if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("(AmsDataStorage) Using package timestamp, which is: %lld\n", (int64_t) now); debugger->printf("(AmsDataStorage) Using package timestamp, which is: %lu\n", (int32_t) now);
} }
} }
} }
if(now < BUILD_EPOCH) { if(now < BUILD_EPOCH) {
if(debugger->isActive(RemoteDebug::VERBOSE)) { if(debugger->isActive(RemoteDebug::VERBOSE)) {
debugger->printf("(AmsDataStorage) Invalid time: %lld\n", (int64_t) now); debugger->printf("(AmsDataStorage) Invalid time: %lu\n", (int32_t) now);
} }
return false; return false;
} }
@@ -63,7 +63,7 @@ bool AmsDataStorage::update(AmsData* data) {
return true; return true;
} else { } else {
if(debugger->isActive(RemoteDebug::DEBUG)) { if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("(AmsDataStorage) Last day update: %lld\n", (int64_t) day.lastMeterReadTime); debugger->printf("(AmsDataStorage) Last day update: %lu\n", (int32_t) day.lastMeterReadTime);
} }
tmElements_t last; tmElements_t last;
breakTime(day.lastMeterReadTime, last); breakTime(day.lastMeterReadTime, last);
@@ -86,7 +86,7 @@ bool AmsDataStorage::update(AmsData* data) {
month.lastMeterReadTime = now; month.lastMeterReadTime = now;
} else { } else {
if(debugger->isActive(RemoteDebug::DEBUG)) { if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("(AmsDataStorage) Last month update: %lld\n", (int64_t) month.lastMeterReadTime); debugger->printf("(AmsDataStorage) Last month update: %lu\n", (int32_t) month.lastMeterReadTime);
} }
tmElements_t last; tmElements_t last;
breakTime(tz->toLocal(month.lastMeterReadTime), last); breakTime(tz->toLocal(month.lastMeterReadTime), last);
@@ -156,7 +156,7 @@ bool AmsDataStorage::update(AmsData* data) {
setHourExport(last.Hour, exp); setHourExport(last.Hour, exp);
if(debugger->isActive(RemoteDebug::INFO)) { if(debugger->isActive(RemoteDebug::INFO)) {
debugger->printf("(AmsDataStorage) Estimated usage for hour %u: %.1f - %.1f (%lld)\n", last.Hour, imp, exp, (int64_t) cur); debugger->printf("(AmsDataStorage) Estimated usage for hour %u: %.1f - %.1f (%lu)\n", last.Hour, imp, exp, (int32_t) cur);
} }
day.activeImport += imp; day.activeImport += imp;
@@ -199,7 +199,7 @@ bool AmsDataStorage::update(AmsData* data) {
breakTime(tz->toLocal(month.lastMeterReadTime), last); breakTime(tz->toLocal(month.lastMeterReadTime), last);
month.lastMeterReadTime = month.lastMeterReadTime - (last.Hour * 3600) - (last.Minute * 60) - last.Second; month.lastMeterReadTime = month.lastMeterReadTime - (last.Hour * 3600) - (last.Minute * 60) - last.Second;
if(debugger->isActive(RemoteDebug::DEBUG)) { if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("(AmsDataStorage) Last month read after resetting to midnight: %lld\n", (int64_t) month.lastMeterReadTime); debugger->printf("(AmsDataStorage) Last month read after resetting to midnight: %lu\n", (int32_t) month.lastMeterReadTime);
} }
float hrs = (now - month.lastMeterReadTime) / 3600.0; float hrs = (now - month.lastMeterReadTime) / 3600.0;
@@ -224,7 +224,7 @@ bool AmsDataStorage::update(AmsData* data) {
setDayExport(last.Day, exp); setDayExport(last.Day, exp);
if(debugger->isActive(RemoteDebug::INFO)) { if(debugger->isActive(RemoteDebug::INFO)) {
debugger->printf("(AmsDataStorage) Estimated usage for day %u: %.1f - %.1f (%lld)\n", last.Day, imp, exp, (int64_t) cur); debugger->printf("(AmsDataStorage) Estimated usage for day %u: %.1f - %.1f (%lu)\n", last.Day, imp, exp, (int32_t) cur);
} }
month.activeImport += imp; month.activeImport += imp;
@@ -383,11 +383,11 @@ bool AmsDataStorage::isDayHappy() {
tmElements_t tm, last; tmElements_t tm, last;
if(now < day.lastMeterReadTime) { if(now < day.lastMeterReadTime) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lld < %lld\n", (int64_t) now, (int64_t) day.lastMeterReadTime); if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lu < %lu\n", (int32_t) now, (int32_t) day.lastMeterReadTime);
return false; return false;
} }
if(now-day.lastMeterReadTime > 3600) { if(now-day.lastMeterReadTime > 3600) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lld - %lld > 3600\n", (int64_t) now, (int64_t) day.lastMeterReadTime); if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lu - %lu > 3600\n", (int32_t) now, (int32_t) day.lastMeterReadTime);
return false; return false;
} }
breakTime(tz->toLocal(now), tm); breakTime(tz->toLocal(now), tm);
@@ -411,11 +411,11 @@ bool AmsDataStorage::isMonthHappy() {
tmElements_t tm, last; tmElements_t tm, last;
if(now < month.lastMeterReadTime) { if(now < month.lastMeterReadTime) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lld < %lld\n", (int64_t) now, (int64_t) month.lastMeterReadTime); if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lu < %lu\n", (int32_t) now, (int32_t) month.lastMeterReadTime);
return false; return false;
} }
if(now-month.lastMeterReadTime > 86400) { if(now-month.lastMeterReadTime > 86400) {
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lld - %lld > 3600\n", (int64_t) now, (int64_t) month.lastMeterReadTime); if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lu - %lu > 3600\n", (int32_t) now, (int32_t) month.lastMeterReadTime);
return false; return false;
} }
breakTime(tz->toLocal(now), tm); breakTime(tz->toLocal(now), tm);

View File

@@ -122,44 +122,7 @@ void setup() {
Serial.begin(115200); Serial.begin(115200);
if(!config.getGpioConfig(gpioConfig)) { if(!config.getGpioConfig(gpioConfig)) {
#if HW_ROARFRED config.clearGpio(gpioConfig);
gpioConfig.hanPin = 3;
gpioConfig.apPin = 0;
gpioConfig.ledPin = 2;
gpioConfig.ledInverted = true;
gpioConfig.tempSensorPin = 5;
#elif defined(ARDUINO_ESP8266_WEMOS_D1MINI)
gpioConfig.hanPin = 5;
gpioConfig.apPin = 4;
gpioConfig.ledPin = 2;
gpioConfig.ledInverted = true;
gpioConfig.tempSensorPin = 14;
gpioConfig.vccMultiplier = 1100;
#elif defined(ARDUINO_LOLIN_D32)
gpioConfig.hanPin = 16;
gpioConfig.ledPin = 5;
gpioConfig.ledInverted = true;
gpioConfig.tempSensorPin = 14;
#elif defined(ARDUINO_FEATHER_ESP32)
gpioConfig.hanPin = 16;
gpioConfig.ledPin = 2;
gpioConfig.tempSensorPin = 14;
#elif defined(ARDUINO_ESP32_DEV)
gpioConfig.hanPin = 16;
gpioConfig.ledPin = 2;
gpioConfig.ledInverted = true;
#elif defined(ESP8266)
gpioConfig.hanPin = 3;
gpioConfig.ledPin = 2;
gpioConfig.ledInverted = true;
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
gpioConfig.hanPin = 18;
#elif defined(ESP32)
gpioConfig.hanPin = 16;
gpioConfig.ledPin = 2;
gpioConfig.ledInverted = true;
gpioConfig.tempSensorPin = 14;
#endif
} }
delay(1); delay(1);
@@ -1391,7 +1354,7 @@ void MQTT_connect() {
#if defined(ESP8266) #if defined(ESP8266)
if(mqttSecureClient) { if(mqttSecureClient) {
time_t epoch = time(nullptr); time_t epoch = time(nullptr);
debugD("Setting NTP time %lld for secure MQTT connection", epoch); debugD("Setting NTP time %lu for secure MQTT connection", epoch);
mqttSecureClient->setX509Time(epoch); mqttSecureClient->setX509Time(epoch);
} }
#endif #endif

View File

@@ -42,7 +42,7 @@ bool EnergyAccounting::update(AmsData* amsData) {
if(!init) { if(!init) {
currentHour = local.Hour; currentHour = local.Hour;
currentDay = local.Day; currentDay = local.Day;
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EnergyAccounting) Initializing data at %lld\n", (int64_t) now); if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EnergyAccounting) Initializing data at %lu\n", (int32_t) now);
if(!load()) { if(!load()) {
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) Unable to load existing data\n"); if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) Unable to load existing data\n");
data = { 4, local.Month, data = { 4, local.Month,
@@ -63,18 +63,21 @@ bool EnergyAccounting::update(AmsData* amsData) {
} }
if(!initPrice && eapi != NULL && eapi->getValueForHour(0) != ENTSOE_NO_VALUE) { if(!initPrice && eapi != NULL && eapi->getValueForHour(0) != ENTSOE_NO_VALUE) {
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EnergyAccounting) Initializing prices at %lld\n", (int64_t) now); if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EnergyAccounting) Initializing prices at %lu\n", (int32_t) now);
calcDayCost(); calcDayCost();
} }
if(local.Hour != currentHour && (amsData->getListType() >= 3 || local.Minute == 1)) { if(local.Hour != currentHour && (amsData->getListType() >= 3 || local.Minute == 1)) {
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) New local hour %d\n", local.Hour); if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) New local hour %d\n", local.Hour);
tmElements_t oneHrAgo; tmElements_t oneHrAgo, oneHrAgoLocal;
breakTime(now-3600, oneHrAgo); breakTime(now-3600, oneHrAgo);
uint16_t val = ds->getHourImport(oneHrAgo.Hour) / 10; uint16_t val = ds->getHourImport(oneHrAgo.Hour) / 10;
ret |= updateMax(val, local.Day);
breakTime(tz->toLocal(now-3600), oneHrAgoLocal);
ret |= updateMax(val, oneHrAgoLocal.Day);
currentHour = local.Hour; // Need to be defined here so that day cost is correctly calculated
if(local.Hour > 0) { if(local.Hour > 0) {
calcDayCost(); calcDayCost();
} }
@@ -143,9 +146,9 @@ void EnergyAccounting::calcDayCost() {
if(eapi != NULL && eapi->getValueForHour(0) != ENTSOE_NO_VALUE) { if(eapi != NULL && eapi->getValueForHour(0) != ENTSOE_NO_VALUE) {
if(initPrice) costDay = 0; if(initPrice) costDay = 0;
for(int i = 0; i < currentHour; i++) { for(int i = 0; i < currentHour; i++) {
float price = eapi->getValueForHour(i - currentHour); float price = eapi->getValueForHour(i - local.Hour);
if(price == ENTSOE_NO_VALUE) break; if(price == ENTSOE_NO_VALUE) break;
breakTime(now - ((currentHour - i) * 3600), utc); breakTime(now - ((local.Hour - i) * 3600), utc);
int16_t wh = ds->getHourImport(utc.Hour); int16_t wh = ds->getHourImport(utc.Hour);
costDay += price * (wh / 1000.0); costDay += price * (wh / 1000.0);
} }
@@ -161,9 +164,10 @@ double EnergyAccounting::getUseToday() {
float ret = 0.0; float ret = 0.0;
time_t now = time(nullptr); time_t now = time(nullptr);
if(now < BUILD_EPOCH) return 0; if(now < BUILD_EPOCH) return 0;
tmElements_t utc; tmElements_t utc, local;
breakTime(tz->toLocal(now), local);
for(int i = 0; i < currentHour; i++) { for(int i = 0; i < currentHour; i++) {
breakTime(now - ((currentHour - i) * 3600), utc); breakTime(now - ((local.Hour - i) * 3600), utc);
ret += ds->getHourImport(utc.Hour) / 1000.0; ret += ds->getHourImport(utc.Hour) / 1000.0;
} }
return ret + getUseThisHour(); return ret + getUseThisHour();

View File

@@ -1,16 +1,10 @@
#include "IEC6205621.h" #include "IEC6205621.h"
#include "ams/crc.h"
IEC6205621::IEC6205621(const char* p) { IEC6205621::IEC6205621(const char* p) {
if(strlen(p) < 16) if(strlen(p) < 16)
return; return;
String payload(p+1); String payload(p+1);
int crc_pos = payload.lastIndexOf("!");
String crc = payload.substring(crc_pos+1, crc_pos+5);
//uint16_t crc_calc = crc16_x25((uint8_t*) (payload.startsWith("/") ? p+1 : p), crc_pos);
//Serial.printf("CRC %s :: %04X\n", crc.c_str(), crc_calc);
lastUpdateMillis = millis(); lastUpdateMillis = millis();
listId = payload.substring(payload.startsWith("/") ? 1 : 0, payload.indexOf("\n")); listId = payload.substring(payload.startsWith("/") ? 1 : 0, payload.indexOf("\n"));
@@ -28,11 +22,14 @@ IEC6205621::IEC6205621(const char* p) {
meterType = AmsTypeIskra; meterType = AmsTypeIskra;
listId = listId.substring(0,5); listId = listId.substring(0,5);
} else if(listId.startsWith("XMX")) { } else if(listId.startsWith("XMX")) {
meterType = AmsTypeLandis; meterType = AmsTypeLandisGyr;
listId = listId.substring(0,6); listId = listId.substring(0,6);
} else if(listId.startsWith("Ene") || listId.startsWith("EST")) { } else if(listId.startsWith("Ene") || listId.startsWith("EST")) {
meterType = AmsTypeSagemcom; meterType = AmsTypeSagemcom;
listId = listId.substring(0,4); listId = listId.substring(0,4);
} else if(listId.startsWith("LGF")) {
meterType = AmsTypeLandisGyr;
listId = listId.substring(0,4);
} else { } else {
meterType = AmsTypeUnknown; meterType = AmsTypeUnknown;
listId = listId.substring(0,4); listId = listId.substring(0,4);
@@ -80,6 +77,14 @@ IEC6205621::IEC6205621(const char* p) {
l2current = extractDouble(payload, "51.7.0"); l2current = extractDouble(payload, "51.7.0");
l3current = extractDouble(payload, "71.7.0"); l3current = extractDouble(payload, "71.7.0");
l1activeImportPower = extractDouble(payload, "21.7.0");
l2activeImportPower = extractDouble(payload, "41.7.0");
l3activeImportPower = extractDouble(payload, "61.7.0");
l1activeExportPower = extractDouble(payload, "22.7.0");
l2activeExportPower = extractDouble(payload, "42.7.0");
l3activeExportPower = extractDouble(payload, "62.7.0");
if(l1voltage > 0 || l2voltage > 0 || l3voltage > 0) if(l1voltage > 0 || l2voltage > 0 || l3voltage > 0)
listType = 2; listType = 2;
@@ -128,6 +133,9 @@ IEC6205621::IEC6205621(const char* p) {
l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage; l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage;
} }
} }
if (l1activeImportPower > 0 || l2activeImportPower > 0 || l3activeImportPower > 0 || l1activeExportPower > 0 || l2activeExportPower > 0 || l3activeExportPower > 0)
listType = 4;
} }
String IEC6205621::extract(String payload, String obis) { String IEC6205621::extract(String payload, String obis) {

View File

@@ -98,8 +98,10 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, MeterConfig* meterCo
} }
if(listType >= 2 && memcmp(meterModel.c_str(), "MA304T3", 7) == 0) { if(listType >= 2 && memcmp(meterModel.c_str(), "MA304T3", 7) == 0) {
l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage;
l2voltage = sqrt(pow(l1voltage - l3voltage * cos(60 * (PI/180)), 2) + pow(l3voltage * sin(60 * (PI/180)),2)); l2voltage = sqrt(pow(l1voltage - l3voltage * cos(60 * (PI/180)), 2) + pow(l3voltage * sin(60 * (PI/180)),2));
if(l2voltage > 0) {
l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage;
}
} }
if(listType == 3) { if(listType == 3) {

View File

@@ -1,4 +1,7 @@
#include "DsmrParser.h" #include "DsmrParser.h"
#include "crc.h"
#include "hexutils.h"
#include "lwip/def.h"
int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) { int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) {
uint16_t crcPos = 0; uint16_t crcPos = 0;
@@ -14,8 +17,13 @@ int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) {
if(!reachedEnd) return DATA_PARSE_INCOMPLETE; if(!reachedEnd) return DATA_PARSE_INCOMPLETE;
buf[ctx.length+1] = '\0'; buf[ctx.length+1] = '\0';
if(crcPos > 0) { if(crcPos > 0) {
// TODO: CRC uint16_t crc_calc = crc16(buf, crcPos);
Serial.printf("CRC: %s\n", buf+crcPos); uint16_t crc = 0x0000;
fromHex((uint8_t*) &crc, String((char*) buf+crcPos), 2);
crc = ntohs(crc);
if(crc != crc_calc)
return DATA_PARSE_FOOTER_CHECKSUM_ERROR;
} }
return DATA_PARSE_OK; return DATA_PARSE_OK;
} }

View File

@@ -10,3 +10,20 @@ uint16_t crc16_x25(const uint8_t* p, int len)
return (~crc << 8) | (~crc >> 8 & 0xff); return (~crc << 8) | (~crc >> 8 & 0xff);
} }
uint16_t crc16 (const uint8_t *p, int len) {
uint16_t crc = 0;
while (len--) {
int i;
crc ^= *p++;
for (i = 0 ; i < 8 ; ++i) {
if (crc & 1)
crc = (crc >> 1) ^ 0xa001;
else
crc = (crc >> 1);
}
}
return crc;
}

View File

@@ -4,6 +4,7 @@
#include "Arduino.h" #include "Arduino.h"
#include <stdint.h> #include <stdint.h>
uint16_t crc16(const uint8_t* p, int len);
uint16_t crc16_x25(const uint8_t* p, int len); uint16_t crc16_x25(const uint8_t* p, int len);
#endif #endif

View File

@@ -110,7 +110,7 @@ bool EntsoeApi::loop() {
currentDay = tm.Day; currentDay = tm.Day;
return false; return false;
} else if(now > midnightMillis && currentDay != tm.Day) { } else if(now > midnightMillis && currentDay != tm.Day) {
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Rotating price objects at %lld\n", t); if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Rotating price objects at %lu\n", t);
if(today != NULL) delete today; if(today != NULL) delete today;
if(tomorrow != NULL) { if(tomorrow != NULL) {
today = tomorrow; today = tomorrow;

View File

@@ -329,8 +329,8 @@ void AmsWebServer::configMeterHtml() {
case AmsTypeIskra: case AmsTypeIskra:
manufacturer = F("Iskra"); manufacturer = F("Iskra");
break; break;
case AmsTypeLandis: case AmsTypeLandisGyr:
manufacturer = F("Landis + Gyro"); manufacturer = F("Landis+Gyr");
break; break;
case AmsTypeSagemcom: case AmsTypeSagemcom:
manufacturer = F("Sagemcom"); manufacturer = F("Sagemcom");
@@ -347,6 +347,7 @@ void AmsWebServer::configMeterHtml() {
html.replace(F("{mod}"), meterState->getMeterModel()); html.replace(F("{mod}"), meterState->getMeterModel());
html.replace(F("{mid}"), meterState->getMeterId()); html.replace(F("{mid}"), meterState->getMeterId());
html.replace(F("{b}"), String(meterConfig->baud)); html.replace(F("{b}"), String(meterConfig->baud));
html.replace(F("{b300}"), meterConfig->baud == 300 ? F("selected") : F(""));
html.replace(F("{b2400}"), meterConfig->baud == 2400 ? F("selected") : F("")); html.replace(F("{b2400}"), meterConfig->baud == 2400 ? F("selected") : F(""));
html.replace(F("{b4800}"), meterConfig->baud == 4800 ? F("selected") : F("")); html.replace(F("{b4800}"), meterConfig->baud == 4800 ? F("selected") : F(""));
html.replace(F("{b9600}"), meterConfig->baud == 9600 ? F("selected") : F("")); html.replace(F("{b9600}"), meterConfig->baud == 9600 ? F("selected") : F(""));
@@ -1022,6 +1023,7 @@ void AmsWebServer::handleSetup() {
switch(sys.boardType) { switch(sys.boardType) {
case 0: // roarfred case 0: // roarfred
config->clearGpio(*gpioConfig);
gpioConfig->hanPin = 3; gpioConfig->hanPin = 3;
gpioConfig->apPin = 0; gpioConfig->apPin = 0;
gpioConfig->ledPin = 2; gpioConfig->ledPin = 2;
@@ -1029,6 +1031,7 @@ void AmsWebServer::handleSetup() {
gpioConfig->tempSensorPin = 5; gpioConfig->tempSensorPin = 5;
break; break;
case 1: // Arnio Kamstrup case 1: // Arnio Kamstrup
config->clearGpio(*gpioConfig);
gpioConfig->hanPin = 3; gpioConfig->hanPin = 3;
gpioConfig->apPin = 0; gpioConfig->apPin = 0;
gpioConfig->ledPin = 2; gpioConfig->ledPin = 2;
@@ -1038,6 +1041,7 @@ void AmsWebServer::handleSetup() {
gpioConfig->ledRgbInverted = true; gpioConfig->ledRgbInverted = true;
break; break;
case 2: // spenceme case 2: // spenceme
config->clearGpio(*gpioConfig);
gpioConfig->hanPin = 3; gpioConfig->hanPin = 3;
gpioConfig->apPin = 0; gpioConfig->apPin = 0;
gpioConfig->ledPin = 2; gpioConfig->ledPin = 2;
@@ -1047,6 +1051,7 @@ void AmsWebServer::handleSetup() {
wifi.sleep = 1; wifi.sleep = 1;
break; break;
case 3: // Pow UART0 case 3: // Pow UART0
config->clearGpio(*gpioConfig);
gpioConfig->hanPin = 3; gpioConfig->hanPin = 3;
gpioConfig->apPin = 0; gpioConfig->apPin = 0;
gpioConfig->ledPin = 2; gpioConfig->ledPin = 2;
@@ -1057,6 +1062,7 @@ void AmsWebServer::handleSetup() {
wifi.sleep = 1; wifi.sleep = 1;
break; break;
case 4: // Pow GPIO12 case 4: // Pow GPIO12
config->clearGpio(*gpioConfig);
gpioConfig->hanPin = 12; gpioConfig->hanPin = 12;
gpioConfig->apPin = 0; gpioConfig->apPin = 0;
gpioConfig->ledPin = 2; gpioConfig->ledPin = 2;
@@ -1067,6 +1073,7 @@ void AmsWebServer::handleSetup() {
wifi.sleep = 1; wifi.sleep = 1;
break; break;
case 5: // Pow-K+ UART2 case 5: // Pow-K+ UART2
config->clearGpio(*gpioConfig);
gpioConfig->hanPin = 16; gpioConfig->hanPin = 16;
gpioConfig->apPin = 0; gpioConfig->apPin = 0;
gpioConfig->ledPinRed = 13; gpioConfig->ledPinRed = 13;
@@ -1078,6 +1085,7 @@ void AmsWebServer::handleSetup() {
wifi.sleep = 1; wifi.sleep = 1;
break; break;
case 6: // Pow-P1 case 6: // Pow-P1
config->clearGpio(*gpioConfig);
gpioConfig->hanPin = 16; gpioConfig->hanPin = 16;
gpioConfig->apPin = 0; gpioConfig->apPin = 0;
gpioConfig->ledPinRed = 13; gpioConfig->ledPinRed = 13;
@@ -1088,6 +1096,7 @@ void AmsWebServer::handleSetup() {
gpioConfig->vccResistorVcc = 33; gpioConfig->vccResistorVcc = 33;
break; break;
case 7: // Pow-U+ case 7: // Pow-U+
config->clearGpio(*gpioConfig);
gpioConfig->hanPin = 16; gpioConfig->hanPin = 16;
gpioConfig->apPin = 0; gpioConfig->apPin = 0;
gpioConfig->ledPinRed = 13; gpioConfig->ledPinRed = 13;
@@ -1264,6 +1273,7 @@ void AmsWebServer::handleSave() {
if(server.hasArg(F("h")) && !server.arg(F("h")).isEmpty()) { if(server.hasArg(F("h")) && !server.arg(F("h")).isEmpty()) {
strcpy(wifi.hostname, server.arg(F("h")).c_str()); 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.power = server.arg(F("w")).toFloat() * 10;
wifi.sleep = server.arg(F("z")).toInt(); wifi.sleep = server.arg(F("z")).toInt();
config->setWiFiConfig(wifi); config->setWiFiConfig(wifi);
@@ -2304,9 +2314,9 @@ void AmsWebServer::configFileDownload() {
if(ds != NULL) { if(ds != NULL) {
DayDataPoints day = ds->getDayData(); DayDataPoints day = ds->getDayData();
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dayplot %d %lld %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"), server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dayplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
day.version, day.version,
(int64_t) day.lastMeterReadTime, (int32_t) day.lastMeterReadTime,
day.activeImport, day.activeImport,
ds->getHourImport(0), ds->getHourImport(0),
ds->getHourImport(1), ds->getHourImport(1),
@@ -2366,9 +2376,9 @@ void AmsWebServer::configFileDownload() {
} }
MonthDataPoints month = ds->getMonthData(); MonthDataPoints month = ds->getMonthData();
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("monthplot %d %lld %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"), server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("monthplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
month.version, month.version,
(int64_t) month.lastMeterReadTime, (int32_t) month.lastMeterReadTime,
month.activeImport, month.activeImport,
ds->getDayImport(1), ds->getDayImport(1),
ds->getDayImport(2), ds->getDayImport(2),

View File

@@ -854,7 +854,7 @@ var fetch = function() {
$('.jmt').html("Iskra"); $('.jmt').html("Iskra");
break; break;
case 9: case 9:
$('.jmt').html("Landis"); $('.jmt').html("Landis+Gyr");
break; break;
case 10: case 10:
$('.jmt').html("Sagemcom"); $('.jmt').html("Sagemcom");

View File

@@ -35,6 +35,7 @@
<span class="input-group-text">Baud rate</span> <span class="input-group-text">Baud rate</span>
</div> </div>
<select class="form-control sd" name="b"> <select class="form-control sd" name="b">
<option value="300" {b300}>300</option>
<option value="2400" {b2400}>2400</option> <option value="2400" {b2400}>2400</option>
<option value="4800" {b4800}>4800</option> <option value="4800" {b4800}>4800</option>
<option value="9600" {b9600}>9600</option> <option value="9600" {b9600}>9600</option>