kopia lustrzana https://github.com/weetmuts/wmbusmeters
Add support for the same fully specified secondary address printed by libmbus after doing a bus scan.
rodzic
9a34a55abb
commit
9facddf019
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
3
test.sh
3
test.sh
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue