From 8c09f7b2d868498b1b23ca7e82aa0050ae8f3ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Sun, 3 Mar 2024 19:34:00 +0100 Subject: [PATCH] The required field does not contribute to testing of the address expressions before. --- README.md | 26 ++++++++++++--- simulations/simulation_qheat_bad.txt | 4 +++ src/address.cc | 48 +++++++++++++++++----------- src/meters.cc | 7 ++-- test.sh | 6 ++++ tests/test_address_dll.sh | 47 +++++++++++++++++++++++++++ tests/test_address_filtering.sh | 28 ++++++++++++++++ 7 files changed, 142 insertions(+), 24 deletions(-) create mode 100644 simulations/simulation_qheat_bad.txt create mode 100755 tests/test_address_dll.sh create mode 100755 tests/test_address_filtering.sh diff --git a/README.md b/README.md index 982bf03..80769d4 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,33 @@ log file. Wmbusmeters converts incoming telegrams from (w)mbus/OMS compatible meters like: `2A442D2C998734761B168D2091D37CAC21576C78_02FF207100041308190000441308190000615B7F616713` -into human readable tab separated fields: -`MyTapWater 12345678 6.388 m3 6.377 m3 0.000 m3/h 8°C 23°C DRY(dry 22-31 days) 2018-03-05 12:02.50` +into human readable: +`MyTapWater 12345678 6.388 m³ 6.377 m³ 0.000 m³/h 8°C 23°C DRY(dry 22-31 days) 2018-03-05 12:02.50` -or into computer readable fields: +or into csv: `MyTapWater;12345678;6.388;6.377;0.000;8;23;DRY(dry 22-31 days);2018-03-05 12:02.50` or into json: ```json -{"media":"cold water","meter":"multical21","name":"MyTapWater","id":"12345678","total_m3":6.388,"target_m3":6.377,"max_flow_m3h":0.000,"flow_temperature":8,"external_temperature":23,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"2018-02-08T09:07:22Z","device":"im871a[1234567]","rssi_dbm":-40} +{ + "media":"cold water", + "meter":"multical21", + "name":"MyTapWater", + "id":"12345678", + "total_m3":6.388, + "target_m3":6.377, + "max_flow_m3h":0.000, + "flow_temperature":8, + "external_temperature":23, + "current_status":"DRY", + "time_dry":"22-31 days", + "time_reversed":"", + "time_leaking":"", + "time_bursting":"", + "timestamp":"2018-02-08T09:07:22Z", + "device":"im871a[1234567]", + "rssi_dbm":-40 +} ``` Wmbusmeters can collect telegrams from radio using hardware dongles or rtl-sdr software radio dongles, diff --git a/simulations/simulation_qheat_bad.txt b/simulations/simulation_qheat_bad.txt new file mode 100644 index 0000000..f7a1c34 --- /dev/null +++ b/simulations/simulation_qheat_bad.txt @@ -0,0 +1,4 @@ +telegram=|414493447514916746377275149167934446044D000020_0C06490000004C0600000000426CFF2CCC080611000000C2086C1F3102FD170000326CFFFF046D330F1432| +telegram=|5b44934475149167463778077975149167934446040dff5f3500823d0000810007c006ffff49000000ff2c000000001f3111000000008000800080008000800080008000800080000000000B002f02fd170000046d390d1432488408| +telegram=|414493447514916746377275149167934446044D000020_0C06490000004C0600000000426CFF2CCC080611000000C2086C1F3102FD170000326CFFFF046D330F1432| +telegram=|5b44934475149167463778077975149167934446040dff5f3500823d0000810007c006ffff49000000ff2c000000001f3111000000008000800080008000800080008000800080000000000B002f02fd170000046d390d1432488408| diff --git a/src/address.cc b/src/address.cc index e666532..9ae39d0 100644 --- a/src/address.cc +++ b/src/address.cc @@ -30,7 +30,9 @@ bool doesIdMatchExpression(const std::string& id, std::string match_rule); bool doesAddressMatchExpressions(Address &address, std::vector& address_expressions, bool *used_wildcard, - bool *filtered_out); + bool *filtered_out, + bool *required_found, + bool *required_failed); bool isValidMatchExpression(const string& s, bool *has_wildcard) { @@ -348,6 +350,7 @@ string AddressExpression::str() string s; if (filter_out) s = "!"; + if (required) s = "R"; s.append(id); if (mfct != 0xffff) @@ -443,9 +446,17 @@ bool doesTelegramMatchExpressions(std::vector
&addresses, { bool match = false; bool filtered_out = false; + bool required_found = false; // An R12345678 field was found. + bool required_failed = true; // Init to fail, set to true if R is satistifed anywhere. + for (Address &a : addresses) { - if (doesAddressMatchExpressions(a, address_expressions, used_wildcard, &filtered_out)) + if (doesAddressMatchExpressions(a, + address_expressions, + used_wildcard, + &filtered_out, + &required_found, + &required_failed)) { match = true; } @@ -454,18 +465,21 @@ bool doesTelegramMatchExpressions(std::vector
&addresses, } // If any expression triggered a filter out, then the whole telegram does not match. if (filtered_out) match = false; + // If a required field was found and it failed.... + if (required_found && required_failed) match = false; return match; } bool doesAddressMatchExpressions(Address &address, vector& address_expressions, bool *used_wildcard, - bool *filtered_out) + bool *filtered_out, + bool *required_found, + bool *required_failed) { bool found_match = false; bool found_negative_match = false; bool exact_match = false; - bool failed_required_match = false; // Goes through all possible match expressions. // If no expression matches, neither positive nor negative, @@ -485,8 +499,11 @@ bool doesAddressMatchExpressions(Address &address, { bool has_wildcard = ae.has_wildcard; bool is_negative_rule = ae.filter_out; + // We currently assume that only a single expression is required, the last one! bool is_required = ae.required; + if (is_required) *required_found = true; + bool m = ae.match(address.id, address.mfct, address.version, address.type); if (is_negative_rule) @@ -497,27 +514,22 @@ bool doesAddressMatchExpressions(Address &address, { if (m) { - found_match = true; - if (!has_wildcard) + // A match, but the required does not count. + if (!is_required) { - exact_match = true; + found_match = true; + if (!has_wildcard) + { + exact_match = true; + } } - } - else - { - // No match - if (is_required) + else { - // Oups! A required match! - failed_required_match = true; + *required_failed = false; } } } } - if (failed_required_match) - { - return false; - } if (found_negative_match) { *filtered_out = true; diff --git a/src/meters.cc b/src/meters.cc index a3f15e1..d455f38 100644 --- a/src/meters.cc +++ b/src/meters.cc @@ -938,9 +938,12 @@ bool MeterCommonImplementation::isTelegramForMeter(Telegram *t, Meter *meter, Me } bool used_wildcard = false; - bool match = doesTelegramMatchExpressions(t->addresses, address_expressions, &used_wildcard); + bool match = doesTelegramMatchExpressions(t->addresses, + address_expressions, + &used_wildcard); - if (!match) { + if (!match) + { // The id must match. debug("(meter) %s: not for me: no match\n", name.c_str()); return false; diff --git a/test.sh b/test.sh index 22f5e7c..bb41a1c 100755 --- a/test.sh +++ b/test.sh @@ -126,6 +126,12 @@ if [ "$?" != "0" ]; then RC="1"; fi tests/test_addresses.sh $PROG if [ "$?" != "0" ]; then RC="1"; fi +tests/test_address_filtering.sh $PROG +if [ "$?" != "0" ]; then RC="1"; fi + +tests/test_address_dll.sh $PROG +if [ "$?" != "0" ]; then RC="1"; fi + tests/test_identity_mode.sh $PROG if [ "$?" != "0" ]; then RC="1"; fi diff --git a/tests/test_address_dll.sh b/tests/test_address_dll.sh new file mode 100755 index 0000000..d88bf3d --- /dev/null +++ b/tests/test_address_dll.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +PROG="$1" + +mkdir -p testoutput +TEST=testoutput + +TESTNAME="Test addresses dll" +TESTRESULT="OK" + +# Test that selecting the meter using the dll id instead of the tpl id works. +OUT=$($PROG --format=fields --selectfields=total_m3 6644496A1064035514377251345015496A0007EE0050052F2F_0C1359000000026CBE2B82046CA12B8C0413FFFFFFFF8D0493132CFBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02FD1700002F2F W minomess 55036410 NOKEY) + +if [ "$OUT" != "0.059" ] +then + echo "ERROR: Test addresses dll failed" +else + echo "OK: Test addresses dll" +fi + +# Test that selecting the meter using the tpl id instead of the dll id works. +OUT=$($PROG --format=fields --selectfields=total_m3 6644496A1064035514377251345015496A0007EE0050052F2F_0C1359000000026CBE2B82046CA12B8C0413FFFFFFFF8D0493132CFBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02FD1700002F2F W minomess 15503451 NOKEY) + +if [ "$OUT" != "0.059" ] +then + echo "ERROR: Test addresses tpl failed" +else + echo "OK: Test addresses tpl" +fi + +OUT=$($PROG --format=fields --selectfields=total_m3 6644496A1064035514377251345015496A0007EE0050052F2F_0C1359000000026CBE2B82046CA12B8C0413FFFFFFFF8D0493132CFBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02FD1700002F2F W minomess '*.T=07' NOKEY) + +if [ "$OUT" != "0.059" ] +then + echo "ERROR: Test addresses *.T=07 failed" +else + echo "OK: Test addresses *.T=07" +fi + +OUT=$($PROG --format=fields --selectfields=total_m3 6644496A1064035514377251345015496A0007EE0050052F2F_0C1359000000026CBE2B82046CA12B8C0413FFFFFFFF8D0493132CFBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02FD1700002F2F W minomess '*.T=37' NOKEY) + +if [ "$OUT" != "0.059" ] +then + echo "ERROR: Test addresses *.T=37 failed" +else + echo "OK: Test addresses *.T=37" +fi diff --git a/tests/test_address_filtering.sh b/tests/test_address_filtering.sh new file mode 100755 index 0000000..cc01c91 --- /dev/null +++ b/tests/test_address_filtering.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +PROG="$1" + +mkdir -p testoutput +TEST=testoutput + +TESTNAME="Test address type filtering" +TESTRESULT="OK" + +$PROG --format=fields simulations/simulation_qheat_bad.txt HEAT qheat '67911475.T=04' NOKEY > $TEST/test_output.txt 2>&1 + +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_expected.txt <