diff --git a/simulations/simulation_unix_timestamp.txt b/simulations/simulation_unix_timestamp.txt index 5d339d3..5a1a4de 100644 --- a/simulations/simulation_unix_timestamp.txt +++ b/simulations/simulation_unix_timestamp.txt @@ -1,3 +1,3 @@ # Test Aventies Water Meter telegram=76442104710007612507727100076121042507B5006005E2E95A3C2A1279A5415E6732679B43369FD5FDDDD783EEEBB48236D34E7C94AF0A18A5FDA5F7D64111EB42D4D891622139F2952F9D12A20088DFA4CF8123871123EE1F6C1DCEA414879DDB4E05E508F1826D7EFBA6964DF804C9261EA23BBF03 -|466.472;UT;Votten;61070071 +|466.472*UT*1111-11-11T11:11.11Z*1111-11-11 11:11.11*Votten*61070071*extra_info diff --git a/src/main.cc b/src/main.cc index 429b04a..84a4351 100644 --- a/src/main.cc +++ b/src/main.cc @@ -205,7 +205,7 @@ void list_fields(Configuration *config, string meter_driver) mi.driver = toMeterDriver(meter_driver); shared_ptr meter = createMeter(&mi); - int width = 0; + int width = 13; // Width of timestamp_utc for (auto &p : meter->prints()) { if ((int)p.field_name.size() > width) width = p.field_name.size(); @@ -223,8 +223,10 @@ void list_fields(Configuration *config, string meter_driver) printf("%s Timestamp when wmbusmeters received the telegram. Local time for hr/fields UTC for json.\n", timestamp.c_str()); string timestamp_ut = padLeft("timestamp_ut", width); printf("%s Unix timestamp when wmbusmeters received the telegram.\n", timestamp_ut.c_str()); - string timestamp_lt = padLeft("timestamp_l", width); - printf("%s Unix timestamp when wmbusmeters received the telegram.\n", timestamp_ut.c_str()); + string timestamp_lt = padLeft("timestamp_lt", width); + printf("%s Local time when wmbusmeters received the telegram.\n", timestamp_lt.c_str()); + string timestamp_utc = padLeft("timestamp_utc", width); + printf("%s UTC time when wmbusmeters received the telegram.\n", timestamp_utc.c_str()); string device = padLeft("device", width); printf("%s The wmbus device that received the telegram.\n", device.c_str()); string rssi = padLeft("rssi_dbm", width); diff --git a/src/meters.cc b/src/meters.cc index 61dcd3d..44a371d 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -584,7 +584,8 @@ void MeterCommonImplementation::triggerUpdate(Telegram *t) t->handled = true; } -string concatAllFields(Meter *m, Telegram *t, char c, vector &prints, vector &cs, bool hr, vector *added_fields) +string concatAllFields(Meter *m, Telegram *t, char c, vector &prints, vector &cs, bool hr, + vector *added_fields, vector *extra_constant_fields) { string s; s = ""; @@ -623,102 +624,155 @@ string concatAllFields(Meter *m, Telegram *t, char c, vector &prints, vec return s; } -string concatFields(Meter *m, Telegram *t, char c, vector &prints, vector &cs, bool hr, - vector *selected_fields, vector *added_fields) +string findField(string key, vector *extra_constant_fields) { - if (selected_fields == NULL || selected_fields->size() == 0) + key = key+"="; + for (string ecf : *extra_constant_fields) { - return concatAllFields(m, t, c, prints, cs, hr, added_fields); + if (startsWith(ecf, key)) + { + return ecf.substr(key.length()); + } } - string s; - s = ""; + return ""; +} - for (string field : *selected_fields) +// Is the desired field one of the fields common to all meters and telegrams? +bool checkCommonField(string *buf, string field, Meter *m, Telegram *t, char c) +{ + if (field == "name") { - if (field == "name") - { - s += m->name() + c; - continue; - } - if (field == "id") - { - s += t->ids.back() + c; - continue; - } - if (field == "timestamp") - { - s += m->datetimeOfUpdateHumanReadable() + c; - continue; - } - if (field == "timestamp_lt") - { - s += m->datetimeOfUpdateHumanReadable() + c; - continue; - } - if (field == "timestamp_utc") - { - s += m->datetimeOfUpdateRobot() + c; - continue; - } - if (field == "timestamp_ut") - { - s += m->unixTimestampOfUpdate() + c; - continue; - } - if (field == "device") - { - s += t->about.device + c; - continue; - } - if (field == "rssi_dbm") - { - s += to_string(t->about.rssi_dbm) + c; - continue; - } + *buf += m->name() + c; + return true; + } + if (field == "id") + { + *buf += t->ids.back() + c; + return true; + } + if (field == "timestamp") + { + *buf += m->datetimeOfUpdateHumanReadable() + c; + return true; + } + if (field == "timestamp_lt") + { + *buf += m->datetimeOfUpdateHumanReadable() + c; + return true; + } + if (field == "timestamp_utc") + { + *buf += m->datetimeOfUpdateRobot() + c; + return true; + } + if (field == "timestamp_ut") + { + *buf += m->unixTimestampOfUpdate() + c; + return true; + } + if (field == "device") + { + *buf += t->about.device + c; + return true; + } + if (field == "rssi_dbm") + { + *buf += to_string(t->about.rssi_dbm) + c; + return true; + } - bool handled = false; - for (Print p : prints) + return false; +} + +// Is the desired field one of the meter printable fields? +bool checkPrintableField(string *buf, string field, Meter *m, Telegram *t, char c, + vector &prints, vector &cs) +{ + for (Print p : prints) + { + if (p.getValueString) { - if (p.getValueString) + // Strings are simply just print them. + if (field == p.vname) { - if (field == p.vname) - { - s += p.getValueString() + c; - handled = true; - } + *buf += p.getValueString() + c; + return true; } - else if (p.getValueDouble) + } + else if (p.getValueDouble) + { + // Doubles have to be converted into the proper unit. + string default_unit = unitToStringLowerCase(p.default_unit); + string var = p.vname+"_"+default_unit; + if (field == var) { - string default_unit = unitToStringLowerCase(p.default_unit); - string var = p.vname+"_"+default_unit; - if (field == var) + // Default unit. + *buf += valueToString(p.getValueDouble(p.default_unit), p.default_unit) + c; + return true; + } + else + { + // Added conversion unit. + Unit u = replaceWithConversionUnit(p.default_unit, cs); + if (u != p.default_unit) { - s += valueToString(p.getValueDouble(p.default_unit), p.default_unit) + c; - handled = true; - } - else - { - Unit u = replaceWithConversionUnit(p.default_unit, cs); - if (u != p.default_unit) + string unit = unitToStringLowerCase(u); + string var = p.vname+"_"+unit; + if (field == var) { - string unit = unitToStringLowerCase(u); - string var = p.vname+"_"+unit; - if (field == var) - { - s += valueToString(p.getValueDouble(u), u) + c; - handled = true; - } + *buf += valueToString(p.getValueDouble(u), u) + c; + return true; } } } } + } + + return false; +} + +// Is the desired field one of the constant fields? +bool checkConstantField(string *buf, string field, char c, vector *extra_constant_fields) +{ + // Ok, lets look for extra constant fields and print any such static information. + string v = findField(field, extra_constant_fields); + if (v != "") + { + *buf += v + c; + return true; + } + + return false; +} + + +string concatFields(Meter *m, Telegram *t, char c, vector &prints, vector &cs, bool hr, + vector *selected_fields, vector *added_fields, vector *extra_constant_fields) +{ + if (selected_fields == NULL || selected_fields->size() == 0) + { + return concatAllFields(m, t, c, prints, cs, hr, added_fields, extra_constant_fields); + } + string buf = ""; + + for (string field : *selected_fields) + { + bool handled = checkCommonField(&buf, field, m, t, c); + if (handled) continue; + + handled = checkPrintableField(&buf, field, m, t, c, prints, cs); + if (handled) continue; + + handled = checkConstantField(&buf, field, c, extra_constant_fields); + if (handled) continue; + if (!handled) { - s += "?"+field+"?"+c; + buf += "?"+field+"?"+c; } } - if (s.back() == c) s.pop_back(); - return s; + if (buf.back() == c) buf.pop_back(); + return buf; } bool MeterCommonImplementation::handleTelegram(AboutTelegram &about, vector input_frame, bool simulated, string *ids, bool *id_match) @@ -780,8 +834,8 @@ void MeterCommonImplementation::printMeter(Telegram *t, vector *selected_fields, vector *added_fields) { - *human_readable = concatFields(this, t, '\t', prints_, conversions_, true, selected_fields, added_fields); - *fields = concatFields(this, t, separator, prints_, conversions_, false, selected_fields, added_fields); + *human_readable = concatFields(this, t, '\t', prints_, conversions_, true, selected_fields, added_fields, extra_constant_fields); + *fields = concatFields(this, t, separator, prints_, conversions_, false, selected_fields, added_fields, extra_constant_fields); string media; if (t->tpl_id_found) diff --git a/src/util.cc b/src/util.cc index 89e3e7b..a26c80c 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1374,6 +1374,11 @@ int countSetBits(int v) return n; } +bool startsWith(string &s, string &prefix) +{ + return startsWith(s, prefix.c_str()); +} + bool startsWith(string &s, const char *prefix) { size_t len = strlen(prefix); diff --git a/src/util.h b/src/util.h index 8f0b678..f4443a0 100644 --- a/src/util.h +++ b/src/util.h @@ -176,6 +176,7 @@ AccessCheck checkIfExistsAndSameGroup(std::string device); int countSetBits(int v); bool startsWith(std::string &s, const char *prefix); +bool startsWith(std::string &s, std::string &prefix); // Given alfa=beta it returns "alfa":"beta" std::string makeQuotedJson(std::string &s); diff --git a/test.sh b/test.sh index d7daeac..aa9090f 100755 --- a/test.sh +++ b/test.sh @@ -110,7 +110,7 @@ if [ "$?" != "0" ]; then RC="1"; fi if [ -x ../additional_tests.sh ] then - (cd ..; ./additional_tests.sh) + (cd ..; ./additional_tests.sh $PROG) fi echo Slower tests... diff --git a/tests/test_unix_timestamp.sh b/tests/test_unix_timestamp.sh index 43382cc..c161afb 100755 --- a/tests/test_unix_timestamp.sh +++ b/tests/test_unix_timestamp.sh @@ -14,16 +14,20 @@ cat simulations/simulation_unix_timestamp.txt | grep '^{' > $TEST/test_expected. NOW=$(date +%s) cat simulations/simulation_unix_timestamp.txt | grep '^|' | sed 's/^|//' | sed "s/UT/${NOW}/" > $TEST/test_expected.txt -$PROG --format=fields --selectfields=total_m3,timestamp_ut,name,id simulations/simulation_t1.txt $METERS > $TEST/test_output.txt 2> $TEST/test_stderr.txt +$PROG --format=fields --separator='*' --field_extra=extra_info --selectfields=total_m3,timestamp_ut,timestamp_utc,timestamp_lt,name,id,extra simulations/simulation_t1.txt $METERS > $TEST/test_output.txt 2> $TEST/test_stderr.txt if [ "$?" = "0" ] then - cat $TEST/test_output.txt | sed 's/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9].[0-9][0-9]$/1111-11-11 11:11.11/' > $TEST/test_responses.txt + cat $TEST/test_output.txt | \ + sed 's/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9].[0-9][0-9]/1111-11-11 11:11.11/g' | \ + sed 's/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9].[0-9][0-9]Z/1111-11-11T11:11.11Z/g' \ + > $TEST/test_responses.txt diff $TEST/test_expected.txt $TEST/test_responses.txt if [ "$?" = "0" ] then echo OK fields: $TESTNAME TESTRESULT="OK" else + meld $TEST/test_expected.txt $TEST/test_responses.txt TESTRESULT="ERROR" fi else