mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-04-07 22:50:16 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f1790a464 | ||
|
|
ca4cef5233 | ||
|
|
a0d7fd0d95 | ||
|
|
489dbf9254 | ||
|
|
a81aa11558 |
48
frames/iskra_croatia.txt
Normal file
48
frames/iskra_croatia.txt
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
They actually use multiple frames, so this is a "fake" frame combining the two into one, but without checksum fields.
|
||||||
|
|
||||||
|
7E
|
||||||
|
A0 BD
|
||||||
|
CF 02 23 03 00 00
|
||||||
|
E6 E7 00
|
||||||
|
0F 00 03 46 3B
|
||||||
|
0C 07 E9 0C 13 05 17 37 28 00 FF C4 00
|
||||||
|
|
||||||
|
02 21
|
||||||
|
09 08 39 32 30 32 39 36 39 31
|
||||||
|
09 04 17 37 28 00
|
||||||
|
09 05 07 E9 0C 13 05
|
||||||
|
06 00 6C 28 5A
|
||||||
|
06 00 4B 76 1A
|
||||||
|
06 00 20 B2 40
|
||||||
|
06 00 58 68 AA
|
||||||
|
06 00 57 A1 62
|
||||||
|
06 00 00 C7 48
|
||||||
|
06 00 17 EE D7
|
||||||
|
06 00 12 F5 5C
|
||||||
|
06 00 00 D9 6A
|
||||||
|
06 00 15 36 84
|
||||||
|
06 00 00 01 7E
|
||||||
|
06 00 00 00 00
|
||||||
|
12 03 79
|
||||||
|
06 00 00 00 7F
|
||||||
|
06 00 00 00 BD
|
||||||
|
06 00 00 00 41
|
||||||
|
06 00 00 00 00
|
||||||
|
06 00 00 00 00
|
||||||
|
06 00 00 00 00
|
||||||
|
12 09 54
|
||||||
|
12 09 35
|
||||||
|
12 09 49
|
||||||
|
12 00 37
|
||||||
|
12 00 59
|
||||||
|
12 00 4D
|
||||||
|
06 00 00 43 62
|
||||||
|
01 01
|
||||||
|
12 24 B8
|
||||||
|
01 01
|
||||||
|
12 24 B8
|
||||||
|
01 01
|
||||||
|
12 24 B8
|
||||||
|
03 01
|
||||||
|
|
||||||
|
00 00 7E
|
||||||
@@ -74,7 +74,7 @@ int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified, Pr
|
|||||||
fromHex((uint8_t*) &crc, String((char*) buf+crcPos), 2);
|
fromHex((uint8_t*) &crc, String((char*) buf+crcPos), 2);
|
||||||
crc = ntohs(crc);
|
crc = ntohs(crc);
|
||||||
|
|
||||||
if(crc != crc_calc) {
|
if(crc > 0 && crc != crc_calc) {
|
||||||
if(debugger != NULL) {
|
if(debugger != NULL) {
|
||||||
debugger->printf_P(PSTR("CRC incorrrect, %04X != %04X at position %lu\n"), crc, crc_calc, crcPos);
|
debugger->printf_P(PSTR("CRC incorrrect, %04X != %04X at position %lu\n"), crc, crc_calc, crcPos);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ int8_t HDLCParser::parse(uint8_t *d, DataParserContext &ctx) {
|
|||||||
return DATA_PARSE_BOUNDARY_FLAG_MISSING;
|
return DATA_PARSE_BOUNDARY_FLAG_MISSING;
|
||||||
|
|
||||||
// Verify FCS
|
// Verify FCS
|
||||||
if(ntohs(f->fcs) != crc16_x25(d + 1, len - sizeof *f - 1))
|
if(f->fcs > 0 && ntohs(f->fcs) != crc16_x25(d + 1, len - sizeof *f - 1))
|
||||||
return DATA_PARSE_FOOTER_CHECKSUM_ERROR;
|
return DATA_PARSE_FOOTER_CHECKSUM_ERROR;
|
||||||
|
|
||||||
// Skip destination address, LSB marks last byte
|
// Skip destination address, LSB marks last byte
|
||||||
@@ -50,7 +50,7 @@ int8_t HDLCParser::parse(uint8_t *d, DataParserContext &ctx) {
|
|||||||
HDLC3CtrlHcs* t3 = (HDLC3CtrlHcs*) (ptr);
|
HDLC3CtrlHcs* t3 = (HDLC3CtrlHcs*) (ptr);
|
||||||
|
|
||||||
// Verify HCS
|
// Verify HCS
|
||||||
if(ntohs(t3->hcs) != crc16_x25(d + 1, ptr-d))
|
if(t3->hcs > 0 && ntohs(t3->hcs) != crc16_x25(d + 1, ptr-d))
|
||||||
return DATA_PARSE_HEADER_CHECKSUM_ERROR;
|
return DATA_PARSE_HEADER_CHECKSUM_ERROR;
|
||||||
ptr += 3;
|
ptr += 3;
|
||||||
|
|
||||||
@@ -69,7 +69,12 @@ int8_t HDLCParser::parse(uint8_t *d, DataParserContext &ctx) {
|
|||||||
|
|
||||||
if(buf == NULL) return DATA_PARSE_FAIL;
|
if(buf == NULL) return DATA_PARSE_FAIL;
|
||||||
|
|
||||||
memcpy(buf + pos, ptr+3, ctx.length); // +3 to skip LLC
|
if((*ptr) == DATA_TAG_LLC) {
|
||||||
|
ptr += 3; // Skip LLC
|
||||||
|
ctx.length -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf + pos, ptr, ctx.length);
|
||||||
pos += ctx.length;
|
pos += ctx.length;
|
||||||
|
|
||||||
lastSequenceNumber++;
|
lastSequenceNumber++;
|
||||||
@@ -78,7 +83,12 @@ int8_t HDLCParser::parse(uint8_t *d, DataParserContext &ctx) {
|
|||||||
lastSequenceNumber = 0;
|
lastSequenceNumber = 0;
|
||||||
if(buf == NULL) return DATA_PARSE_FAIL;
|
if(buf == NULL) return DATA_PARSE_FAIL;
|
||||||
|
|
||||||
memcpy(buf + pos, ptr+3, ctx.length); // +3 to skip LLC
|
if((*ptr) == DATA_TAG_LLC) {
|
||||||
|
ptr += 3; // Skip LLC
|
||||||
|
ctx.length -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf + pos, ptr, ctx.length);
|
||||||
pos += ctx.length;
|
pos += ctx.length;
|
||||||
|
|
||||||
memcpy((uint8_t *) d, buf, pos);
|
memcpy((uint8_t *) d, buf, pos);
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ private:
|
|||||||
void publishPriceSensors(PriceService* ps);
|
void publishPriceSensors(PriceService* ps);
|
||||||
void publishSystemSensors();
|
void publishSystemSensors();
|
||||||
void publishThresholdSensors();
|
void publishThresholdSensors();
|
||||||
|
void toJsonIsoTimestamp(time_t t, char* buf, size_t buflen);
|
||||||
|
|
||||||
String boardTypeToString(uint8_t b) {
|
String boardTypeToString(uint8_t b) {
|
||||||
switch(b) {
|
switch(b) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"P" : %lu,
|
"P" : %lu,
|
||||||
"t" : "%s"
|
"t" : %s
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
"tPO" : %.3f,
|
"tPO" : %.3f,
|
||||||
"tQI" : %.3f,
|
"tQI" : %.3f,
|
||||||
"tQO" : %.3f,
|
"tQO" : %.3f,
|
||||||
"rtc" : "%s",
|
"rtc" : %s,
|
||||||
"t" : "%s"
|
"t" : %s
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,5 +12,5 @@
|
|||||||
"U1" : %.2f,
|
"U1" : %.2f,
|
||||||
"U2" : %.2f,
|
"U2" : %.2f,
|
||||||
"U3" : %.2f,
|
"U3" : %.2f,
|
||||||
"t" : "%s"
|
"t" : %s
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,5 +28,5 @@
|
|||||||
"tPO1" : %.3f,
|
"tPO1" : %.3f,
|
||||||
"tPO2" : %.3f,
|
"tPO2" : %.3f,
|
||||||
"tPO3" : %.3f,
|
"tPO3" : %.3f,
|
||||||
"t" : "%s"
|
"t" : %s
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ void HomeAssistantMqttHandler::setHomeAssistantConfig(HomeAssistantConfig config
|
|||||||
snprintf_P(json, 128, PSTR("[%s] "), config.discoveryNameTag);
|
snprintf_P(json, 128, PSTR("[%s] "), config.discoveryNameTag);
|
||||||
sensorNamePrefix = String(json);
|
sensorNamePrefix = String(json);
|
||||||
} else {
|
} else {
|
||||||
deviceName = F("AMS reader");
|
snprintf_P(json, 128, PSTR("AMS reader"));
|
||||||
|
deviceName = String(json);
|
||||||
sensorNamePrefix = "";
|
sensorNamePrefix = "";
|
||||||
}
|
}
|
||||||
deviceModel = boardTypeToString(boardType);
|
deviceModel = boardTypeToString(boardType);
|
||||||
@@ -52,20 +53,18 @@ void HomeAssistantMqttHandler::setHomeAssistantConfig(HomeAssistantConfig config
|
|||||||
deviceUrl = String(json);
|
deviceUrl = String(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strlen(config.discoveryPrefix) > 0) {
|
if(strlen(config.discoveryPrefix) == 0) {
|
||||||
snprintf_P(json, 128, PSTR("%s/status"), config.discoveryPrefix);
|
snprintf_P(config.discoveryPrefix, 64, PSTR("homeassistant"));
|
||||||
statusTopic = String(json);
|
|
||||||
|
|
||||||
snprintf_P(json, 128, PSTR("%s/sensor"), config.discoveryPrefix);
|
|
||||||
sensorTopic = String(json);
|
|
||||||
|
|
||||||
snprintf_P(json, 128, PSTR("%s/update"), config.discoveryPrefix);
|
|
||||||
updateTopic = String(json);
|
|
||||||
} else {
|
|
||||||
statusTopic = F("homeassistant/status");
|
|
||||||
sensorTopic = F("homeassistant/sensor");
|
|
||||||
updateTopic = F("homeassistant/update");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf_P(json, 128, PSTR("%s/status"), config.discoveryPrefix);
|
||||||
|
statusTopic = String(json);
|
||||||
|
|
||||||
|
snprintf_P(json, 128, PSTR("%s/sensor"), config.discoveryPrefix);
|
||||||
|
sensorTopic = String(json);
|
||||||
|
|
||||||
|
snprintf_P(json, 128, PSTR("%s/update"), config.discoveryPrefix);
|
||||||
|
updateTopic = String(json);
|
||||||
strcpy(this->mqttConfig.subscribeTopic, statusTopic.c_str());
|
strcpy(this->mqttConfig.subscribeTopic, statusTopic.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,12 +133,7 @@ bool HomeAssistantMqttHandler::publishList1(AmsData* data, EnergyAccounting* ea)
|
|||||||
publishList1Sensors();
|
publishList1Sensors();
|
||||||
|
|
||||||
char pt[24];
|
char pt[24];
|
||||||
memset(pt, 0, 24);
|
toJsonIsoTimestamp(data->getPackageTimestamp(), pt, sizeof(pt));
|
||||||
if(data->getPackageTimestamp() > 0) {
|
|
||||||
tmElements_t tm;
|
|
||||||
breakTime(data->getPackageTimestamp(), tm);
|
|
||||||
sprintf_P(pt, PSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf_P(json, BufferSize, HA1_JSON, data->getActiveImportPower(), pt);
|
snprintf_P(json, BufferSize, HA1_JSON, data->getActiveImportPower(), pt);
|
||||||
return mqtt.publish(pubTopic + "/power", json);
|
return mqtt.publish(pubTopic + "/power", json);
|
||||||
@@ -150,12 +144,7 @@ bool HomeAssistantMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea)
|
|||||||
if(data->getActiveExportPower() > 0) publishList2ExportSensors();
|
if(data->getActiveExportPower() > 0) publishList2ExportSensors();
|
||||||
|
|
||||||
char pt[24];
|
char pt[24];
|
||||||
memset(pt, 0, 24);
|
toJsonIsoTimestamp(data->getPackageTimestamp(), pt, sizeof(pt));
|
||||||
if(data->getPackageTimestamp() > 0) {
|
|
||||||
tmElements_t tm;
|
|
||||||
breakTime(data->getPackageTimestamp(), tm);
|
|
||||||
sprintf_P(pt, PSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf_P(json, BufferSize, HA3_JSON,
|
snprintf_P(json, BufferSize, HA3_JSON,
|
||||||
data->getListId().c_str(),
|
data->getListId().c_str(),
|
||||||
@@ -181,20 +170,11 @@ bool HomeAssistantMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea)
|
|||||||
if(data->getActiveExportCounter() > 0.0) publishList3ExportSensors();
|
if(data->getActiveExportCounter() > 0.0) publishList3ExportSensors();
|
||||||
|
|
||||||
char mt[24];
|
char mt[24];
|
||||||
memset(mt, 0, 24);
|
toJsonIsoTimestamp(data->getMeterTimestamp(), mt, sizeof(mt));
|
||||||
if(data->getMeterTimestamp() > 0) {
|
|
||||||
tmElements_t tm;
|
|
||||||
breakTime(data->getMeterTimestamp(), tm);
|
|
||||||
sprintf_P(mt, PSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
|
||||||
}
|
|
||||||
|
|
||||||
char pt[24];
|
char pt[24];
|
||||||
memset(pt, 0, 24);
|
memset(pt, 0, 24);
|
||||||
if(data->getPackageTimestamp() > 0) {
|
toJsonIsoTimestamp(data->getPackageTimestamp(), pt, sizeof(pt));
|
||||||
tmElements_t tm;
|
|
||||||
breakTime(data->getPackageTimestamp(), tm);
|
|
||||||
sprintf_P(pt, PSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf_P(json, BufferSize, HA2_JSON,
|
snprintf_P(json, BufferSize, HA2_JSON,
|
||||||
data->getActiveImportCounter(),
|
data->getActiveImportCounter(),
|
||||||
@@ -212,12 +192,7 @@ bool HomeAssistantMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea)
|
|||||||
if(data->getL1ActiveExportPower() > 0 || data->getL2ActiveExportPower() > 0 || data->getL3ActiveExportPower() > 0) publishList4ExportSensors();
|
if(data->getL1ActiveExportPower() > 0 || data->getL2ActiveExportPower() > 0 || data->getL3ActiveExportPower() > 0) publishList4ExportSensors();
|
||||||
|
|
||||||
char pt[24];
|
char pt[24];
|
||||||
memset(pt, 0, 24);
|
toJsonIsoTimestamp(data->getPackageTimestamp(), pt, sizeof(pt));
|
||||||
if(data->getPackageTimestamp() > 0) {
|
|
||||||
tmElements_t tm;
|
|
||||||
breakTime(data->getPackageTimestamp(), tm);
|
|
||||||
sprintf_P(pt, PSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf_P(json, BufferSize, HA4_JSON,
|
snprintf_P(json, BufferSize, HA4_JSON,
|
||||||
data->getListId().c_str(),
|
data->getListId().c_str(),
|
||||||
@@ -307,13 +282,8 @@ bool HomeAssistantMqttHandler::publishRealtime(AmsData* data, EnergyAccounting*
|
|||||||
|
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
char pt[24];
|
char pt[24];
|
||||||
memset(pt, 0, 24);
|
toJsonIsoTimestamp(now, pt, sizeof(pt));
|
||||||
if(now > 0) {
|
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"t\":%s"), pt);
|
||||||
tmElements_t tm;
|
|
||||||
breakTime(now, tm);
|
|
||||||
sprintf_P(pt, PSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
|
||||||
}
|
|
||||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"t\":\"%s\""), pt);
|
|
||||||
|
|
||||||
json[pos++] = '}';
|
json[pos++] = '}';
|
||||||
json[pos] = '\0';
|
json[pos] = '\0';
|
||||||
@@ -343,13 +313,8 @@ bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwT
|
|||||||
|
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
char pt[24];
|
char pt[24];
|
||||||
memset(pt, 0, 24);
|
toJsonIsoTimestamp(now, pt, sizeof(pt));
|
||||||
if(now > 0) {
|
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"t\":%s"), pt);
|
||||||
tmElements_t tm;
|
|
||||||
breakTime(now, tm);
|
|
||||||
sprintf_P(pt, PSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
|
||||||
}
|
|
||||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"t\":\"%s\""), pt);
|
|
||||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("}"));
|
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("}"));
|
||||||
|
|
||||||
bool ret = mqtt.publish(pubTopic + "/temperatures", json);
|
bool ret = mqtt.publish(pubTopic + "/temperatures", json);
|
||||||
@@ -421,25 +386,34 @@ bool HomeAssistantMqttHandler::publishPrices(PriceService* ps) {
|
|||||||
memset(ts1hr, 0, 24);
|
memset(ts1hr, 0, 24);
|
||||||
if(min1hrIdx > -1) {
|
if(min1hrIdx > -1) {
|
||||||
time_t ts = now + (SECS_PER_HOUR * min1hrIdx);
|
time_t ts = now + (SECS_PER_HOUR * min1hrIdx);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(ts, tm);
|
breakTime(ts, tm);
|
||||||
sprintf_P(ts1hr, PSTR("%04d-%02d-%02dT%02d:00:00Z"), tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
tm.Minute = 0;
|
||||||
|
tm.Second = 0;
|
||||||
|
ts = makeTime(tm);
|
||||||
|
toJsonIsoTimestamp(ts, ts1hr, sizeof(ts1hr));
|
||||||
}
|
}
|
||||||
char ts3hr[24];
|
char ts3hr[24];
|
||||||
memset(ts3hr, 0, 24);
|
memset(ts3hr, 0, 24);
|
||||||
if(min3hrIdx > -1) {
|
if(min3hrIdx > -1) {
|
||||||
time_t ts = now + (SECS_PER_HOUR * min3hrIdx);
|
time_t ts = now + (SECS_PER_HOUR * min3hrIdx);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(ts, tm);
|
breakTime(ts, tm);
|
||||||
sprintf_P(ts3hr, PSTR("%04d-%02d-%02dT%02d:00:00Z"), tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
tm.Minute = 0;
|
||||||
|
tm.Second = 0;
|
||||||
|
ts = makeTime(tm);
|
||||||
|
toJsonIsoTimestamp(ts, ts3hr, sizeof(ts3hr));
|
||||||
}
|
}
|
||||||
char ts6hr[24];
|
char ts6hr[24];
|
||||||
memset(ts6hr, 0, 24);
|
memset(ts6hr, 0, 24);
|
||||||
if(min6hrIdx > -1) {
|
if(min6hrIdx > -1) {
|
||||||
time_t ts = now + (SECS_PER_HOUR * min6hrIdx);
|
time_t ts = now + (SECS_PER_HOUR * min6hrIdx);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(ts, tm);
|
breakTime(ts, tm);
|
||||||
sprintf_P(ts6hr, PSTR("%04d-%02d-%02dT%02d:00:00Z"), tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
tm.Minute = 0;
|
||||||
|
tm.Second = 0;
|
||||||
|
ts = makeTime(tm);
|
||||||
|
toJsonIsoTimestamp(ts, ts6hr, sizeof(ts6hr));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t pos = snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\",\"prices\":{\"import\":["), WiFi.macAddress().c_str());
|
uint16_t pos = snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\",\"prices\":{\"import\":["), WiFi.macAddress().c_str());
|
||||||
@@ -468,7 +442,7 @@ bool HomeAssistantMqttHandler::publishPrices(PriceService* ps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pos--;
|
pos--;
|
||||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("],\"min\":%.4f,\"max\":%.4f,\"cheapest1hr\":\"%s\",\"cheapest3hr\":\"%s\",\"cheapest6hr\":\"%s\"}"),
|
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("],\"min\":%.4f,\"max\":%.4f,\"cheapest1hr\":%s,\"cheapest3hr\":%s,\"cheapest6hr\":%s}"),
|
||||||
min == INT16_MAX ? 0.0 : min,
|
min == INT16_MAX ? 0.0 : min,
|
||||||
max == INT16_MIN ? 0.0 : max,
|
max == INT16_MIN ? 0.0 : max,
|
||||||
ts1hr,
|
ts1hr,
|
||||||
@@ -477,13 +451,8 @@ bool HomeAssistantMqttHandler::publishPrices(PriceService* ps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
char pt[24];
|
char pt[24];
|
||||||
memset(pt, 0, 24);
|
toJsonIsoTimestamp(now, pt, sizeof(pt));
|
||||||
if(now > 0) {
|
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"t\":%s"), pt);
|
||||||
tmElements_t tm;
|
|
||||||
breakTime(now, tm);
|
|
||||||
sprintf_P(pt, PSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
|
||||||
}
|
|
||||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"t\":\"%s\""), pt);
|
|
||||||
|
|
||||||
json[pos++] = '}';
|
json[pos++] = '}';
|
||||||
json[pos] = '\0';
|
json[pos] = '\0';
|
||||||
@@ -502,14 +471,9 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, PriceService* ps, Ener
|
|||||||
|
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
char pt[24];
|
char pt[24];
|
||||||
memset(pt, 0, 24);
|
toJsonIsoTimestamp(now, pt, sizeof(pt));
|
||||||
if(now > 0) {
|
|
||||||
tmElements_t tm;
|
|
||||||
breakTime(now, tm);
|
|
||||||
sprintf_P(pt, PSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\",\"name\":\"%s\",\"up\":%d,\"vcc\":%.3f,\"rssi\":%d,\"temp\":%.2f,\"version\":\"%s\",\"t\":\"%s\"}"),
|
snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\",\"name\":\"%s\",\"up\":%d,\"vcc\":%.3f,\"rssi\":%d,\"temp\":%.2f,\"version\":\"%s\",\"t\":%s}"),
|
||||||
WiFi.macAddress().c_str(),
|
WiFi.macAddress().c_str(),
|
||||||
mqttConfig.clientId,
|
mqttConfig.clientId,
|
||||||
(uint32_t) (millis64()/1000),
|
(uint32_t) (millis64()/1000),
|
||||||
@@ -902,3 +866,14 @@ void HomeAssistantMqttHandler::onMessage(String &topic, String &payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HomeAssistantMqttHandler::toJsonIsoTimestamp(time_t t, char* buf, size_t buflen) {
|
||||||
|
memset(buf, 0, buflen);
|
||||||
|
if(t > 0) {
|
||||||
|
tmElements_t tm;
|
||||||
|
breakTime(t, tm);
|
||||||
|
snprintf_P(buf, buflen, PSTR("\"%04d-%02d-%02dT%02d:%02d:%02dZ\""), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
||||||
|
} else {
|
||||||
|
snprintf_P(buf, buflen, PSTR("null"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,5 +42,6 @@ private:
|
|||||||
bool publishList3(AmsData* data, EnergyAccounting* ea);
|
bool publishList3(AmsData* data, EnergyAccounting* ea);
|
||||||
bool publishList4(AmsData* data, EnergyAccounting* ea);
|
bool publishList4(AmsData* data, EnergyAccounting* ea);
|
||||||
String getMeterModel(AmsData* data);
|
String getMeterModel(AmsData* data);
|
||||||
|
void toJsonIsoTimestamp(time_t t, char* buf, size_t buflen);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -356,25 +356,34 @@ bool JsonMqttHandler::publishPrices(PriceService* ps) {
|
|||||||
memset(ts1hr, 0, 24);
|
memset(ts1hr, 0, 24);
|
||||||
if(min1hrIdx > -1) {
|
if(min1hrIdx > -1) {
|
||||||
time_t ts = now + (SECS_PER_HOUR * min1hrIdx);
|
time_t ts = now + (SECS_PER_HOUR * min1hrIdx);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(ts, tm);
|
breakTime(ts, tm);
|
||||||
sprintf_P(ts1hr, PSTR("%04d-%02d-%02dT%02d:00:00Z"), tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
tm.Minute = 0;
|
||||||
|
tm.Second = 0;
|
||||||
|
ts = makeTime(tm);
|
||||||
|
toJsonIsoTimestamp(ts, ts1hr, sizeof(ts1hr));
|
||||||
}
|
}
|
||||||
char ts3hr[24];
|
char ts3hr[24];
|
||||||
memset(ts3hr, 0, 24);
|
memset(ts3hr, 0, 24);
|
||||||
if(min3hrIdx > -1) {
|
if(min3hrIdx > -1) {
|
||||||
time_t ts = now + (SECS_PER_HOUR * min3hrIdx);
|
time_t ts = now + (SECS_PER_HOUR * min3hrIdx);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(ts, tm);
|
breakTime(ts, tm);
|
||||||
sprintf_P(ts3hr, PSTR("%04d-%02d-%02dT%02d:00:00Z"), tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
tm.Minute = 0;
|
||||||
|
tm.Second = 0;
|
||||||
|
ts = makeTime(tm);
|
||||||
|
toJsonIsoTimestamp(ts, ts3hr, sizeof(ts3hr));
|
||||||
}
|
}
|
||||||
char ts6hr[24];
|
char ts6hr[24];
|
||||||
memset(ts6hr, 0, 24);
|
memset(ts6hr, 0, 24);
|
||||||
if(min6hrIdx > -1) {
|
if(min6hrIdx > -1) {
|
||||||
time_t ts = now + (SECS_PER_HOUR * min6hrIdx);
|
time_t ts = now + (SECS_PER_HOUR * min6hrIdx);
|
||||||
tmElements_t tm;
|
tmElements_t tm;
|
||||||
breakTime(ts, tm);
|
breakTime(ts, tm);
|
||||||
sprintf_P(ts6hr, PSTR("%04d-%02d-%02dT%02d:00:00Z"), tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
tm.Minute = 0;
|
||||||
|
tm.Second = 0;
|
||||||
|
ts = makeTime(tm);
|
||||||
|
toJsonIsoTimestamp(ts, ts6hr, sizeof(ts6hr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mqttConfig.payloadFormat == 6) {
|
if(mqttConfig.payloadFormat == 6) {
|
||||||
@@ -388,7 +397,7 @@ bool JsonMqttHandler::publishPrices(PriceService* ps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"pr_min\":%.4f,\"pr_max\":%.4f,\"pr_cheapest1hr\":\"%s\",\"pr_cheapest3hr\":\"%s\",\"pr_cheapest6hr\":\"%s\"}"),
|
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"pr_min\":%.4f,\"pr_max\":%.4f,\"pr_cheapest1hr\":%s,\"pr_cheapest3hr\":%s,\"pr_cheapest6hr\":%s}"),
|
||||||
min == INT16_MAX ? 0.0 : min,
|
min == INT16_MAX ? 0.0 : min,
|
||||||
max == INT16_MIN ? 0.0 : max,
|
max == INT16_MIN ? 0.0 : max,
|
||||||
ts1hr,
|
ts1hr,
|
||||||
@@ -535,3 +544,14 @@ void JsonMqttHandler::onMessage(String &topic, String &payload) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JsonMqttHandler::toJsonIsoTimestamp(time_t t, char* buf, size_t buflen) {
|
||||||
|
memset(buf, 0, buflen);
|
||||||
|
if(t > 0) {
|
||||||
|
tmElements_t tm;
|
||||||
|
breakTime(t, tm);
|
||||||
|
snprintf_P(buf, buflen, PSTR("\"%04d-%02d-%02dT%02d:%02d:%02dZ\""), tm.Year+1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
|
||||||
|
} else {
|
||||||
|
snprintf_P(buf, buflen, PSTR("null"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,14 +27,11 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
|||||||
|
|
||||||
// Kaifa special case...
|
// Kaifa special case...
|
||||||
if(useMeterType == AmsTypeKaifa && data->base.type == CosemTypeDLongUnsigned) {
|
if(useMeterType == AmsTypeKaifa && data->base.type == CosemTypeDLongUnsigned) {
|
||||||
this->packageTimestamp = this->packageTimestamp > 0 && tz != NULL ? tz->toUTC(this->packageTimestamp) : 0;
|
|
||||||
listType = 1;
|
listType = 1;
|
||||||
meterType = AmsTypeKaifa;
|
meterType = AmsTypeKaifa;
|
||||||
activeImportPower = ntohl(data->dlu.data);
|
activeImportPower = ntohl(data->dlu.data);
|
||||||
lastUpdateMillis = millis64();
|
lastUpdateMillis = millis64();
|
||||||
} else if(data->base.type == CosemTypeOctetString) {
|
} else if(data->base.type == CosemTypeOctetString) {
|
||||||
this->packageTimestamp = this->packageTimestamp > 0 && tz != NULL ? tz->toUTC(this->packageTimestamp) : 0;
|
|
||||||
|
|
||||||
memcpy(str, data->oct.data, data->oct.length);
|
memcpy(str, data->oct.data, data->oct.length);
|
||||||
str[data->oct.length] = 0x00;
|
str[data->oct.length] = 0x00;
|
||||||
String listId = String(str);
|
String listId = String(str);
|
||||||
@@ -42,7 +39,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
|||||||
this->listId = listId;
|
this->listId = listId;
|
||||||
meterType = AmsTypeKaifa;
|
meterType = AmsTypeKaifa;
|
||||||
|
|
||||||
int idx = 0;
|
uint8_t idx = 0;
|
||||||
data = getCosemDataAt(idx, ((char *) (d)));
|
data = getCosemDataAt(idx, ((char *) (d)));
|
||||||
idx+=2;
|
idx+=2;
|
||||||
if(data->base.length == 0x0D || data->base.length == 0x12) {
|
if(data->base.length == 0x0D || data->base.length == 0x12) {
|
||||||
@@ -144,7 +141,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
|||||||
this->listId = listId;
|
this->listId = listId;
|
||||||
meterType = AmsTypeIskra;
|
meterType = AmsTypeIskra;
|
||||||
|
|
||||||
int idx = 0;
|
uint8_t idx = 0;
|
||||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
if(data->base.length == 0x12) {
|
if(data->base.length == 0x12) {
|
||||||
apply(state);
|
apply(state);
|
||||||
@@ -561,54 +558,157 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
|||||||
}
|
}
|
||||||
} else if(useMeterType == AmsTypeIskra && data->base.type == CosemTypeOctetString) { // Iskra special case
|
} else if(useMeterType == AmsTypeIskra && data->base.type == CosemTypeOctetString) { // Iskra special case
|
||||||
meterType = AmsTypeIskra;
|
meterType = AmsTypeIskra;
|
||||||
uint8_t idx = 5;
|
|
||||||
|
|
||||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
uint8_t idx = 0;
|
||||||
if(data != NULL) {
|
data = getCosemDataAt(idx, ((char *) (d)));
|
||||||
|
if(data->base.length == 0x21) {
|
||||||
|
idx = 4;
|
||||||
|
|
||||||
|
// 1.8.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
activeImportCounter = ntohl(data->dlu.data) / 1000.0;
|
activeImportCounter = ntohl(data->dlu.data) / 1000.0;
|
||||||
}
|
|
||||||
|
// 1.8.1
|
||||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
// 1.8.2
|
||||||
if(data != NULL) {
|
idx += 2;
|
||||||
|
|
||||||
|
// 2.8.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
activeExportCounter = ntohl(data->dlu.data) / 1000.0;
|
activeExportCounter = ntohl(data->dlu.data) / 1000.0;
|
||||||
}
|
|
||||||
|
|
||||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
|
||||||
if(data != NULL) {
|
|
||||||
reactiveImportCounter = ntohl(data->dlu.data) / 1000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
|
||||||
if(data != NULL) {
|
|
||||||
reactiveExportCounter = ntohl(data->dlu.data) / 1000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
// 2.8.1
|
||||||
if(data != NULL) {
|
// 2.8.2
|
||||||
|
idx += 2;
|
||||||
|
|
||||||
|
// 5.8.0
|
||||||
|
// 6.8.0
|
||||||
|
// 7.8.0
|
||||||
|
// 8.8.0
|
||||||
|
idx += 4;
|
||||||
|
|
||||||
|
// 1.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
activeImportPower = ntohl(data->dlu.data);
|
activeImportPower = ntohl(data->dlu.data);
|
||||||
}
|
|
||||||
|
|
||||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
// 2.7.0
|
||||||
if(data != NULL) {
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
activeExportPower = ntohl(data->dlu.data);
|
activeExportPower = ntohl(data->dlu.data);
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t str_len = 0;
|
// 13.7.0
|
||||||
str_len = getString(AMS_OBIS_UNKNOWN_1, sizeof(AMS_OBIS_UNKNOWN_1), ((char *) (d)), str);
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
if(str_len > 0) {
|
powerFactor= ntohl(data->dlu.data) / 1000.0;
|
||||||
meterId = String(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
listType = 3;
|
// 21.7.0
|
||||||
lastUpdateMillis = millis64();
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l1activeImportPower = ntohl(data->dlu.data);
|
||||||
|
|
||||||
|
// 41.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l2activeImportPower = ntohl(data->dlu.data);
|
||||||
|
|
||||||
|
// 61.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l3activeImportPower = ntohl(data->dlu.data);
|
||||||
|
|
||||||
|
// 22.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l1activeExportPower = ntohl(data->dlu.data);
|
||||||
|
|
||||||
|
// 42.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l2activeExportPower = ntohl(data->dlu.data);
|
||||||
|
|
||||||
|
// 62.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l3activeExportPower = ntohl(data->dlu.data);
|
||||||
|
|
||||||
|
// 32.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l1voltage = ntohs(data->lu.data) / 10.0;
|
||||||
|
|
||||||
|
// 52.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l2voltage = ntohs(data->lu.data) / 10.0;
|
||||||
|
|
||||||
|
// 72.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l3voltage = ntohs(data->lu.data) / 10.0;
|
||||||
|
|
||||||
|
// 31.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l1current = ntohs(data->lu.data) / 100.0;
|
||||||
|
|
||||||
|
// 51.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l2current = ntohs(data->lu.data) / 100.0;
|
||||||
|
|
||||||
|
// 71.7.0
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
l3current = ntohs(data->lu.data) / 100.0;
|
||||||
|
|
||||||
|
listType = 4;
|
||||||
|
lastUpdateMillis = millis64();
|
||||||
|
} else {
|
||||||
|
idx = 5;
|
||||||
|
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
if(data != NULL) {
|
||||||
|
activeImportCounter = ntohl(data->dlu.data) / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
if(data != NULL) {
|
||||||
|
activeExportCounter = ntohl(data->dlu.data) / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
if(data != NULL) {
|
||||||
|
reactiveImportCounter = ntohl(data->dlu.data) / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
if(data != NULL) {
|
||||||
|
reactiveExportCounter = ntohl(data->dlu.data) / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
if(data != NULL) {
|
||||||
|
activeImportPower = ntohl(data->dlu.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
if(data != NULL) {
|
||||||
|
activeExportPower = ntohl(data->dlu.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t str_len = 0;
|
||||||
|
str_len = getString(AMS_OBIS_UNKNOWN_1, sizeof(AMS_OBIS_UNKNOWN_1), ((char *) (d)), str);
|
||||||
|
if(str_len > 0) {
|
||||||
|
meterId = String(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
listType = 4;
|
||||||
|
lastUpdateMillis = millis64();
|
||||||
|
}
|
||||||
} else if(useMeterType == AmsTypeUnknown) {
|
} else if(useMeterType == AmsTypeUnknown) {
|
||||||
uint8_t str_len = 0;
|
uint8_t idx = 1;
|
||||||
str_len = getString(AMS_OBIS_UNKNOWN_1, sizeof(AMS_OBIS_UNKNOWN_1), ((char *) (d)), str);
|
CosemData* d1 = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
if(str_len > 0) {
|
CosemData* d2 = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
CosemData* d3 = getCosemDataAt(idx++, ((char *) (d)));
|
||||||
|
|
||||||
|
if(d1->base.type == CosemTypeOctetString && d2->base.type == CosemTypeOctetString && d3->base.type == CosemTypeOctetString) {
|
||||||
meterType = AmsTypeIskra;
|
meterType = AmsTypeIskra;
|
||||||
meterId = String(str);
|
|
||||||
lastUpdateMillis = millis64();
|
lastUpdateMillis = millis64();
|
||||||
listType = 3;
|
listType = 3;
|
||||||
|
} else {
|
||||||
|
uint8_t str_len = 0;
|
||||||
|
str_len = getString(AMS_OBIS_UNKNOWN_1, sizeof(AMS_OBIS_UNKNOWN_1), ((char *) (d)), str);
|
||||||
|
if(str_len > 0) {
|
||||||
|
meterType = AmsTypeIskra;
|
||||||
|
meterId = String(str);
|
||||||
|
lastUpdateMillis = millis64();
|
||||||
|
listType = 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -574,7 +574,8 @@ PricesContainer* PriceService::fetchPrices(time_t t) {
|
|||||||
for(uint8_t i = 0; i < ret->getNumberOfPoints(); i++) {
|
for(uint8_t i = 0; i < ret->getNumberOfPoints(); i++) {
|
||||||
// To avoid alignment issues on ESP8266, we use memcpy
|
// To avoid alignment issues on ESP8266, we use memcpy
|
||||||
memcpy(&intval, &points[i], sizeof(int32_t));
|
memcpy(&intval, &points[i], sizeof(int32_t));
|
||||||
float value = ntohl(intval) / 10000.0;
|
intval = ntohl(intval); // Change byte order before converting to float, to support negative values
|
||||||
|
float value = intval / 10000.0;
|
||||||
#if defined(AMS_REMOTE_DEBUG)
|
#if defined(AMS_REMOTE_DEBUG)
|
||||||
if (debugger->isActive(RemoteDebug::VERBOSE))
|
if (debugger->isActive(RemoteDebug::VERBOSE))
|
||||||
#endif
|
#endif
|
||||||
@@ -585,7 +586,8 @@ PricesContainer* PriceService::fetchPrices(time_t t) {
|
|||||||
for(uint8_t i = 0; i < ret->getNumberOfPoints(); i++) {
|
for(uint8_t i = 0; i < ret->getNumberOfPoints(); i++) {
|
||||||
// To avoid alignment issues on ESP8266, we use memcpy
|
// To avoid alignment issues on ESP8266, we use memcpy
|
||||||
memcpy(&intval, &points[ret->getNumberOfPoints()+i], sizeof(int32_t));
|
memcpy(&intval, &points[ret->getNumberOfPoints()+i], sizeof(int32_t));
|
||||||
float value = ntohl(intval) / 10000.0;
|
intval = ntohl(intval); // Change byte order before converting to float, to support negative values
|
||||||
|
float value = intval / 10000.0;
|
||||||
#if defined(AMS_REMOTE_DEBUG)
|
#if defined(AMS_REMOTE_DEBUG)
|
||||||
if (debugger->isActive(RemoteDebug::VERBOSE))
|
if (debugger->isActive(RemoteDebug::VERBOSE))
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
16
lib/SvelteUi/app/dist/index.js
vendored
16
lib/SvelteUi/app/dist/index.js
vendored
File diff suppressed because one or more lines are too long
11
lib/SvelteUi/app/package-lock.json
generated
11
lib/SvelteUi/app/package-lock.json
generated
@@ -9,7 +9,8 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssnano": "^5.1.15",
|
"cssnano": "^5.1.15",
|
||||||
"esbuild": ">=0.25.0"
|
"esbuild": ">=0.25.0",
|
||||||
|
"ipaddr.js": "^2.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.1.0",
|
"@sveltejs/vite-plugin-svelte": "^2.1.0",
|
||||||
@@ -1584,6 +1585,14 @@
|
|||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/ipaddr.js": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-binary-path": {
|
"node_modules/is-binary-path": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"svelte-navigator": {
|
"svelte-navigator": {
|
||||||
"svelte": ">=4.x"
|
"svelte": ">=4.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.1.0",
|
"@sveltejs/vite-plugin-svelte": "^2.1.0",
|
||||||
"@tailwindcss/forms": "^0.5.3",
|
"@tailwindcss/forms": "^0.5.3",
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssnano": "^5.1.15",
|
"cssnano": "^5.1.15",
|
||||||
"esbuild": ">=0.25.0"
|
"esbuild": ">=0.25.0",
|
||||||
|
"ipaddr.js": "^2.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import Clock from './Clock.svelte';
|
import Clock from './Clock.svelte';
|
||||||
import Mask from './Mask.svelte';
|
import Mask from './Mask.svelte';
|
||||||
import { scanForDevice } from './Helpers.js';
|
import { scanForDevice } from './Helpers.js';
|
||||||
|
import ipaddr from 'ipaddr.js';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
export let sysinfo;
|
export let sysinfo;
|
||||||
@@ -207,11 +208,11 @@
|
|||||||
</div>
|
</div>
|
||||||
{#if sysinfo.net.ipv6}
|
{#if sysinfo.net.ipv6}
|
||||||
<div class="my-2">
|
<div class="my-2">
|
||||||
IPv6: <span style="font-size: 14px;">{sysinfo.net.ipv6.replace(/\b:?(?:0+:?){2,}/, '::')}</span>
|
IPv6: <span style="font-size: 14px;">{ipaddr.parse(sysinfo.net.ipv6)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-2">
|
<div class="my-2">
|
||||||
{#if sysinfo.net.dns1v6}DNSv6: <span style="font-size: 14px;">{sysinfo.net.dns1v6.replace(/\b:?(?:0+:?){2,}/, '::')}</span>{/if}
|
{#if sysinfo.net.dns1v6}DNSv6: <span style="font-size: 14px;">{ipaddr.parse(sysinfo.net.dns1v6)}</span>{/if}
|
||||||
{#if sysinfo.net.dns2v6}DNSv6: <span style="font-size: 14px;">{sysinfo.net.dns2v6.replace(/\b:?(?:0+:?){2,}/, '::')}</span>{/if}
|
{#if sysinfo.net.dns2v6}DNSv6: <span style="font-size: 14px;">{ipaddr.parse(sysinfo.net.dns2v6)}</span>{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user