kopia lustrzana https://github.com/weetmuts/wmbusmeters
				
				
				
			Add filter_out to address expression.
							rodzic
							
								
									0c98b474bb
								
							
						
					
					
						commit
						78e7c47503
					
				
							
								
								
									
										1
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										1
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
# Copyright (C) 2017-2023 Fredrik Öhrström (gpl-3.0-or-later)
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										187
									
								
								src/address.cc
								
								
								
								
							
							
						
						
									
										187
									
								
								src/address.cc
								
								
								
								
							| 
						 | 
				
			
			@ -16,10 +16,13 @@
 | 
			
		|||
*/
 | 
			
		||||
 | 
			
		||||
#include"address.h"
 | 
			
		||||
#include"manufacturers.h"
 | 
			
		||||
 | 
			
		||||
#include<assert.h>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
bool isValidMatchExpression(const string& s)
 | 
			
		||||
bool isValidMatchExpression(const string& s, bool *has_wildcard)
 | 
			
		||||
{
 | 
			
		||||
    string me = s;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +61,7 @@ bool isValidMatchExpression(const string& s)
 | 
			
		|||
    {
 | 
			
		||||
        me.erase(0,1);
 | 
			
		||||
        wildcard_used = true;
 | 
			
		||||
        if (has_wildcard) *has_wildcard = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Now we should have eaten the whole expression.
 | 
			
		||||
| 
						 | 
				
			
			@ -78,7 +82,7 @@ bool isValidMatchExpressions(const string& mes)
 | 
			
		|||
 | 
			
		||||
    for (string me : v)
 | 
			
		||||
    {
 | 
			
		||||
        if (!isValidMatchExpression(me)) return false;
 | 
			
		||||
        if (!isValidMatchExpression(me, NULL)) return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -231,6 +235,74 @@ bool doesIdMatchExpressions(const string& id, vector<string>& mes, bool *used_wi
 | 
			
		|||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool doesIdMatchAddressExpressions(const string& id, vector<AddressExpression>& aes, bool *used_wildcard)
 | 
			
		||||
{
 | 
			
		||||
/*    bool found_match = false;
 | 
			
		||||
    bool found_negative_match = false;
 | 
			
		||||
    bool exact_match = false;*/
 | 
			
		||||
    *used_wildcard = false;
 | 
			
		||||
 | 
			
		||||
    // Goes through all possible match expressions.
 | 
			
		||||
    // If no expression matches, neither positive nor negative,
 | 
			
		||||
    // then the result is false. (ie no match)
 | 
			
		||||
 | 
			
		||||
    // If more than one positive match is found, and no negative,
 | 
			
		||||
    // then the result is true.
 | 
			
		||||
 | 
			
		||||
    // If more than one negative match is found, irrespective
 | 
			
		||||
    // if there is any positive matches or not, then the result is false.
 | 
			
		||||
 | 
			
		||||
    // If a positive match is found, using a wildcard not any exact match,
 | 
			
		||||
    // then *used_wildcard is set to true.
 | 
			
		||||
/*
 | 
			
		||||
    for (AddressExpression &ae : aes)
 | 
			
		||||
    {
 | 
			
		||||
        bool has_wildcard = ae.has_wildcard;
 | 
			
		||||
        bool is_negative_rule = (me.length() > 0 && me.front() == '!');
 | 
			
		||||
        if (is_negative_rule)
 | 
			
		||||
        {
 | 
			
		||||
            me.erase(0, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool m = doesIdMatchExpression(id, me);
 | 
			
		||||
 | 
			
		||||
        if (is_negative_rule)
 | 
			
		||||
        {
 | 
			
		||||
            if (m) found_negative_match = true;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (m)
 | 
			
		||||
            {
 | 
			
		||||
                found_match = true;
 | 
			
		||||
                if (!has_wildcard)
 | 
			
		||||
                {
 | 
			
		||||
                    exact_match = true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (found_negative_match)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (found_match)
 | 
			
		||||
    {
 | 
			
		||||
        if (exact_match)
 | 
			
		||||
        {
 | 
			
		||||
            *used_wildcard = false;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            *used_wildcard = true;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
*/
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string toIdsCommaSeparated(vector<string> &ids)
 | 
			
		||||
{
 | 
			
		||||
    string cs;
 | 
			
		||||
| 
						 | 
				
			
			@ -242,3 +314,114 @@ string toIdsCommaSeparated(vector<string> &ids)
 | 
			
		|||
    if (cs.length() > 0) cs.pop_back();
 | 
			
		||||
    return cs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool AddressExpression::match(const std::string &i, uint16_t m, uchar v, uchar t)
 | 
			
		||||
{
 | 
			
		||||
    if (!(mfct == 0xffff || mfct == m)) return false;
 | 
			
		||||
    if (!(version == 0xff || version == v)) return false;
 | 
			
		||||
    if (!(type == 0xff || type == t)) return false;
 | 
			
		||||
    if (!doesIdMatchExpression(i, id)) return false;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool AddressExpression::parse(const string &in)
 | 
			
		||||
{
 | 
			
		||||
    string s = in;
 | 
			
		||||
    // Example: 12345678
 | 
			
		||||
    // or       12345678.M=PII.T=1B.V=01
 | 
			
		||||
    // or       1234*
 | 
			
		||||
    // or       1234*.M=PII
 | 
			
		||||
    // or       1234*.V=01
 | 
			
		||||
    // or       12 // mbus primary
 | 
			
		||||
    // or       0  // mbus primary
 | 
			
		||||
    // or       250.MPII.V01.T1B // mbus primary
 | 
			
		||||
    // or       !12345678
 | 
			
		||||
    // or       !*.M=ABC
 | 
			
		||||
    id = "";
 | 
			
		||||
    mbus_primary = false;
 | 
			
		||||
    mfct = 0xffff;
 | 
			
		||||
    type = 0xff;
 | 
			
		||||
    version = 0xff;
 | 
			
		||||
    filter_out = false;
 | 
			
		||||
 | 
			
		||||
    if (s.size() == 0) return false;
 | 
			
		||||
 | 
			
		||||
    if (s.size() > 1 && s[0] == '!')
 | 
			
		||||
    {
 | 
			
		||||
        filter_out = true;
 | 
			
		||||
        s = s.substr(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vector<string> parts = splitString(s, '.');
 | 
			
		||||
 | 
			
		||||
    assert(parts.size() > 0);
 | 
			
		||||
 | 
			
		||||
    id = parts[0];
 | 
			
		||||
    if (!isValidMatchExpression(id, &has_wildcard))
 | 
			
		||||
    {
 | 
			
		||||
        // Not a long id, so lets check if it is p0 to p250 for primary mbus ids.
 | 
			
		||||
        if (id.size() < 2) return false;
 | 
			
		||||
        if (id[0] != 'p') return false;
 | 
			
		||||
        for (size_t i=1; i < id.length(); ++i)
 | 
			
		||||
        {
 | 
			
		||||
            if (!isdigit(id[i])) return false;
 | 
			
		||||
        }
 | 
			
		||||
        // All digits good.
 | 
			
		||||
        int v = atoi(id.c_str()+1);
 | 
			
		||||
        if (v < 0 || v > 250) return false;
 | 
			
		||||
        // It is 0-250 which means it is an mbus primary address.
 | 
			
		||||
        mbus_primary = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (size_t i=1; i<parts.size(); ++i)
 | 
			
		||||
    {
 | 
			
		||||
        if (parts[i].size() == 4) // V=xy or T=xy
 | 
			
		||||
        {
 | 
			
		||||
            if (parts[i][1] != '=') return false;
 | 
			
		||||
 | 
			
		||||
            vector<uchar> data;
 | 
			
		||||
            bool ok = hex2bin(&parts[i][2], &data);
 | 
			
		||||
            if (!ok) return false;
 | 
			
		||||
            if (data.size() != 1) return false;
 | 
			
		||||
 | 
			
		||||
            if (parts[i][0] == 'V')
 | 
			
		||||
            {
 | 
			
		||||
                version = data[0];
 | 
			
		||||
            }
 | 
			
		||||
            else if (parts[i][0] == 'T')
 | 
			
		||||
            {
 | 
			
		||||
                type = data[0];
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (parts[i].size() == 5) // M=xyz
 | 
			
		||||
        {
 | 
			
		||||
            if (parts[i][1] != '=') return false;
 | 
			
		||||
            if (parts[i][0] != 'M') return false;
 | 
			
		||||
 | 
			
		||||
            bool ok = flagToManufacturer(&parts[i][2], &mfct);
 | 
			
		||||
            if (!ok) return false;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool flagToManufacturer(const char *s, uint16_t *out_mfct)
 | 
			
		||||
{
 | 
			
		||||
    if (s[0] == 0 || s[1] == 0 || s[2] == 0 || s[3] != 0) return false;
 | 
			
		||||
    if (s[0] < '@' || s[0] > 'Z' ||
 | 
			
		||||
        s[1] < '@' || s[1] > 'Z' ||
 | 
			
		||||
        s[2] < '@' || s[2] > 'Z') return false;
 | 
			
		||||
 | 
			
		||||
    *out_mfct = MANFCODE(s[0],s[1],s[2]);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,24 +21,35 @@
 | 
			
		|||
#include "util.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
struct Address
 | 
			
		||||
struct AddressExpression
 | 
			
		||||
{
 | 
			
		||||
    // An address expression is used to select which telegrams to decode for a driver.
 | 
			
		||||
    // An address expression is also used to select a specific meter to poll for data.
 | 
			
		||||
    // Example address: 12345678
 | 
			
		||||
    // Or fully qualified: 12345678.M=PII.T=1b.V=01
 | 
			
		||||
    // which means manufacturer triplet PII, type/media=0x1b, version=0x01
 | 
			
		||||
    // Or wildcards in id: 12*.T=16
 | 
			
		||||
    // which matches all cold water meters whose ids start with 12.
 | 
			
		||||
    // Or negated tests: 12345678.V!=66
 | 
			
		||||
    // which will decode all telegrams from 12345678 except those where the version is 0x66.
 | 
			
		||||
    // Or every telegram which is does not start with 12 and is not from ABB:
 | 
			
		||||
    // !12*.M!=ABB
 | 
			
		||||
 | 
			
		||||
    std::string id; // 1 or 12345678 or non-compliant hex: 1234abcd
 | 
			
		||||
    bool wildcard_used {}; // The id contains a *
 | 
			
		||||
    bool has_wildcard {}; // The id contains a *
 | 
			
		||||
    bool mbus_primary {}; // Signals that the id is 0-250
 | 
			
		||||
 | 
			
		||||
    uint16_t mfct {}; // If 0xffff then any mfct matches this address.
 | 
			
		||||
    uchar type {}; // If 0xff then any type matches this address.
 | 
			
		||||
    uchar version {}; // If 0xff then any version matches this address.
 | 
			
		||||
    bool negate {}; // When used for testing this address was negated. !12345678
 | 
			
		||||
 | 
			
		||||
    bool parse(std::string &s);
 | 
			
		||||
    bool match(Address *a);
 | 
			
		||||
    bool filter_out {}; // Telegrams matching this rule should be filtered out!
 | 
			
		||||
 | 
			
		||||
    bool parse(const std::string &s);
 | 
			
		||||
    bool match(const std::string &id, uint16_t mfct, uchar version, uchar type);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool isValidMatchExpression(const std::string& s);
 | 
			
		||||
bool isValidMatchExpression(const std::string& s, bool *has_wildcard);
 | 
			
		||||
bool isValidMatchExpressions(const std::string& s);
 | 
			
		||||
 | 
			
		||||
bool doesIdMatchExpression(const std::string& id,
 | 
			
		||||
| 
						 | 
				
			
			@ -55,4 +66,6 @@ bool isValidId(const std::string& id);
 | 
			
		|||
 | 
			
		||||
std::vector<std::string> splitMatchExpressions(const std::string& mes);
 | 
			
		||||
 | 
			
		||||
bool flagToManufacturer(const char *s, uint16_t *out_mfct);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2588,87 +2588,6 @@ bool FieldInfo::extractString(Meter *m, Telegram *t, DVEntry *dve)
 | 
			
		|||
    return found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Address::parse(string &s)
 | 
			
		||||
{
 | 
			
		||||
    // Example: 12345678
 | 
			
		||||
    // or       12345678.M=PII.T=1B.V=01
 | 
			
		||||
    // or       1234*
 | 
			
		||||
    // or       1234*.M=PII
 | 
			
		||||
    // or       1234*.V=01
 | 
			
		||||
    // or       12 // mbus primary
 | 
			
		||||
    // or       0  // mbus primary
 | 
			
		||||
    // or       250.MPII.V01.T1B // mbus primary
 | 
			
		||||
    // or       !12345678
 | 
			
		||||
    // or       !*.M=ABC
 | 
			
		||||
    id = "";
 | 
			
		||||
    mbus_primary = false;
 | 
			
		||||
    mfct = 0xffff;
 | 
			
		||||
    type = 0xff;
 | 
			
		||||
    version = 0xff;
 | 
			
		||||
    negate = false;
 | 
			
		||||
 | 
			
		||||
    if (s.size() == 0) return false;
 | 
			
		||||
 | 
			
		||||
    vector<string> parts = splitString(s, '.');
 | 
			
		||||
 | 
			
		||||
    assert(parts.size() > 0);
 | 
			
		||||
 | 
			
		||||
    if (!isValidMatchExpression(parts[0]))
 | 
			
		||||
    {
 | 
			
		||||
        // Not a long id, so lets check if it is 0-250.
 | 
			
		||||
        for (size_t i=0; i < parts[0].length(); ++i)
 | 
			
		||||
        {
 | 
			
		||||
            if (!isdigit(parts[0][i])) return false;
 | 
			
		||||
        }
 | 
			
		||||
        // All digits good.
 | 
			
		||||
        int v = atoi(parts[0].c_str());
 | 
			
		||||
        if (v < 0 || v > 250) return false;
 | 
			
		||||
        // It is 0-250 which means it is an mbus primary address.
 | 
			
		||||
        mbus_primary = true;
 | 
			
		||||
    }
 | 
			
		||||
    id = parts[0];
 | 
			
		||||
 | 
			
		||||
    for (size_t i=1; i<parts.size(); ++i)
 | 
			
		||||
    {
 | 
			
		||||
        if (parts[i].size() == 4) // V=xy or T=xy
 | 
			
		||||
        {
 | 
			
		||||
            if (parts[i][1] != '=') return false;
 | 
			
		||||
 | 
			
		||||
            vector<uchar> data;
 | 
			
		||||
            bool ok = hex2bin(&parts[i][2], &data);
 | 
			
		||||
            if (!ok) return false;
 | 
			
		||||
            if (data.size() != 1) return false;
 | 
			
		||||
 | 
			
		||||
            if (parts[i][0] == 'V')
 | 
			
		||||
            {
 | 
			
		||||
                version = data[0];
 | 
			
		||||
            }
 | 
			
		||||
            else if (parts[i][0] == 'T')
 | 
			
		||||
            {
 | 
			
		||||
                type = data[0];
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (parts[i].size() == 5) // M=xyz
 | 
			
		||||
        {
 | 
			
		||||
            if (parts[i][1] != '=') return false;
 | 
			
		||||
            if (parts[i][0] != 'M') return false;
 | 
			
		||||
 | 
			
		||||
            bool ok = flagToManufacturer(&parts[i][2], &mfct);
 | 
			
		||||
            if (!ok) return false;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool checkIf(set<string> &fields, const char *s)
 | 
			
		||||
{
 | 
			
		||||
    if (fields.count(s) > 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,13 +39,13 @@ bool verbose_ = false;
 | 
			
		|||
 | 
			
		||||
#define LIST_OF_TESTS \
 | 
			
		||||
    X(addresses) \
 | 
			
		||||
    /*
 | 
			
		||||
    X(dynamic_loading)                        \
 | 
			
		||||
    X(crc)            \
 | 
			
		||||
    X(dvparser)       \
 | 
			
		||||
    X(devices)        \
 | 
			
		||||
    X(linkmodes)      \
 | 
			
		||||
    X(ids)            \
 | 
			
		||||
    X(addresses)      \
 | 
			
		||||
    X(kdf)            \
 | 
			
		||||
    X(periods)        \
 | 
			
		||||
    X(device_parsing) \
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +77,7 @@ bool verbose_ = false;
 | 
			
		|||
    X(formulas_dventries)                       \
 | 
			
		||||
    X(formulas_stringinterpolation)             \
 | 
			
		||||
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
#define X(t) void test_##t();
 | 
			
		||||
LIST_OF_TESTS
 | 
			
		||||
| 
						 | 
				
			
			@ -498,11 +499,15 @@ void test_ids()
 | 
			
		|||
    test_does_id_match_expression("78563413", "*,!00156327,!00048713", true, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tst_address(string s, bool valid, string id,
 | 
			
		||||
                 string mfct, uchar version, uchar type,
 | 
			
		||||
                 bool mbus_primary, bool wildcard_used)
 | 
			
		||||
void tst_address(string s, bool valid,
 | 
			
		||||
                 string id, bool has_wildcard,
 | 
			
		||||
                 string mfct,
 | 
			
		||||
                 uchar version,
 | 
			
		||||
                 uchar type,
 | 
			
		||||
                 bool mbus_primary,
 | 
			
		||||
                 bool filter_out)
 | 
			
		||||
{
 | 
			
		||||
    Address a;
 | 
			
		||||
    AddressExpression a;
 | 
			
		||||
    bool ok = a.parse(s);
 | 
			
		||||
 | 
			
		||||
    if (ok != valid)
 | 
			
		||||
| 
						 | 
				
			
			@ -515,47 +520,119 @@ void tst_address(string s, bool valid, string id,
 | 
			
		|||
    {
 | 
			
		||||
        string smfct = manufacturerFlag(a.mfct);
 | 
			
		||||
        if (id != a.id ||
 | 
			
		||||
            has_wildcard != a.has_wildcard ||
 | 
			
		||||
            mfct != smfct ||
 | 
			
		||||
            version != a.version ||
 | 
			
		||||
            type != a.type ||
 | 
			
		||||
            wildcard_used != a.wildcard_used ||
 | 
			
		||||
            mbus_primary != a.mbus_primary ||
 | 
			
		||||
            wildcard_used != a.wildcard_used)
 | 
			
		||||
            filter_out != a.filter_out)
 | 
			
		||||
        {
 | 
			
		||||
            printf("Expected parse of address \"%s\" to return (id=%s mfct=%s version=%02x type=%02x mp=%d wu=%d)\n"
 | 
			
		||||
                   "but got (id=%s mfct=%s version=%02x type=%02x mp=%d wu=%d)\n",
 | 
			
		||||
            printf("Expected parse of address \"%s\" to return\n"
 | 
			
		||||
                   "(id=%s haswild=%d mfct=%s version=%02x type=%02x mbus=%d negt=%d)\n"
 | 
			
		||||
                   "but got\n"
 | 
			
		||||
                   "(id=%s haswild=%d mfct=%s version=%02x type=%02x mbus=%d negt=%d)\n",
 | 
			
		||||
                   s.c_str(),
 | 
			
		||||
                   id.c_str(), mfct.c_str(), version, type, mbus_primary, wildcard_used,
 | 
			
		||||
                   a.id.c_str(), smfct.c_str(), a.version, a.type, a.mbus_primary, a.wildcard_used);
 | 
			
		||||
                   id.c_str(),
 | 
			
		||||
                   has_wildcard,
 | 
			
		||||
                   mfct.c_str(),
 | 
			
		||||
                   version,
 | 
			
		||||
                   type,
 | 
			
		||||
                   mbus_primary,
 | 
			
		||||
                   filter_out,
 | 
			
		||||
                   a.id.c_str(),
 | 
			
		||||
                   a.has_wildcard,
 | 
			
		||||
                   smfct.c_str(),
 | 
			
		||||
                   a.version,
 | 
			
		||||
                   a.type,
 | 
			
		||||
                   a.mbus_primary,
 | 
			
		||||
                   a.filter_out);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tst_address_match(string expr, string id, uint16_t m, uchar v, uchar t, bool match, bool filter_out)
 | 
			
		||||
{
 | 
			
		||||
    AddressExpression e;
 | 
			
		||||
    bool ok = e.parse(expr);
 | 
			
		||||
    assert(ok);
 | 
			
		||||
 | 
			
		||||
    bool test = e.match(id, m, v, t);
 | 
			
		||||
 | 
			
		||||
    if (test != match)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Expected address %s %04x %02x %02x to %smatch expression %s\n",
 | 
			
		||||
               id.c_str(),
 | 
			
		||||
               m, v, t,
 | 
			
		||||
               match?"":"not ",
 | 
			
		||||
               expr.c_str());
 | 
			
		||||
    }
 | 
			
		||||
    if (match && e.filter_out != filter_out)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Expected %s from match expression %s\n",
 | 
			
		||||
               filter_out?"FILTERED OUT":"NOT filtered",
 | 
			
		||||
               expr.c_str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_addresses()
 | 
			
		||||
{
 | 
			
		||||
    tst_address("12345678",
 | 
			
		||||
                true,
 | 
			
		||||
                "12345678", // id
 | 
			
		||||
                false, // has wildcard
 | 
			
		||||
                "___", // mfct
 | 
			
		||||
                0xff, // type
 | 
			
		||||
                0xff,  // version
 | 
			
		||||
                false, // mbus primary
 | 
			
		||||
                false // wildcard used
 | 
			
		||||
                false, // mbus primary found
 | 
			
		||||
                false // negate test
 | 
			
		||||
        );
 | 
			
		||||
    tst_address("123k45678", false, "", "", 0xff, 0xff, false, false);
 | 
			
		||||
    tst_address("1234", false, "", "", 0xff, 0xff, false, false);
 | 
			
		||||
    tst_address("0", true, "0", "___", 0xff, 0xff, true,false);
 | 
			
		||||
    tst_address("250", true, "250", "___", 0xff, 0xff, true, false);
 | 
			
		||||
    tst_address("251", false, "", "", 0xff, 0xff, false, false);
 | 
			
		||||
    tst_address("0.M=PII.V=01.T=1b", true, "0", "PII", 0x01, 0x1b, true, false);
 | 
			
		||||
    tst_address("123.V=11.M=FOO.T=ff", true, "123", "FOO", 0x11, 0xff, true, false);
 | 
			
		||||
    tst_address("123.M=FOO", true, "123", "FOO", 0xff, 0xff, true, false);
 | 
			
		||||
    tst_address("123.M=FOO.V=33", true, "123", "FOO", 0x33, 0xff, true, false);
 | 
			
		||||
    tst_address("123.T=33", true, "123", "___", 0xff, 0x33, true, false);
 | 
			
		||||
    tst_address("1.V=33", true, "1", "___", 0x33, 0xff, true, false);
 | 
			
		||||
    tst_address("16.M=BAR", true, "16", "BAR", 0xff, 0xff, true, false);
 | 
			
		||||
    tst_address("123k45678", false, "", false, "", 0xff, 0xff, false, false);
 | 
			
		||||
    tst_address("1234", false, "", false, "", 0xff, 0xff, false, false);
 | 
			
		||||
    tst_address("p0", true, "p0", false, "___", 0xff, 0xff, true, false);
 | 
			
		||||
    tst_address("p250", true, "p250", false, "___", 0xff, 0xff, true, false);
 | 
			
		||||
    tst_address("p251", false, "", false, "", 0xff, 0xff, false, false);
 | 
			
		||||
    tst_address("p0.M=PII.V=01.T=1b", true, "p0", false, "PII", 0x01, 0x1b, true, false);
 | 
			
		||||
    tst_address("p123.V=11.M=FOO.T=ff", true, "p123", false, "FOO", 0x11, 0xff, true, false);
 | 
			
		||||
    tst_address("p123.M=FOO", true, "p123", false, "FOO", 0xff, 0xff, true, false);
 | 
			
		||||
    tst_address("p123.M=FOO.V=33", true, "p123", false, "FOO", 0x33, 0xff, true, false);
 | 
			
		||||
    tst_address("p123.T=33", true, "p123", false, "___", 0xff, 0x33, true, false);
 | 
			
		||||
    tst_address("p1.V=33", true, "p1", false, "___", 0x33, 0xff, true, false);
 | 
			
		||||
    tst_address("p16.M=BAR", true, "p16", false, "BAR", 0xff, 0xff, true, false);
 | 
			
		||||
 | 
			
		||||
//    tst_address("12*", true, "12*", "___", 0xff, 0xff, false, true);
 | 
			
		||||
    tst_address("12345678.M=ABB.V=66.T=16", true, "12345678",  false, "ABB", 0x66, 0x16, false, false);
 | 
			
		||||
    tst_address("!12345678.M=ABB.V=66.T=16", true, "12345678", false, "ABB", 0x66, 0x16, false, true);
 | 
			
		||||
    tst_address("!*.M=ABB", true, "*", true, "ABB", 0xff, 0xff, false, true);
 | 
			
		||||
    tst_address("!*.V=66.T=06", true, "*", true, "___", 0x66, 0x06, false, true);
 | 
			
		||||
 | 
			
		||||
    tst_address("12*", true, "12*", true, "___", 0xff, 0xff, false, false);
 | 
			
		||||
    tst_address("!1234567*", true, "1234567*", true, "___", 0xff, 0xff, false, true);
 | 
			
		||||
 | 
			
		||||
    tst_address_match("12345678", "12345678", 1, 1, 1, true, false);
 | 
			
		||||
    tst_address_match("12345678.M=ABB.V=77", "12345678", MANUFACTURER_ABB, 0x77, 88, true, false);
 | 
			
		||||
    tst_address_match("1*.V=77", "12345678", MANUFACTURER_ABB, 0x77, 1, true, false);
 | 
			
		||||
    tst_address_match("12345678.M=ABB.V=67.T=06", "12345678", MANUFACTURER_ABB, 0x67, 0x06, true, false);
 | 
			
		||||
    tst_address_match("12345678.M=ABB.V=67.T=06", "12345678", MANUFACTURER_ABB, 0x68, 0x06, false, false);
 | 
			
		||||
    tst_address_match("12345678.M=ABB.V=67.T=06", "12345678", MANUFACTURER_ABB, 0x67, 0x07, false, false);
 | 
			
		||||
    tst_address_match("12345678.M=ABB.V=67.T=06", "12345678", MANUFACTURER_ABB+1, 0x67, 0x06, false, false);
 | 
			
		||||
    tst_address_match("12345678.M=ABB.V=67.T=06", "12345677", MANUFACTURER_ABB, 0x67, 0x06, false, false);
 | 
			
		||||
 | 
			
		||||
    // Now verify filter out ! character. The filter out does notchange the test. It is still the same
 | 
			
		||||
    // test, but the match will be used as a filter out. Ie if the match triggers, then the telegram will be filtered out.
 | 
			
		||||
    tst_address_match("!12345678", "12345677", 1, 1, 1, false, false);
 | 
			
		||||
    tst_address_match("!*.M=ABB", "99999999", MANUFACTURER_ABB, 1, 1, true, true);
 | 
			
		||||
    tst_address_match("*.M=ABB", "99999999", MANUFACTURER_ABB, 1, 1, true, false);
 | 
			
		||||
 | 
			
		||||
    // Test that both id wildcard matches and the version.
 | 
			
		||||
    tst_address_match("9*.V=06", "99999999", MANUFACTURER_ABB, 0x06, 1, true, false);
 | 
			
		||||
    tst_address_match("9*.V=06", "89999999", MANUFACTURER_ABB, 0x06, 1, false, false);
 | 
			
		||||
    tst_address_match("9*.V=06", "99999999", MANUFACTURER_ABB, 0x07, 1, false, false);
 | 
			
		||||
    tst_address_match("9*.V=06", "89999999", MANUFACTURER_ABB, 0x07, 1, false, false);
 | 
			
		||||
 | 
			
		||||
    // Test the same, expect same answers but check that filtered out is set.
 | 
			
		||||
    tst_address_match("!9*.V=06", "99999999", MANUFACTURER_ABB, 0x06, 1, true, true);
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eq(string a, string b, const char *tn)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								src/wmbus.cc
								
								
								
								
							
							
						
						
									
										11
									
								
								src/wmbus.cc
								
								
								
								
							| 
						 | 
				
			
			@ -465,17 +465,6 @@ string manufacturerFlag(int m_field) {
 | 
			
		|||
    return flag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool flagToManufacturer(const char *s, uint16_t *out_mfct)
 | 
			
		||||
{
 | 
			
		||||
    if (s[0] == 0 || s[1] == 0 || s[2] == 0 || s[3] != 0) return false;
 | 
			
		||||
    if (s[0] < '@' || s[0] > 'Z' ||
 | 
			
		||||
        s[1] < '@' || s[1] > 'Z' ||
 | 
			
		||||
        s[2] < '@' || s[2] > 'Z') return false;
 | 
			
		||||
 | 
			
		||||
    *out_mfct = MANFCODE(s[0],s[1],s[2]);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
string mediaType(int a_field_device_type, int m_field) {
 | 
			
		||||
    switch (a_field_device_type) {
 | 
			
		||||
    case 0: return "Other";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -742,7 +742,6 @@ shared_ptr<BusDevice> openSimulator(Detected detected,
 | 
			
		|||
 | 
			
		||||
string manufacturer(int m_field);
 | 
			
		||||
string manufacturerFlag(int m_field);
 | 
			
		||||
bool flagToManufacturer(const char *s, uint16_t *out_mfct);
 | 
			
		||||
string mediaType(int a_field_device_type, int m_field);
 | 
			
		||||
string mediaTypeJSON(int a_field_device_type, int m_field);
 | 
			
		||||
bool isCiFieldOfType(int ci_field, CI_TYPE type);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue