mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-04-03 21:32:54 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
606bac100a | ||
|
|
be569d1802 | ||
|
|
3e21105b2d | ||
|
|
9946827431 | ||
|
|
90d03ca77f | ||
|
|
7727b17122 |
@@ -175,6 +175,14 @@ byte* DlmsReader::getBuffer() {
|
|||||||
return buffer + (3 + destinationAddressLength + sourceAddressLength + 2 + 1);
|
return buffer + (3 + destinationAddressLength + sourceAddressLength + 2 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte* DlmsReader::getFullBuffer() {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DlmsReader::getFullBufferLength() {
|
||||||
|
return dataLength;
|
||||||
|
}
|
||||||
|
|
||||||
int DlmsReader::GetAddress(int addressPosition, byte* addressBuffer, int start, int length)
|
int DlmsReader::GetAddress(int addressPosition, byte* addressBuffer, int start, int length)
|
||||||
{
|
{
|
||||||
int addressBufferPos = start;
|
int addressBufferPos = start;
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ class DlmsReader
|
|||||||
int GetRawData(byte *buffer, int start, int length);
|
int GetRawData(byte *buffer, int start, int length);
|
||||||
int getBytesRead();
|
int getBytesRead();
|
||||||
byte* getBuffer();
|
byte* getBuffer();
|
||||||
|
byte* getFullBuffer();
|
||||||
|
int getFullBufferLength();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Crc16Class Crc16;
|
Crc16Class Crc16;
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ bool HanReader::read(byte data) {
|
|||||||
if (debugger->isActive(RemoteDebug::INFO)) {
|
if (debugger->isActive(RemoteDebug::INFO)) {
|
||||||
printI("Got valid DLMS data (%d bytes)", bytesRead);
|
printI("Got valid DLMS data (%d bytes)", bytesRead);
|
||||||
if (debugger->isActive(RemoteDebug::DEBUG)) {
|
if (debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
debugPrint(buffer, 0, bytesRead);
|
byte* full = reader.getFullBuffer();
|
||||||
|
int size = reader.getFullBufferLength();
|
||||||
|
printI("Full DLMS frame (%d bytes)", size);
|
||||||
|
debugPrint(full, 0, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -410,7 +410,7 @@ void loop() {
|
|||||||
mqtt.disconnect();
|
mqtt.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(eapi != NULL) {
|
if(eapi != NULL && ntpEnabled) {
|
||||||
if(eapi->loop() && mqttHandler != NULL && mqtt.connected()) {
|
if(eapi->loop() && mqttHandler != NULL && mqtt.connected()) {
|
||||||
mqttHandler->publishPrices(eapi);
|
mqttHandler->publishPrices(eapi);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ float DnbCurrParser::getValue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int DnbCurrParser::available() {
|
int DnbCurrParser::available() {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DnbCurrParser::read() {
|
int DnbCurrParser::read() {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DnbCurrParser::peek() {
|
int DnbCurrParser::peek() {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DnbCurrParser::flush() {
|
void DnbCurrParser::flush() {
|
||||||
|
|||||||
@@ -18,15 +18,15 @@ float EntsoeA44Parser::getPoint(uint8_t position) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int EntsoeA44Parser::available() {
|
int EntsoeA44Parser::available() {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EntsoeA44Parser::read() {
|
int EntsoeA44Parser::read() {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EntsoeA44Parser::peek() {
|
int EntsoeA44Parser::peek() {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntsoeA44Parser::flush() {
|
void EntsoeA44Parser::flush() {
|
||||||
|
|||||||
@@ -78,9 +78,13 @@ bool EntsoeApi::loop() {
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
uint64_t now = millis64();
|
uint64_t now = millis64();
|
||||||
|
if(now < 10000) return false; // Grace period
|
||||||
|
|
||||||
if(midnightMillis == 0) {
|
if(midnightMillis == 0) {
|
||||||
time_t epoch = tz->toLocal(time(nullptr));
|
time_t t = time(nullptr);
|
||||||
|
if(t <= 0) return false; // NTP not ready
|
||||||
|
|
||||||
|
time_t epoch = tz->toLocal(t);
|
||||||
|
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(epoch, tm);
|
breakTime(epoch, tm);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState) {
|
|||||||
);
|
);
|
||||||
return mqtt->publish(topic, json);
|
return mqtt->publish(topic, json);
|
||||||
} else if(data->getListType() == 2) {
|
} else if(data->getListType() == 2) {
|
||||||
char json[256];
|
char json[384];
|
||||||
snprintf_P(json, sizeof(json), JSON2_JSON,
|
snprintf_P(json, sizeof(json), JSON2_JSON,
|
||||||
WiFi.macAddress().c_str(),
|
WiFi.macAddress().c_str(),
|
||||||
clientId.c_str(),
|
clientId.c_str(),
|
||||||
@@ -50,7 +50,7 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState) {
|
|||||||
);
|
);
|
||||||
return mqtt->publish(topic, json);
|
return mqtt->publish(topic, json);
|
||||||
} else if(data->getListType() == 3) {
|
} else if(data->getListType() == 3) {
|
||||||
char json[384];
|
char json[512];
|
||||||
snprintf_P(json, sizeof(json), JSON3_JSON,
|
snprintf_P(json, sizeof(json), JSON3_JSON,
|
||||||
WiFi.macAddress().c_str(),
|
WiFi.macAddress().c_str(),
|
||||||
clientId.c_str(),
|
clientId.c_str(),
|
||||||
@@ -112,13 +112,13 @@ bool JsonMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw)
|
|||||||
bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) {
|
bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||||
if(topic.isEmpty() || !mqtt->connected())
|
if(topic.isEmpty() || !mqtt->connected())
|
||||||
return false;
|
return false;
|
||||||
if(strcmp(eapi->getToken(), "") != 0)
|
if(strcmp(eapi->getToken(), "") == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
|
|
||||||
float min1hr, min3hr, min6hr;
|
float min1hr, min3hr, min6hr;
|
||||||
uint8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1;
|
int8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1;
|
||||||
float min = INT16_MAX, max = INT16_MIN;
|
float min = INT16_MAX, max = INT16_MIN;
|
||||||
float values[24] = {0};
|
float values[24] = {0};
|
||||||
for(uint8_t i = 0; i < 24; i++) {
|
for(uint8_t i = 0; i < 24; i++) {
|
||||||
@@ -167,21 +167,27 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char ts1hr[21];
|
char ts1hr[21];
|
||||||
if(min1hrIdx != -1) {
|
if(min1hrIdx > -1) {
|
||||||
|
time_t ts = now + (SECS_PER_HOUR * min1hrIdx);
|
||||||
|
//Serial.printf("1hr: %d %lu\n", min1hrIdx, ts);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(now + (SECS_PER_HOUR * min1hrIdx), tm);
|
breakTime(ts, tm);
|
||||||
sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||||
}
|
}
|
||||||
char ts3hr[21];
|
char ts3hr[21];
|
||||||
if(min3hrIdx != -1) {
|
if(min3hrIdx > -1) {
|
||||||
|
time_t ts = now + (SECS_PER_HOUR * min3hrIdx);
|
||||||
|
//Serial.printf("3hr: %d %lu\n", min3hrIdx, ts);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(now + (SECS_PER_HOUR * min3hrIdx), tm);
|
breakTime(ts, tm);
|
||||||
sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||||
}
|
}
|
||||||
char ts6hr[21];
|
char ts6hr[21];
|
||||||
if(min6hrIdx != -1) {
|
if(min6hrIdx > -1) {
|
||||||
|
time_t ts = now + (SECS_PER_HOUR * min6hrIdx);
|
||||||
|
//Serial.printf("6hr: %d %lu\n", min6hrIdx, ts);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(now + (SECS_PER_HOUR * min6hrIdx), tm);
|
breakTime(ts, tm);
|
||||||
sprintf(ts6hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
sprintf(ts6hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,19 +79,20 @@ bool RawMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw)
|
|||||||
bool RawMqttHandler::publishPrices(EntsoeApi* eapi) {
|
bool RawMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||||
if(topic.isEmpty() || !mqtt->connected())
|
if(topic.isEmpty() || !mqtt->connected())
|
||||||
return false;
|
return false;
|
||||||
if(strcmp(eapi->getToken(), "") != 0)
|
if(strcmp(eapi->getToken(), "") == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
|
|
||||||
float min1hr, min3hr, min6hr;
|
float min1hr, min3hr, min6hr;
|
||||||
uint8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1;
|
int8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1;
|
||||||
float min = INT16_MAX, max = INT16_MIN;
|
float min = INT16_MAX, max = INT16_MIN;
|
||||||
float values[24] = {0};
|
float values[34] = {0};
|
||||||
for(uint8_t i = 0; i < 24; i++) {
|
for(uint8_t i = 0; i < 34; i++) {
|
||||||
float val = eapi->getValueForHour(now, i);
|
float val = eapi->getValueForHour(now, i);
|
||||||
values[i] = val;
|
values[i] = val;
|
||||||
|
|
||||||
|
if(i > 23) continue;
|
||||||
if(val == ENTSOE_NO_VALUE) break;
|
if(val == ENTSOE_NO_VALUE) break;
|
||||||
|
|
||||||
if(val < min) min = val;
|
if(val < min) min = val;
|
||||||
@@ -134,50 +135,56 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char ts1hr[21];
|
char ts1hr[21];
|
||||||
if(min1hrIdx != -1) {
|
if(min1hrIdx > -1) {
|
||||||
|
time_t ts = now + (SECS_PER_HOUR * min1hrIdx);
|
||||||
|
//Serial.printf("1hr: %d %lu\n", min1hrIdx, ts);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(now + (SECS_PER_HOUR * min1hrIdx), tm);
|
breakTime(ts, tm);
|
||||||
sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||||
}
|
}
|
||||||
char ts3hr[21];
|
char ts3hr[21];
|
||||||
if(min3hrIdx != -1) {
|
if(min3hrIdx > -1) {
|
||||||
|
time_t ts = now + (SECS_PER_HOUR * min3hrIdx);
|
||||||
|
//Serial.printf("3hr: %d %lu\n", min3hrIdx, ts);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(now + (SECS_PER_HOUR * min3hrIdx), tm);
|
breakTime(ts, tm);
|
||||||
sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||||
}
|
}
|
||||||
char ts6hr[21];
|
char ts6hr[21];
|
||||||
if(min6hrIdx != -1) {
|
if(min6hrIdx > -1) {
|
||||||
|
time_t ts = now + (SECS_PER_HOUR * min6hrIdx);
|
||||||
|
//Serial.printf("6hr: %d %lu\n", min6hrIdx, ts);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(now + (SECS_PER_HOUR * min6hrIdx), tm);
|
breakTime(ts, tm);
|
||||||
sprintf(ts6hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
sprintf(ts6hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 24; i++) {
|
for(int i = 0; i < 34; i++) {
|
||||||
float val = values[i];
|
float val = values[i];
|
||||||
if(val == ENTSOE_NO_VALUE) {
|
if(val == ENTSOE_NO_VALUE) {
|
||||||
mqtt->publish(topic + "/price/" + String(i), "");
|
mqtt->publish(topic + "/price/" + String(i), "", true, 0);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
mqtt->publish(topic + "/price/" + String(i), String(val, 4));
|
mqtt->publish(topic + "/price/" + String(i), String(val, 4), true, 0);
|
||||||
}
|
}
|
||||||
mqtt->loop();
|
mqtt->loop();
|
||||||
delay(10);
|
delay(10);
|
||||||
}
|
}
|
||||||
if(min != INT16_MAX) {
|
if(min != INT16_MAX) {
|
||||||
mqtt->publish(topic + "/price/min", String(min, 4));
|
mqtt->publish(topic + "/price/min", String(min, 4), true, 0);
|
||||||
}
|
}
|
||||||
if(max != INT16_MIN) {
|
if(max != INT16_MIN) {
|
||||||
mqtt->publish(topic + "/price/max", String(max, 4));
|
mqtt->publish(topic + "/price/max", String(max, 4), true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(min1hrIdx != -1) {
|
if(min1hrIdx != -1) {
|
||||||
mqtt->publish(topic + "/price/cheapest/1hr", String(ts1hr));
|
mqtt->publish(topic + "/price/cheapest/1hr", String(ts1hr), true, 0);
|
||||||
}
|
}
|
||||||
if(min3hrIdx != -1) {
|
if(min3hrIdx != -1) {
|
||||||
mqtt->publish(topic + "/price/cheapest/3hr", String(ts3hr));
|
mqtt->publish(topic + "/price/cheapest/3hr", String(ts3hr), true, 0);
|
||||||
}
|
}
|
||||||
if(min6hrIdx != -1) {
|
if(min6hrIdx != -1) {
|
||||||
mqtt->publish(topic + "/price/cheapest/6hr", String(ts6hr));
|
mqtt->publish(topic + "/price/cheapest/6hr", String(ts6hr), true, 0);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -186,7 +193,7 @@ bool RawMqttHandler::publishSystem(HwTools* hw) {
|
|||||||
if(topic.isEmpty() || !mqtt->connected())
|
if(topic.isEmpty() || !mqtt->connected())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mqtt->publish(topic + "/id", WiFi.macAddress());
|
mqtt->publish(topic + "/id", WiFi.macAddress(), true, 0);
|
||||||
mqtt->publish(topic + "/uptime", String((unsigned long) millis64()/1000));
|
mqtt->publish(topic + "/uptime", String((unsigned long) millis64()/1000));
|
||||||
float vcc = hw->getVcc();
|
float vcc = hw->getVcc();
|
||||||
if(vcc > 0) {
|
if(vcc > 0) {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
"9" : %.4f,
|
"9" : %.4f,
|
||||||
"10" : %.4f,
|
"10" : %.4f,
|
||||||
"11" : %.4f,
|
"11" : %.4f,
|
||||||
"12" : %.4f,
|
|
||||||
"min" : %.4f,
|
"min" : %.4f,
|
||||||
"max" : %.4f,
|
"max" : %.4f,
|
||||||
"cheapest1hr" : "%s",
|
"cheapest1hr" : "%s",
|
||||||
|
|||||||
Reference in New Issue
Block a user