Always detect negative BCD values. Also detect BCD values with all F and treat them as missing data, ie. null in fields and not printed in json.

pull/1095/head
Fredrik Öhrström 2023-11-12 15:29:30 +01:00
rodzic 9a99daf0ed
commit c4b9f0d104
5 zmienionych plików z 46 dodań i 7 usunięć

Wyświetl plik

@ -55,4 +55,4 @@ telegram=|494468509494949495377286868686A85CFE07A90030052F2F_0413100000000F52FCF
# Test Zenner Minomess C1 water meter
telegram=|6644496A1064035514377251345015496A0007EE0050052F2F_0C1359000000026CBE2B82046CA12B8C0413FFFFFFFF8D0493132CFBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02FD1700002F2F|
{"media":"water","meter":"minomess","name":"Mino","id":"15503451","meter_date":"2021-11-30","total_m3":0.059,"target_m3":244444.442,"target_date":"2021-11-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
{"media":"water","meter":"minomess","name":"Mino","id":"15503451","meter_date":"2021-11-30","total_m3":0.059,"target_date":"2021-11-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}

Wyświetl plik

@ -189,3 +189,9 @@ namespace
// telegram=|1E4424238B06204790607A2A0010D8_0413DDC00000426CBF23441382BB0000|
// {"media":"warm water","meter":"hydrus","name":"HydrusIzarRSWarm","id":"60904720","total_m3":49.373,"total_at_date_m3":48.002,"at_date":"2021-03-31","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |HydrusIzarRSWarm;60904720;49.373;48.002;OK;1111-11-11 11:11.11
// Test: HydrusFoo hydrus 64641820 NOKEY
// Comment: Negative power values.
// telegram=|6344A5112018646470078C00D7900F002C256AB59B00F0F13032019092DE7A6A004007102F2F0C13896729004C1323462400CC101300000000CC201323462400426CDF2C0B3B0200F002FD742F0D025AC100C4016D3B17FE29CC01132841290001FD089F|
// {"at_date": "2022-12-31","at_datetime": "2023-09-30 23:59","flow_m3h": -0.002,"flow_temperature_c": 19.3,"id": "64641820","media": "water","meter": "hydrus","name": "HydrusFoo","remaining_battery_life_y": 9.240436,"status": "OK","timestamp": "1111-11-11T11:11:11Z","total_at_date_m3": 294.128,"total_m3": 296.789,"total_tariff1_at_date_m3": 0,"total_tariff2_at_date_m3": 244.623}
// |HydrusFoo;64641820;296.789;294.128;OK;1111-11-11 11:11.11

Wyświetl plik

@ -1,6 +1,6 @@
/*
Copyright (C) 2021 Olli Salonen (gpl-3.0-or-later)
Copyright (C) 2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2022-2023 Fredrik Öhrström (gpl-3.0-or-later)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -207,8 +207,8 @@ namespace
// Test: Mino minomess 15503451 NOKEY
// telegram=|6644496A1064035514377251345015496A0007EE0050052F2F#0C1359000000026CBE2B82046CA12B8C0413FFFFFFFF8D0493132CFBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02FD1700002F2F|
// {"media":"water","meter":"minomess","name":"Mino","id":"15503451","meter_date":"2021-11-30","total_m3":0.059,"target_m3":244444.442,"target_date":"2021-11-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |Mino;15503451;0.059;244444.442;OK;1111-11-11 11:11.11
// {"media":"water","meter":"minomess","name":"Mino","id":"15503451","meter_date":"2021-11-30","total_m3":0.059,"target_date":"2021-11-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |Mino;15503451;0.059;null;OK;1111-11-11 11:11.11
// Test: Minowired minomess 57575757 NOKEY
// telegram=|6874746808007257575757496A000712000000_0C7857575757046D2414DE280413000000000C943C000000004413FFFFFFFF426CFFFF840113FFFFFFFF82016CFFFFC40113FFFFFFFFC2016CFFFF840213FFFFFFFF82026CFFFF043B000000000422E62F000004260000000034220000000002FD1700001F5716|
@ -223,4 +223,4 @@ namespace
// Test: Zenner_warm minomess 51413121 NOKEY
// telegram=|6644496A8753155518377221314151496A0106300050052F2F_0C1357000000026CEC2182046CE1218C0413000000808D0493132C33FE00008000008000008000008000008000008000008000008000008000008000008000008000008000008002FD1700002F2F|
// {"media":"warm water","meter":"minomess","name":"Zenner_warm","id":"51413121","meter_date":"2023-01-12","total_m3":0.057,"target_m3":80000,"target_date":"2023-01-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |Zenner_warm;51413121;0.057;80000;OK;1111-11-11 11:11.11
// |Zenner_warm;51413121;0.057;80000;OK;1111-11-11 11:11.11

Wyświetl plik

@ -222,8 +222,8 @@ namespace
// Test: zenner_heat qcaloric 25932395 NOKEY
// telegram=|5E44496A95239325FD087A2CC050052F2F_0B6E030100426CDF2C4B6EFFFFFF82046CE1228B046E6200008D04EE132C3BFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F2F2F2F|
// {"media":"heat cost allocation","meter":"qcaloric","name":"zenner_heat","id":"25932395","status":"UNKNOWN_C0","current_consumption_hca":103,"set_date":"2022-12-31","consumption_at_set_date_hca":2444442,"set_date_1":"2022-12-31","consumption_at_set_date_1_hca":2444442,"set_date_8":"2023-02-01","consumption_at_set_date_8_hca":62,"timestamp":"1111-11-11T11:11:11Z"}
// |zenner_heat;25932395;103;2022-12-31;2444442;1111-11-11 11:11.11
// {"media":"heat cost allocation","meter":"qcaloric","name":"zenner_heat","id":"25932395","status":"UNKNOWN_C0","current_consumption_hca":103,"set_date":"2022-12-31","set_date_1":"2022-12-31","set_date_8":"2023-02-01","consumption_at_set_date_8_hca":62,"timestamp":"1111-11-11T11:11:11Z"}
// |zenner_heat;25932395;103;2022-12-31;null;1111-11-11 11:11.11
// Comment: Normal telegram that fills in values.
// telegram=|314493449392919034087a520000200b6e9700004b6e700200426c9f2ccb086e970000c2086cbe26326cffff046d2d16a227|

Wyświetl plik

@ -20,6 +20,7 @@
#include"util.h"
#include<assert.h>
#include<math.h>
#include<memory.h>
#include<limits>
@ -760,6 +761,15 @@ bool checkSizeHex(size_t expected_len, DifVifKey &dvk, string &v)
return false;
}
bool is_all_F(string &v)
{
for (size_t i = 0; i < v.length(); ++i)
{
if (v[i] != 'F') return false;
}
return true;
}
bool DVEntry::extractDouble(double *out, bool auto_scale, bool assume_signed)
{
int t = dif_vif_key.dif() & 0xf;
@ -847,10 +857,18 @@ bool DVEntry::extractDouble(double *out, bool auto_scale, bool assume_signed)
t == 0xC || // 8 digit BCD
t == 0xE) // 12 digit BCD
{
// Signed BCD values are always visible in bcd! Top nybble is f. We can force assume_signed to true.
assume_signed = true;
// 74140000 -> 00001474
string& v = value;
uint64_t raw = 0;
bool negate = false;
if (is_all_F(v))
{
*out = std::nan("");
return false;
}
if (t == 0x9) {
if (!checkSizeHex(2, dif_vif_key, v)) return false;
if (assume_signed && v[0] == 'F') { negate = true; v[0] = '0'; }
@ -1009,24 +1027,33 @@ bool DVEntry::extractLong(uint64_t *out)
{
// 74140000 -> 00001474
string& v = value;
if (is_all_F(v))
{
return false;
}
uint64_t raw = 0;
bool negate = false;
if (t == 0x9) {
if (!checkSizeHex(2, dif_vif_key, value)) return false;
if (v[0] == 'F') { negate = true; v[0] = '0'; }
assert(v.size() == 2);
raw = (v[0]-'0')*10 + (v[1]-'0');
} else if (t == 0xA) {
if (!checkSizeHex(4, dif_vif_key, value)) return false;
if (v[2] == 'F') { negate = true; v[2] = '0'; }
assert(v.size() == 4);
raw = (v[2]-'0')*10*10*10 + (v[3]-'0')*10*10
+ (v[0]-'0')*10 + (v[1]-'0');
} else if (t == 0xB) {
if (!checkSizeHex(6, dif_vif_key, value)) return false;
if (v[4] == 'F') { negate = true; v[4] = '0'; }
assert(v.size() == 6);
raw = (v[4]-'0')*10*10*10*10*10 + (v[5]-'0')*10*10*10*10
+ (v[2]-'0')*10*10*10 + (v[3]-'0')*10*10
+ (v[0]-'0')*10 + (v[1]-'0');
} else if (t == 0xC) {
if (!checkSizeHex(8, dif_vif_key, value)) return false;
if (v[6] == 'F') { negate = true; v[6] = '0'; }
assert(v.size() == 8);
raw = (v[6]-'0')*10*10*10*10*10*10*10 + (v[7]-'0')*10*10*10*10*10*10
+ (v[4]-'0')*10*10*10*10*10 + (v[5]-'0')*10*10*10*10
@ -1034,6 +1061,7 @@ bool DVEntry::extractLong(uint64_t *out)
+ (v[0]-'0')*10 + (v[1]-'0');
} else if (t == 0xE) {
if (!checkSizeHex(12, dif_vif_key, value)) return false;
if (v[10] == 'F') { negate = true; v[10] = '0'; }
assert(v.size() == 12);
raw =(v[10]-'0')*10*10*10*10*10*10*10*10*10*10*10 + (v[11]-'0')*10*10*10*10*10*10*10*10*10*10
+ (v[8]-'0')*10*10*10*10*10*10*10*10*10 + (v[9]-'0')*10*10*10*10*10*10*10*10
@ -1043,6 +1071,11 @@ bool DVEntry::extractLong(uint64_t *out)
+ (v[0]-'0')*10 + (v[1]-'0');
}
if (negate)
{
raw = (uint64_t)(((int64_t)raw)*-1);
}
*out = raw;
}
else