kopia lustrzana https://github.com/weetmuts/wmbusmeters
Handle more address rules.
rodzic
11c83c1f37
commit
5962e727ff
|
@ -27,7 +27,8 @@ bool isValidMatchExpression(const std::string& s, bool *has_wildcard);
|
|||
bool doesIdMatchExpression(const std::string& id, std::string match_rule);
|
||||
bool doesAddressMatchExpressions(Address &address,
|
||||
std::vector<AddressExpression>& address_expressions,
|
||||
bool *used_wildcard);
|
||||
bool *used_wildcard,
|
||||
bool *filtered_out);
|
||||
|
||||
bool isValidMatchExpression(const string& s, bool *has_wildcard)
|
||||
{
|
||||
|
@ -94,7 +95,7 @@ vector<string> splitSequenceOfAddressExpressionsAtCommas(const string& mes)
|
|||
auto i = v.begin();
|
||||
|
||||
for (;;) {
|
||||
auto id = eatTo(v, i, ',', 16, &eof, &err);
|
||||
auto id = eatTo(v, i, ',', 64, &eof, &err);
|
||||
if (err) break;
|
||||
trimWhitespace(&id);
|
||||
if (id == "ANYID") id = "*";
|
||||
|
@ -277,6 +278,19 @@ bool AddressExpression::parse(const string &in)
|
|||
bool ok = flagToManufacturer(&parts[i][2], &mfct);
|
||||
if (!ok) return false;
|
||||
}
|
||||
else if (parts[i].size() == 6) // M=abcd explicit hex version
|
||||
{
|
||||
if (parts[i][1] != '=') return false;
|
||||
if (parts[i][0] != 'M') return false;
|
||||
|
||||
vector<uchar> data;
|
||||
bool ok = hex2bin(&parts[i][2], &data);
|
||||
if (!ok) return false;
|
||||
if (data.size() != 2) return false;
|
||||
|
||||
mfct = data[1] << 8 | data[0];
|
||||
if (!ok) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
|
@ -396,21 +410,25 @@ bool doesTelegramMatchExpressions(std::vector<Address> &addresses,
|
|||
bool *used_wildcard)
|
||||
{
|
||||
bool match = false;
|
||||
bool filtered_out = false;
|
||||
for (Address &a : addresses)
|
||||
{
|
||||
if (doesAddressMatchExpressions(a, address_expressions, used_wildcard))
|
||||
if (doesAddressMatchExpressions(a, address_expressions, used_wildcard, &filtered_out))
|
||||
{
|
||||
match = true;
|
||||
}
|
||||
// Go through all ids even though there is an early match.
|
||||
// This way we can see if theres an exact match later.
|
||||
}
|
||||
// If any expression triggered a filter out, then the whole telegram does not match.
|
||||
if (filtered_out) match = false;
|
||||
return match;
|
||||
}
|
||||
|
||||
bool doesAddressMatchExpressions(Address &address,
|
||||
vector<AddressExpression>& address_expressions,
|
||||
bool *used_wildcard)
|
||||
bool *used_wildcard,
|
||||
bool *filtered_out)
|
||||
{
|
||||
bool found_match = false;
|
||||
bool found_negative_match = false;
|
||||
|
@ -433,7 +451,7 @@ bool doesAddressMatchExpressions(Address &address,
|
|||
bool has_wildcard = ae.has_wildcard;
|
||||
bool is_negative_rule = ae.filter_out;
|
||||
|
||||
bool m = doesIdMatchExpression(address.id, ae.id);
|
||||
bool m = ae.match(address.id, address.mfct, address.version, address.type);
|
||||
|
||||
if (is_negative_rule)
|
||||
{
|
||||
|
@ -453,6 +471,7 @@ bool doesAddressMatchExpressions(Address &address,
|
|||
}
|
||||
if (found_negative_match)
|
||||
{
|
||||
*filtered_out = true;
|
||||
return false;
|
||||
}
|
||||
if (found_match)
|
||||
|
|
|
@ -728,11 +728,11 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
|
|||
string bus;
|
||||
string name = argv[m*4+i+0];
|
||||
string driver = argv[m*4+i+1];
|
||||
string id = argv[m*4+i+2];
|
||||
string address_expressions = argv[m*4+i+2];
|
||||
string key = argv[m*4+i+3];
|
||||
|
||||
MeterInfo mi;
|
||||
mi.parse(name, driver, id, key);
|
||||
mi.parse(name, driver, address_expressions, key);
|
||||
mi.poll_interval = c->pollinterval;
|
||||
|
||||
if (mi.driver_name.str() == "")
|
||||
|
|
|
@ -53,7 +53,7 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
|
|||
string bus;
|
||||
string name;
|
||||
string driver = "auto";
|
||||
string id;
|
||||
string address_expressions;
|
||||
string key = "";
|
||||
string linkmodes;
|
||||
int poll_interval = 0;
|
||||
|
@ -108,7 +108,7 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
|
|||
else
|
||||
if (p.first == "driver") driver = p.second;
|
||||
else
|
||||
if (p.first == "id") id = p.second;
|
||||
if (p.first == "id") address_expressions = p.second;
|
||||
else
|
||||
if (p.first == "key")
|
||||
{
|
||||
|
@ -176,11 +176,11 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
|
|||
|
||||
MeterInfo mi;
|
||||
|
||||
mi.parse(name, driver, id, key); // sets driver, extras, name, bus, bps, link_modes, ids, name, key
|
||||
mi.parse(name, driver, address_expressions, key); // sets driver, extras, name, bus, bps, link_modes, ids, name, key
|
||||
mi.poll_interval = poll_interval;
|
||||
|
||||
if (!isValidSequenceOfAddressExpressions(id)) {
|
||||
warning("Not a valid meter id nor a valid sequence of match expression \"%s\"\n", id.c_str());
|
||||
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)) {
|
||||
|
|
|
@ -403,6 +403,14 @@ void log_start_information(Configuration *config)
|
|||
verbose("(config) using device: %s \n", specified_device.str().c_str());
|
||||
}
|
||||
verbose("(config) number of meters: %d\n", config->meters.size());
|
||||
if (isDebugEnabled())
|
||||
{
|
||||
for (MeterInfo &m : config->meters)
|
||||
{
|
||||
string aes = AddressExpression::concat(m.address_expressions);
|
||||
debug("(config) template %s %s %s\n", m.name.c_str(), aes.c_str(), m.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void oneshot_check(Configuration *config, Telegram *t, Meter *meter)
|
||||
|
|
|
@ -187,6 +187,7 @@ public:
|
|||
aes.push_back(AddressExpression(t.addresses.back()));
|
||||
meter_info.address_expressions = aes;
|
||||
|
||||
// Overwrite the mfct,version and type.
|
||||
if (meter_info.driverName().str() == "auto")
|
||||
{
|
||||
// Look up the proper meter driver!
|
||||
|
|
|
@ -575,6 +575,42 @@ void tst_address_match(string expr, string id, uint16_t m, uchar v, uchar t, boo
|
|||
}
|
||||
}
|
||||
|
||||
void tst_telegram_match(string addresses, string expressions, bool match, bool uw)
|
||||
{
|
||||
vector<AddressExpression> exprs = splitAddressExpressions(expressions);
|
||||
vector<AddressExpression> as = splitAddressExpressions(addresses);
|
||||
vector<Address> addrs;
|
||||
|
||||
for (auto &ad : as)
|
||||
{
|
||||
Address a;
|
||||
a.id = ad.id;
|
||||
a.mfct = ad.mfct;
|
||||
a.version = ad.version;
|
||||
a.type = ad.type;
|
||||
|
||||
addrs.push_back(a);
|
||||
}
|
||||
|
||||
bool used_wildcard = false;
|
||||
bool m = doesTelegramMatchExpressions(addrs, exprs, &used_wildcard);
|
||||
|
||||
if (m != match)
|
||||
{
|
||||
printf("Expected addresses %s to %smatch expressions %s\n",
|
||||
addresses.c_str(),
|
||||
match?"":"NOT ",
|
||||
expressions.c_str());
|
||||
}
|
||||
if (uw != used_wildcard)
|
||||
{
|
||||
printf("Expected addresses %s from match expression %s %susing wildcard\n",
|
||||
addresses.c_str(),
|
||||
expressions.c_str(),
|
||||
uw?"":"NOT ");
|
||||
}
|
||||
}
|
||||
|
||||
void test_addresses()
|
||||
{
|
||||
tst_address("12345678",
|
||||
|
@ -634,6 +670,33 @@ void test_addresses()
|
|||
tst_address_match("!9*.V=06", "89999999", MANUFACTURER_ABB, 0x06, 1, false, true);
|
||||
tst_address_match("!9*.V=06", "99999999", MANUFACTURER_ABB, 0x07, 1, false, true);
|
||||
tst_address_match("!9*.V=06", "89999999", MANUFACTURER_ABB, 0x07, 1, false, true);
|
||||
|
||||
tst_telegram_match("12345678", "12345678", true, false);
|
||||
tst_telegram_match("11111111,22222222", "12345678,22*", true, true);
|
||||
tst_telegram_match("11111111,22222222", "12345678,22222222", true, false);
|
||||
tst_telegram_match("11111111.M=KAM,22222222.M=PII", "11111111.M=KAM", true, false);
|
||||
tst_telegram_match("11111111.M=KAF", "11111111.M=KAM", false, false);
|
||||
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.M=KAM", true, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.M=KAF", false, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111", true, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.M=KAM", true, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.V=1b", true, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.T=16", true, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.M=KAM.T=16", true, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.M=KAM.V=1b", true, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.T=16.V=1b", true, false);
|
||||
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.M=KAL", false, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.V=1c", false, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.T=17", false, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.M=KAM.T=17", false, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.M=KAL.V=1b", false, false);
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16", "11111111.T=17.V=1b", false, false);
|
||||
|
||||
// Test * matches both 11111111 and 2222222 but the only the 111111 matches the filter out V=1b.
|
||||
// Verify that the filter out !1*.V=1b will override successfull match (with no filter out) * for 22222222.
|
||||
tst_telegram_match("11111111.M=KAM.V=1b.T=16,22222222.M=XXX.V=aa.T=99", "*,!1*.V=1b", false, true);
|
||||
}
|
||||
|
||||
void eq(string a, string b, const char *tn)
|
||||
|
|
Ładowanie…
Reference in New Issue