diff --git a/simulations/serial_rtlwmbus_with_timestamps.msg b/simulations/serial_rtlwmbus_with_timestamps.msg new file mode 100644 index 0000000..465eae7 --- /dev/null +++ b/simulations/serial_rtlwmbus_with_timestamps.msg @@ -0,0 +1,5 @@ +T1;1;1;2019-04-03 19:10:42.000;97;148;77777777;0x5744b40988227711101b7ab20800000265a00842658f088201659f08226589081265a0086265510852652b0902fb1aba0142fb1ab0018201fb1abd0122fb1aa90112fb1aba0162fb1aa60152fb1af501066d3b3bb36b2a00 +#2019-04-03T19:10:42Z +T1;0;0;2021-12-29 13:50:57.000;11;108;99999999;0x294468505953629176f0a0009f29982b00e0982b00802e0601316acd636bcd63008dc3009ed4000fe5ff +T1;1;1;2019-04-03 19:00:42.000;97;148;88888888;0x2e44333003020100071b7a634820252f2f0265840842658308820165950802fb1aae0142fb1aae018201fb1aa9012f +#2019-04-03T19:00:42Z diff --git a/src/meters.cc b/src/meters.cc index a1891f4..74240b7 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -630,7 +630,7 @@ void MeterCommonImplementation::poll(shared_ptr bus_manager) if (pollInterval() <= 0) return; time_t now = time(NULL); - time_t next_poll_time = timestampLastUpdate()+pollInterval(); + time_t next_poll_time = datetime_of_poll_+pollInterval(); if (now < next_poll_time) { // Not yet time to poll this meter. @@ -979,7 +979,8 @@ void MeterCommonImplementation::triggerUpdate(Telegram *t) // Check if processContent has discarded this telegram. if (t->discard) return; - datetime_of_update_ = time(NULL); + datetime_of_poll_ = time(NULL); + datetime_of_update_ = t->about.timestamp ? t->about.timestamp : datetime_of_poll_; num_updates_++; for (auto &cb : on_update_) if (cb) cb(t, this); t->handled = true; diff --git a/src/meters_common_implementation.h b/src/meters_common_implementation.h index 629e30f..42a8b83 100644 --- a/src/meters_common_implementation.h +++ b/src/meters_common_implementation.h @@ -266,6 +266,7 @@ private: vector> on_update_; int num_updates_ {}; time_t datetime_of_update_ {}; + time_t datetime_of_poll_ {}; LinkModeSet link_modes_ {}; vector shell_cmdlines_; vector extra_constant_fields_; diff --git a/src/wmbus.h b/src/wmbus.h index c22f5f8..e156abd 100644 --- a/src/wmbus.h +++ b/src/wmbus.h @@ -366,8 +366,10 @@ struct AboutTelegram int rssi_dbm {}; // WMBus or MBus FrameType type {}; + // time the telegram was received + time_t timestamp; - AboutTelegram(string dv, int rs, FrameType t) : device(dv), rssi_dbm(rs), type(t) {} + AboutTelegram(string dv, int rs, FrameType t, time_t ts = 0) : device(dv), rssi_dbm(rs), type(t), timestamp(ts) {} AboutTelegram() {} }; diff --git a/src/wmbus_rtlwmbus.cc b/src/wmbus_rtlwmbus.cc index 6b194b7..2ad576f 100644 --- a/src/wmbus_rtlwmbus.cc +++ b/src/wmbus_rtlwmbus.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include using namespace std; @@ -75,7 +76,8 @@ private: size_t *hex_frame_length, int *hex_payload_len_out, int *hex_payload_offset, - double *rssi); + double *rssi, + struct tm *timestamp); void handleMessage(vector &frame); string setup_; @@ -239,11 +241,12 @@ void WMBusRTLWMBUS::processSerialData() size_t frame_length; int hex_payload_len, hex_payload_offset; + struct tm timestamp; for (;;) { double rssi = 0; - FrameStatus status = checkRTLWMBUSFrame(read_buffer_, &frame_length, &hex_payload_len, &hex_payload_offset, &rssi); + FrameStatus status = checkRTLWMBUSFrame(read_buffer_, &frame_length, &hex_payload_len, &hex_payload_offset, &rssi, ×tamp); if (status == PartialFrame) { @@ -298,7 +301,7 @@ void WMBusRTLWMBUS::processSerialData() } string id = string("rtlwmbus[")+getDeviceId()+"]"; - AboutTelegram about(id, rssi, FrameType::WMBUS); + AboutTelegram about(id, rssi, FrameType::WMBUS, timestamp.tm_mday ? timegm(×tamp) : 0); handleTelegram(about, payload); } else @@ -312,7 +315,8 @@ FrameStatus WMBusRTLWMBUS::checkRTLWMBUSFrame(vector &data, size_t *hex_frame_length, int *hex_payload_len_out, int *hex_payload_offset, - double *rssi) + double *rssi, + struct tm *timestamp) { // C1;1;1;2019-02-09 07:14:18.000;117;102;94740459;0x49449344590474943508780dff5f3500827f0000f10007b06effff530100005f2c620100007f2118010000008000800080008000000000000000000e003f005500d4ff2f046d10086922 // There might be a second telegram on the same line ;0x4944....... @@ -374,9 +378,15 @@ FrameStatus WMBusRTLWMBUS::checkRTLWMBUSFrame(vector &data, } size_t i = 0; int count = 0; - // Look for packet rssi + *timestamp = { 0 }; + // Look for packet timestamp and rssi for (; i+1 < data.size(); ++i) { - if (data[i] == ';') count++; + if (data[i] != ';') continue; + count++; + if (count == 3 && !strptime((const char*)&data[i+1], "%Y-%m-%d %H:%M:%S", timestamp)) { + debug("(rtlwmbus) invalid timestamp\n"); + return ErrorInFrame; + } if (count == 4) break; } if (count == 4) diff --git a/test.sh b/test.sh index 717ce0c..267a5b4 100755 --- a/test.sh +++ b/test.sh @@ -160,6 +160,9 @@ if [ "$?" != "0" ]; then RC="1"; fi ./tests/test_rtlwmbus_crc_errors.sh $PROG if [ "$?" != "0" ]; then RC="1"; fi +./tests/test_rtlwmbus_timestamps.sh $PROG +if [ "$?" != "0" ]; then RC="1"; fi + ./tests/test_drivers.sh $PROG if [ "$?" != "0" ]; then RC="1"; fi diff --git a/tests/test_rtlwmbus_timestamps.sh b/tests/test_rtlwmbus_timestamps.sh new file mode 100755 index 0000000..81394f4 --- /dev/null +++ b/tests/test_rtlwmbus_timestamps.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +PROG="$1" + +TEST=testoutput + +rm -rf $TEST +mkdir -p $TEST + +TESTNAME="Test timestamps from rtlwmbus" +TESTRESULT="ERROR" + +cat simulations/serial_rtlwmbus_with_timestamps.msg | grep '^\#' | tr -d '#' > $TEST/test_expected.txt +cat simulations/serial_rtlwmbus_with_timestamps.msg | grep '^[CT]' > $TEST/test_input.txt +cat $TEST/test_input.txt | $PROG --format=json "stdin:rtlwmbus" \ + Rummet1 lansenth 00010203 "" \ + Rummet2 rfmamb 11772288 "" \ + 2> $TEST/test_stderr.txt | jq -r .timestamp > $TEST/test_output.txt + +diff $TEST/test_expected.txt $TEST/test_output.txt +if [ "$?" = "0" ] +then + echo "OK: $TESTNAME" + TESTRESULT="OK" +else + if [ "$USE_MELD" = "true" ] + then + meld $TEST/test_expected.txt $TEST/test_output.txt + fi +fi + +if [ "$TESTRESULT" = "ERROR" ]; then echo ERROR: $TESTNAME; exit 1; fi