Add support for the same fully specified secondary address printed by libmbus after doing a bus scan.

pull/1227/head
Fredrik Öhrström 2024-03-28 12:40:50 +01:00
rodzic 9a34a55abb
commit 9facddf019
9 zmienionych plików z 139 dodań i 30 usunięć

Wyświetl plik

@ -251,7 +251,9 @@ which will match all meter ids, except those that begin with 2222.
You can also specify the exact manufacturer, version and type: `id=11111111.M=KAM.V=1b.T=16`
or a subset: `id=11111111.T=16` or all telegrams from 22222222 except those with version 77:
`id=22222222,!22222222.V=77`
`id=22222222,!22222222.V=77` You can also use the fully specified secondary address that is
printed by libmbus after doing a bus scan, ie `100002842941011B` which is equivalent to
`10000284.M=PII.V=01.T=1B`
When matching all meters from the command line you can use `ANYID` instead of `*` to avoid shell quotes.

Wyświetl plik

@ -45,6 +45,8 @@ bool isValidMatchExpression(const string& s, bool *has_wildcard)
// !12345677
// 2222222*
// !22222222
// We also accept an secondary libmbus address:
// 100002842941011B
// A match expression cannot be empty.
if (me.length() == 0) return false;
@ -64,12 +66,22 @@ bool isValidMatchExpression(const string& s, bool *has_wildcard)
// We accept hex anyway.
while (me.length() > 0 &&
((me.front() >= '0' && me.front() <= '9') ||
(me.front() >= 'A' && me.front() <= 'F') ||
(me.front() >= 'a' && me.front() <= 'f')))
{
me.erase(0,1);
count++;
}
if (me.length() == 0 && count == 16)
{
// A secondary libmbus address: 100002842941011B
// Strictly speaking the leading 8 digits should be bcd,
// but we accept hex as well.
*has_wildcard = false;
return true;
}
bool wildcard_used = false;
// An expression can end with a *
if (me.length() > 0 && me.front() == '*')
@ -243,6 +255,8 @@ bool AddressExpression::parse(const string &in)
// or 250.MPII.V01.T1B // mbus primary
// or !12345678
// or !*.M=ABC
// or libmbus secondary style:
// 123456782941011B
id = "";
mbus_primary = false;
mfct = 0xffff;
@ -280,6 +294,35 @@ bool AddressExpression::parse(const string &in)
mbus_primary = true;
}
if (parts.size() == 1 && id.length() == 16)
{
// This is a secondary libmbus address.
string mfct_hex = id.substr(8,4);
string version_hex = id.substr(12,2);
string type_hex = id.substr(14,2);
id = id.substr(0,8);
vector<uchar> data;
bool ok = hex2bin(mfct_hex.c_str(), &data);
if (!ok) return false;
if (data.size() != 2) return false;
mfct = data[1] << 8 | data[0];
data.clear();
ok = hex2bin(version_hex.c_str(), &data);
if (!ok) return false;
if (data.size() != 1) return false;
version = data[0];
data.clear();
ok = hex2bin(type_hex.c_str(), &data);
if (!ok) return false;
if (data.size() != 1) return false;
type = data[0];
return true;
}
for (size_t i=1; i<parts.size(); ++i)
{
if (parts[i].size() == 4) // V=xy or T=xy

Wyświetl plik

@ -741,10 +741,21 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
string key = argv[m*4+i+3];
MeterInfo mi;
if (!isValidSequenceOfAddressExpressions(address_expressions))
{
error("Not a valid meter id nor a valid sequence of match expression \"%s\"\n", address_expressions.c_str());
}
mi.parse(name, driver, address_expressions, key);
mi.poll_interval = c->pollinterval;
mi.identity_mode = c->identity_mode;
if (!isValidKey(key, mi))
{
error("Not a valid meter key \"%s\"\n", key.c_str());
}
if (mi.driver_name.str() == "")
{
error("Not a valid meter driver \"%s\"\n", driver.c_str());

Wyświetl plik

@ -186,18 +186,22 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
MeterInfo mi;
if (!isValidSequenceOfAddressExpressions(address_expressions))
{
warning("In config, not a valid meter id nor a valid sequence of match expression \"%s\"\n", address_expressions.c_str());
use = false;
}
mi.parse(name, driver, address_expressions, key); // sets driver, extras, name, bus, bps, link_modes, ids, name, key
mi.poll_interval = poll_interval;
mi.identity_mode = identity_mode;
if (!isValidSequenceOfAddressExpressions(address_expressions)) {
warning("Not a valid meter id nor a valid sequence of match expression \"%s\"\n", address_expressions.c_str());
use = false;
}
if (!isValidKey(key, mi)) {
warning("Not a valid meter key \"%s\"\n", key.c_str());
if (!isValidKey(key, mi))
{
warning("In config, not a valid meter key in config \"%s\"\n", key.c_str());
use = false;
}
if (use)
{
mi.extra_constant_fields = extra_constant_fields;

Wyświetl plik

@ -678,10 +678,16 @@ void MeterCommonImplementation::poll(shared_ptr<BusManager> bus_manager)
return;
}
if (addressExpressions().size() == 0)
{
warning("(meter) not polling from \"%s\" since no valid id\n", name().c_str());
return;
}
AddressExpression &ae = addressExpressions().back();
if (ae.has_wildcard)
{
debug("(meter) not polling from id \"%s\" since poll id must not have a wildcard\n", ae.id.c_str());
warning("(meter) not polling from id \"%s\" since poll id must not have a wildcard\n", ae.id.c_str());
return;
}
@ -691,7 +697,7 @@ void MeterCommonImplementation::poll(shared_ptr<BusManager> bus_manager)
if (idnum < 0 || idnum > 250)
{
debug("(meter) not polling from bad id \"%s\"\n", ae.id.c_str());
warning("(meter) not polling from bad id \"%s\"\n", ae.id.c_str());
return;
}
@ -721,7 +727,7 @@ void MeterCommonImplementation::poll(shared_ptr<BusManager> bus_manager)
if (!ok || idhex.size() != 4)
{
debug("(meter) not polling from bad id \"%s\"\n", ae.id.c_str());
warning("(meter) not polling from bad id \"%s\"\n", ae.id.c_str());
return;
}
@ -739,8 +745,8 @@ void MeterCommonImplementation::poll(shared_ptr<BusManager> bus_manager)
buf[8] = idhex[2]; // id 56
buf[9] = idhex[1]; // id 34
buf[10] = idhex[0]; // id 12
buf[11] = (ae.mfct >> 8) & 0xff; // use 0xff as a wildcard
buf[12] = ae.mfct & 0xff; // mfct
buf[11] = ae.mfct & 0xff; // mfct
buf[12] = (ae.mfct >> 8) & 0xff; // use 0xff as a wildcard
buf[13] = ae.version; // version/generation
buf[14] = ae.type; // type/media/device

Wyświetl plik

@ -36,6 +36,9 @@ if [ "$?" != "0" ]; then RC="1"; fi
tests/test_mbus.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi
tests/test_libmbus_secondary_address.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi
tests/test_anyid.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi

Wyświetl plik

@ -44,7 +44,7 @@ A driver file looks like this: driver { name = abc123 ... }
Failed to load driver from file: testoutput/driver.xmq
EOF
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -62,7 +62,7 @@ The driver name must consist of lower case ascii a-z and digits 0-9.
Failed to load driver from file: testoutput/driver.xmq
EOF
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -93,7 +93,7 @@ WaterMeter
Failed to load driver from file: testoutput/driver.xmq
EOF
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -123,7 +123,7 @@ WaterMeter
Failed to load driver from file: testoutput/driver.xmq
EOF
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -142,7 +142,7 @@ Where you change total_m3 to your meters most important field.
Failed to load driver from file: testoutput/driver.xmq
EOF
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -164,7 +164,7 @@ or as 4 lower case hex digits.
Failed to load driver from file: testoutput/driver.xmq
EOF
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -192,7 +192,7 @@ or as 4 lower case hex digits.
Failed to load driver from file: testoutput/driver.xmq
EOF
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -213,7 +213,7 @@ Remember to add for example: field { name = total ... }
Hej;?total_m3?
EOF
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -235,7 +235,7 @@ Either indirectly based on the quantity or directly based on the display_unit.
Hej;?total_m3?
EOF
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -279,7 +279,7 @@ Dimensionless
Hej;?total_m3?
EOF
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -322,7 +322,7 @@ Dimensionless
Hej;?total_m3?
EOF
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -340,7 +340,7 @@ cat > $TEST/test_expected.txt <<EOF
Hej;null
EOF
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=fields --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -357,7 +357,7 @@ cat > $TEST/test_expected.txt <<EOF
Hej 4712.13 m³
EOF
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -384,7 +384,7 @@ Any
Hej ?total_m3?
EOF
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -410,7 +410,7 @@ Any
Hej ?total_m3?
EOF
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -477,7 +477,7 @@ AnyPowerVIF
Hej ?total_m3?
EOF
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck
@ -494,6 +494,6 @@ cat > $TEST/test_expected.txt <<EOF
Hej 123.529 m³
EOF
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1 || true
$PROG --format=hr --selectfields=name,total_m3 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1 || true
performCheck

Wyświetl plik

@ -0,0 +1,40 @@
#!/bin/sh
PROG="$1"
mkdir -p testoutput
TEST=testoutput
########################################################
TESTNAME="Using libmbus secondary address fully specified format"
TESTRESULT="ERROR"
OUT=$($PROG --pollinterval=1s --format=fields --selectfields=temperature_c 68383868080072840200102941011B0D0000000265FE0842653009820165E70802FB1A480142FB1A45018201FB1A4E010C788402001002FD0F21000F0316 MyTempMeter piigth 100002842941011B NOKEY)
if [ "$OUT" != "23.02" ]
then
echo "ERROR: Test 1 $TESTNAME"
echo "Expected answer 23.02"
exit 1
fi
OUT=$($PROG --pollinterval=1s --format=fields --selectfields=temperature_c 68383868080072840200102941011B0D0000000265FE0842653009820165E70802FB1A480142FB1A45018201FB1A4E010C788402001002FD0F21000F0316 MyTempMeter piigth 10000284.M=PII.V=01.T=1B NOKEY)
if [ "$OUT" != "23.02" ]
then
echo "ERROR: Test 2 $TESTNAME"
echo "Expected answer 23.02"
exit 1
fi
OUT=$($PROG --pollinterval=1s --format=fields --selectfields=temperature_c 68383868080072840200102941011B0D0000000265FE0842653009820165E70802FB1A480142FB1A45018201FB1A4E010C788402001002FD0F21000F0316 MyTempMeter piigth 100002842941011C NOKEY)
if [ "$OUT" != "" ]
then
echo "ERROR: Test 3 $TESTNAME"
echo "Did not expect answer! $OUT"
exit 1
fi
echo "OK: $TESTNAME"

Wyświetl plik

@ -69,6 +69,6 @@ cat > $TEST/test_expected.txt <<EOF
{"media":"water","meter":"iporl","name":"Hej","id":"33225544","max_flowwor_m3h":0,"totalitator_m3":123.529,"timestamp":"1111-11-11T11:11:11Z"}
EOF
$PROG --format=json 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NO_KEY > $TEST/test_output.txt 2>&1
$PROG --format=json 1844AE4C4455223399077A55000000_041389E20100023B0000 Hej $TEST/driver.xmq 33225544 NOKEY > $TEST/test_output.txt 2>&1
performCheck