Add elster,iperl text based drivers.

pull/1167/head
Fredrik Öhrström 2024-02-11 23:06:59 +01:00
rodzic 04ed4d7628
commit fefbf507fe
21 zmienionych plików z 367 dodań i 158 usunięć

1
.gitignore vendored
Wyświetl plik

@ -6,6 +6,7 @@ packaging/
testaes/
testoutput/
tests_tmp/
3rdparty/
*~
config.log
autom4te.cache/

Wyświetl plik

@ -1,3 +1,4 @@
# Copyright (C) 2017-2023 Fredrik Öhrström (gpl-3.0-or-later)
#
# This program is free software: you can redistribute it and/or modify
@ -324,16 +325,16 @@ lcov:
(cd build_debug; genhtml lcov.info)
xdg-open build_debug/src/index.html
test:
test: build/xmq
@./test.sh build/wmbusmeters
testd:
testd: build/xmq
@./test.sh build_debug/wmbusmeters
testdriver:
testdriver: build/xmq
@./tests/test_drivers.sh build/wmbusmeters driver_${DRIVER}.cc
testdriverd:
testdriverd: build/xmq
@./tests/test_drivers.sh build_debug/wmbusmeters driver_${DRIVER}.cc
update_manufacturers:
@ -452,6 +453,14 @@ deploy:
collect_copyrights:
./scripts/collect_copyrights.sh deb/copyright
3rdparty/xmq/build/default/release/xmq: $(wildcard 3rdparty/xmq/src/main/c/* 3rdparty/xmq/src/main/c/parts/*)
@mkdir -p 3rdparty
@(cd 3rdparty; git clone git@github.com:libxmq/xmq.git; cd xmq; ./configure; make; make test)
build/xmq: 3rdparty/xmq/build/default/release/xmq
@cp $< $@
@if [ "$(build/xmq --version ; echo $?)" != "0" ]; then echo "Failed to build a working xmq!"; fi
# Include dependency information generated by gcc in a previous compile.
include $(wildcard $(patsubst %.o,%.d,$(PROG_OBJS) $(DRIVER_OBJS)))

Wyświetl plik

@ -60,6 +60,43 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv)
return parseNormalCommandLine(c, argc, argv);
}
void enableEarlyLoggingFromCommandLine(int argc, char **argv)
{
int i = 1;
// First find all logging flags, --silent --verbose --normal --debug
while (argv[i] && argv[i][0] == '-')
{
if (!strcmp(argv[i], "--silent")) {
i++;
silentLogging(true);
continue;
}
if (!strcmp(argv[i], "--verbose")) {
verboseEnabled(true);
i++;
continue;
}
if (!strcmp(argv[i], "--normal")) {
i++;
continue;
}
if (!strcmp(argv[i], "--debug")) {
verboseEnabled(true);
debugEnabled(true);
i++;
continue;
}
if (!strcmp(argv[i], "--trace")) {
verboseEnabled(true);
debugEnabled(true);
traceEnabled(true);
i++;
continue;
}
i++;
}
}
static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int argc, char **argv)
{
int i = 1;
@ -621,13 +658,13 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
if (!strncmp(argv[i], "--driver=", 9))
{
size_t len = strlen(argv[i]) - 9;
string driver = string(argv[i]+9, len);
if (!checkFileExists(driver.c_str()))
string file_name = string(argv[i]+9, len);
if (!checkFileExists(file_name.c_str()))
{
error("You must supply a valid file to --driver=<file>\n");
}
i++;
loadDriver(driver);
loadDriver(file_name, NULL);
continue;
}

Wyświetl plik

@ -27,5 +27,6 @@
using namespace std;
shared_ptr<Configuration> parseCommandLine(int argc, char **argv);
void enableEarlyLoggingFromCommandLine(int argc, char **argv);
#endif

Wyświetl plik

@ -20,6 +20,8 @@
#include"driver_dynamic.h"
#include"xmq.h"
#include<string.h>
string check_driver_name(const char *name, string file);
MeterType check_meter_type(const char *meter_type_s, string file);
string check_default_fields(const char *fields, string file);
@ -38,14 +40,28 @@ void check_set_vif_range(const char *vif_range_s, FieldMatcher *fm, DriverDynami
const char *line = "-------------------------------------------------------------------------------";
bool DriverDynamic::load(DriverInfo *di, const string &file)
bool DriverDynamic::load(DriverInfo *di, const string &file_name, const char *content)
{
if (!endsWith(file, ".xmq")) return false;
if (!checkFileExists(file.c_str())) return false;
if (!content)
{
if (!endsWith(file_name, ".xmq")) return false;
if (!checkFileExists(file_name.c_str())) return false;
}
string file = file_name;
XMQDoc *doc = xmqNewDoc();
bool ok = xmqParseFile(doc, file.c_str(), NULL);
bool ok = false;
if (!content)
{
ok = xmqParseFile(doc, file.c_str(), NULL);
}
else
{
file = "builtin";
ok = xmqParseBuffer(doc, content, content+strlen(content), NULL);
}
if (!ok) {
warning("(driver) error loading wmbusmeters driver file %s\n%s\n%s\n",
@ -67,7 +83,10 @@ bool DriverDynamic::load(DriverInfo *di, const string &file)
string default_fields = check_default_fields(xmqGetString(doc, NULL, "/driver/default_fields"), file);
di->setDefaultFields(default_fields);
verbose("(driver) loading driver %s from file %s\n", name.c_str(), file.c_str());
if (!content)
{
verbose("(driver) loading driver %s from file %s\n", name.c_str(), file.c_str());
}
di->setDynamic(file, doc);
@ -89,6 +108,7 @@ DriverDynamic::DriverDynamic(MeterInfo &mi, DriverInfo &di) :
MeterCommonImplementation(mi, di), file_name_(di.getDynamicFileName())
{
XMQDoc *doc = di.getDynamicDriver();
assert(doc);
verbose("(driver) constructing driver %s from already loaded file %s\n",
di.name().str().c_str(),
@ -101,8 +121,6 @@ DriverDynamic::DriverDynamic(MeterInfo &mi, DriverInfo &di) :
catch (...)
{
}
xmqFreeDoc(doc);
}
DriverDynamic::~DriverDynamic()

Wyświetl plik

@ -24,7 +24,7 @@ struct DriverDynamic : public virtual MeterCommonImplementation
{
DriverDynamic(MeterInfo &mi, DriverInfo &di);
~DriverDynamic();
static bool load(DriverInfo *di, const string &name);
static bool load(DriverInfo *di, const string &name, const char *content);
static XMQProceed add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *di);
static XMQProceed add_field(XMQDoc *doc, XMQNode *field, DriverDynamic *dd);
static XMQProceed add_match(XMQDoc *doc, XMQNode *match, DriverDynamic *dd);

Wyświetl plik

@ -1,75 +0,0 @@
/*
Copyright (C) 2017-2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2018 David Mallon (gpl-3.0-or-later)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include"meters_common_implementation.h"
namespace
{
struct Driver : public virtual MeterCommonImplementation
{
Driver(MeterInfo &mi, DriverInfo &di);
};
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("iperl");
di.setDefaultFields("name,id,total_m3,max_flow_m3h,timestamp");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_SEN, 0x06, 0x68);
di.addDetection(MANUFACTURER_SEN, 0x07, 0x68);
di.addDetection(MANUFACTURER_SEN, 0x07, 0x7c);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addNumericFieldWithExtractor(
"total",
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
);
addNumericFieldWithExtractor(
"max_flow",
"The maximum flow recorded during previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow));
}
}
// Test: MoreWater iperl 12345699 NOKEY
// Comment: Test iPerl T1 telegram, that after decryption, has 2f2f markers.
// telegram=|1E44AE4C9956341268077A36001000_2F2F0413181E0000023B00002F2F2F2F|
// {"media":"water","meter":"iperl","name":"MoreWater","id":"12345699","total_m3":7.704,"max_flow_m3h":0,"timestamp":"1111-11-11T11:11:11Z"}
// |MoreWater;12345699;7.704;0;1111-11-11 11:11.11
// Test: WaterWater iperl 33225544 NOKEY
// Comment: Test iPerl T1 telegram not encrypted, which has no 2f2f markers.
// telegram=|1844AE4C4455223368077A55000000_041389E20100023B0000|
// {"media":"water","meter":"iperl","name":"WaterWater","id":"33225544","total_m3":123.529,"max_flow_m3h":0,"timestamp":"1111-11-11T11:11:11Z"}
// |WaterWater;33225544;123.529;0;1111-11-11 11:11.11

Wyświetl plik

@ -29,7 +29,6 @@ namespace
di.setName("munia");
di.setDefaultFields("name,id,current_temperature_c,current_relative_humidity_rh,timestamp");
di.setMeterType(MeterType::TempHygroMeter);
di.addLinkMode(LinkMode::MBUS);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
di.addDetection(MANUFACTURER_WEP, 0x1b, 0x02);
di.addDetection(MANUFACTURER_WEP, 0x1b, 0x04);

Wyświetl plik

@ -1,41 +0,0 @@
/*
Copyright (C) 2024 Fredrik Öhrström (gpl-3.0-or-later)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include<vector>
#include<string>
#include"util.h"
#include"drivers.h"
#include"meters.h"
using namespace std;
void loadDriversFromDir(std::string dir)
{
if (!checkIfDirExists(dir.c_str())) return;
vector<string> drivers;
listFiles(dir, &drivers);
verbose("(drivers) scanning dir %s\n", dir.c_str());
for (string &file : drivers)
{
string filename = dir+"/"+file;
string s = loadDriver(filename);
}
}

118
src/drivers.cc 100644
Wyświetl plik

@ -0,0 +1,118 @@
/*
Copyright (C) 2024 Fredrik Öhrström (gpl-3.0-or-later)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include<vector>
#include<string>
#include<map>
#include"util.h"
#include"drivers.h"
#include"meters.h"
using namespace std;
void loadDriversFromDir(std::string dir)
{
if (!checkIfDirExists(dir.c_str())) return;
vector<string> drivers;
listFiles(dir, &drivers);
verbose("(drivers) scanning dir %s\n", dir.c_str());
for (string &file : drivers)
{
string file_name = dir+"/"+file;
string s = loadDriver(file_name, NULL);
}
}
struct BuiltinDriver
{
const char *name;
const char *content;
bool loaded;
};
struct MVT
{
uint16_t mfct;
uchar version;
uchar type;
};
struct MapToDriver {
MVT mvt;
const char *name;
};
#include"generated_database.cc"
map<uint32_t,const char*> builtins_mvt_lookup_;
map<string,BuiltinDriver*> builtins_name_lookup_;
bool loadBuiltinDriver(string driver_name)
{
// Check that there is such a builtin driver.
if (builtins_name_lookup_.count(driver_name) == 0) return false;
BuiltinDriver *driver = builtins_name_lookup_[driver_name];
if (driver->loaded) return true;
string name = loadDriver("", driver->content);
driver->loaded = true;
return true;
}
void loadAllBuiltinDrivers()
{
for (auto &p : builtins_name_lookup_)
{
if (!p.second->loaded)
{
loadBuiltinDriver(p.first);
p.second->loaded = true;
}
}
}
const char *findBuiltinDriver(uint16_t mfct, uchar ver, uchar type)
{
uint32_t key = mfct << 16 | ver << 8 | type;
if (builtins_mvt_lookup_.count(key) == 0) return NULL;
return builtins_mvt_lookup_[key];
}
void prepareBuiltinDrivers()
{
size_t num_mvts = sizeof(builtins_mvts_) / sizeof(MapToDriver);
size_t num_drivers = sizeof(builtins_) / sizeof(BuiltinDriver);
for (size_t i = 0; i < num_drivers; ++i)
{
builtins_name_lookup_[builtins_[i].name] = &builtins_[i];
debug("(drivers) added builtin driver %s\n", builtins_[i].name);
}
for (size_t i = 0; i < num_mvts; ++i)
{
uint32_t key = builtins_mvts_[i].mvt.mfct << 16 |
builtins_mvts_[i].mvt.version << 8 |
builtins_mvts_[i].mvt.type;
builtins_mvt_lookup_[key] = builtins_mvts_[i].name;
}
}

Wyświetl plik

@ -20,6 +20,10 @@
#include<string>
void prepareBuiltinDrivers();
void loadDriversFromDir(std::string dir);
bool loadBuiltinDriver(std::string driver_name);
void loadAllBuiltinDrivers();
const char *findBuiltinDriver(uint16_t mfct, uchar ver, uchar type);
#endif

Wyświetl plik

@ -0,0 +1,30 @@
/*
Copyright (C) 2024 Fredrik Öhrström (gpl-3.0-or-later)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
BuiltinDriver builtins_[] =
{
{ "elster", "driver{name=elster meter_type=GasMeter default_fields=name,id,total_m3,timestamp detect{mvt=ELS,81,03}field{name=total quantity=Volume match{measurement_type=Instantaneous vif_range=Volume}}test{args='Gas elster 05105025 NOKEY'telegram=3644A511640010253837722550100593158103E70020052F2F_0374E602000C137034220302FD74EE0F2F2F2F2F2F2F2F2F2F2F2F2F2F2F json='{\"media\":\"gas\",\"meter\":\"elster\",\"name\":\"Gas\",\"id\":\"05105025\",\"total_m3\":3223.47,\"timestamp\":\"1111-11-11T11:11:11Z\"}'fields='Gas;05105025;3223.47;1111-11-11 11:11.11'}}", false },
{ "iperl", "driver{name=iperl meter_type=WaterMeter default_fields=name,id,total_m3,max_flow_m3h,timestamp detect{mvt=SEN,68,06 mvt=SEN,68,07 mvt=SEN,7c,07}field{name=total quantity=Volume match{measurement_type=Instantaneous vif_range=Volume}about{de='Der Gesamtwasserverbrauch.'en='The total water consumption.'fr='''La consommation totale d'eau.'''sv='Den totala vattenförbrukningen.'}}field{name=max_flow quantity=Flow match{measurement_type=Instantaneous vif_range=VolumeFlow}about{en='The maximum flow recorded during previous period.'}}test{args='MoreWater iperl 12345699 NOKEY'coment='Test iPerl T1 telegram, that after decryption, has 2f2f markers.'telegram=1E44AE4C9956341268077A36001000_2F2F0413181E0000023B00002F2F2F2F json='{\"media\":\"water\",\"meter\":\"iperl\",\"name\":\"MoreWater\",\"id\":\"12345699\",\"total_m3\":7.704,\"max_flow_m3h\":0,\"timestamp\":\"1111-11-11T11:11:11Z\"}'fields='MoreWater;12345699;7.704;0;1111-11-11 11:11.11'}test{args='WaterWater iperl 33225544 NOKEY'comment='Test iPerl T1 telegram not encrypted, which has no 2f2f markers.'telegram=1844AE4C4455223368077A55000000_041389E20100023B0000 json='{\"media\":\"water\",\"meter\":\"iperl\",\"name\":\"WaterWater\",\"id\":\"33225544\",\"total_m3\":123.529,\"max_flow_m3h\":0,\"timestamp\":\"1111-11-11T11:11:11Z\"}'fields='WaterWater;33225544;123.529;0;1111-11-11 11:11.11'}}", false },
};
MapToDriver builtins_mvts_[] =
{
{ { MANUFACTURER_ELS,0x81,0x03 }, "elster" },
{ { MANUFACTURER_SEN,0x68,0x06 }, "iperl" },
{ { MANUFACTURER_SEN,0x68,0x07 }, "iperl" },
{ { MANUFACTURER_SEN,0x7c,0x07 }, "iperl" },
};

Wyświetl plik

@ -86,6 +86,9 @@ int main(int argc, char **argv)
setVersion(VERSION);
enableEarlyLoggingFromCommandLine(argc, argv);
prepareBuiltinDrivers();
auto config = parseCommandLine(argc, argv);
if (config->version)

Wyświetl plik

@ -1,5 +1,5 @@
/*
Copyright (C) 2017-2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2017-2024 Fredrik Öhrström (gpl-3.0-or-later)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,6 +17,7 @@
#include"bus.h"
#include"config.h"
#include"drivers.h"
#include"meters.h"
#include"meters_common_implementation.h"
#include"units.h"
@ -378,6 +379,7 @@ public:
void analyzeTelegram(AboutTelegram &about, vector<uchar> &input_frame, bool simulated)
{
loadAllBuiltinDrivers();
Telegram t;
t.about = about;

Wyświetl plik

@ -17,6 +17,7 @@
#include"bus.h"
#include"config.h"
#include"drivers.h"
#include"driver_dynamic.h"
#include"meters.h"
#include"meters_common_implementation.h"
@ -125,6 +126,10 @@ bool DriverInfo::isValidMedia(uchar type)
return false;
}
DriverInfo::~DriverInfo()
{
}
bool DriverInfo::isCloseEnoughMedia(uchar type)
{
for (auto &dd : detect_)
@ -198,11 +203,11 @@ bool registerDriver(function<void(DriverInfo&)> setup)
return true;
}
string loadDriver(const string &file)
string loadDriver(const string &file, const char *content)
{
DriverInfo di;
bool ok = DriverDynamic::load(&di, file);
bool ok = DriverDynamic::load(&di, file, content);
if (!ok)
{
error("Failed to load driver from file: %s\n", file.c_str());
@ -269,32 +274,47 @@ string loadDriver(const string &file)
bool lookupDriverInfo(const string& driver_name, DriverInfo *out_di)
{
// Lookup an already loaded driver, it might be compiled in as well.
DriverInfo *di = lookupDriver(driver_name);
if (di == NULL)
if (di)
{
if (!endsWith(driver_name, ".xmq") || !checkFileExists(driver_name.c_str()))
if (out_di) *out_di = *di;
return true;
}
// Lookup a dynamic text driver that can be loaded from memory.
if (loadBuiltinDriver(driver_name))
{
// It is loaded, lets fetch the DriverInfo.
di = lookupDriver(driver_name);
if (di)
{
return false;
}
// Ok, not built in, but it ends with .xmq and the file exists!
string new_name = loadDriver(driver_name);
// Check again if it was registered.
di = lookupDriver(new_name);
if (di == NULL)
{
return false;
if (out_di) *out_di = *di;
return true;
}
}
if (out_di != NULL)
// Is this a dynamic text driver file?
if (!endsWith(driver_name, ".xmq") || !checkFileExists(driver_name.c_str()))
{
*out_di = *di;
// Nope, give up.
return false;
}
return true;
string file_name = driver_name;
// Load the driver from the file.
string new_name = loadDriver(file_name, NULL);
// Check again if it was registered.
di = lookupDriver(new_name);
if (di)
{
if (out_di) *out_di = *di;
return true;
}
return false;
}
MeterCommonImplementation::MeterCommonImplementation(MeterInfo &mi,
@ -1980,13 +2000,20 @@ ELLSecurityMode MeterCommonImplementation::expectedELLSecurityMode()
void detectMeterDrivers(int manufacturer, int media, int version, vector<string> *drivers)
{
bool found = false;
for (DriverInfo *p : allDrivers())
{
if (p->detect(manufacturer, media, version))
{
drivers->push_back(p->name().str());
found = true;
}
}
if (!found)
{
const char *name = findBuiltinDriver(manufacturer, version, media);
if (name) drivers->push_back(name);
}
}
bool isMeterDriverValid(DriverName driver_name, int manufacturer, int media, int version)

Wyświetl plik

@ -192,6 +192,7 @@ private:
string dynamic_file_name_; // Name of actual loaded driver file.
public:
~DriverInfo();
DriverInfo() {};
void setName(std::string n) { name_ = n; }
void addNameAlias(std::string n) { name_aliases_.push_back(n); }
@ -236,7 +237,7 @@ DriverInfo pickMeterDriver(Telegram *t);
// Return true for mbus and S2/C2/T2 drivers.
bool driverNeedsPolling(DriverName& dn);
string loadDriver(const string &file);
string loadDriver(const string &file, const char *content);
vector<DriverInfo*>& allDrivers();

Wyświetl plik

@ -169,6 +169,8 @@ if [ "$?" != "0" ]; then RC="1"; fi
./tests/test_rtlwmbus_timestamps.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi
./build/xmq tests/generated_tests.xmq for-each /test --shell='./tests/testit.sh '$PROG' "${args}" "${telegram}" "${json}" "${fields}"'
./tests/test_drivers.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi

Wyświetl plik

@ -0,0 +1,21 @@
//2024-02-11_21:26
test {
args = 'Gas elster 05105025 NOKEY'
telegram = 3644A511640010253837722550100593158103E70020052F2F_0374E602000C137034220302FD74EE0F2F2F2F2F2F2F2F2F2F2F2F2F2F2F
json = '{"media":"gas","meter":"elster","name":"Gas","id":"05105025","total_m3":3223.47,"timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Gas;05105025;3223.47;1111-11-11 11:11.11'
}
test {
args = 'WaterWater iperl 33225544 NOKEY'
comment = 'Test iPerl T1 telegram not encrypted, which has no 2f2f markers.'
telegram = 1844AE4C4455223368077A55000000_041389E20100023B0000
json = '{"media":"water","meter":"iperl","name":"WaterWater","id":"33225544","total_m3":123.529,"max_flow_m3h":0,"timestamp":"1111-11-11T11:11:11Z"}'
fields = 'WaterWater;33225544;123.529;0;1111-11-11 11:11.11'
}
test {
args = 'MoreWater iperl 12345699 NOKEY'
coment = 'Test iPerl T1 telegram, that after decryption, has 2f2f markers.'
telegram = 1E44AE4C9956341268077A36001000_2F2F0413181E0000023B00002F2F2F2F
json = '{"media":"water","meter":"iperl","name":"MoreWater","id":"12345699","total_m3":7.704,"max_flow_m3h":0,"timestamp":"1111-11-11T11:11:11Z"}'
fields = 'MoreWater;12345699;7.704;0;1111-11-11 11:11.11'
}

Wyświetl plik

@ -7,7 +7,7 @@ mkdir -p $TEST
performCheck() {
if [ "$?" = "0" ]
then
cat $TEST/test_output.txt | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_response.txt
cat $TEST/test_output.txt | grep -v == | grep -v \# | grep -v Indirect | grep -v Direct | grep -v -e "^$" | grep -v SUMMARY | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_response.txt
diff $TEST/test_expected.txt $TEST/test_response.txt
if [ "$?" = "0" ]
then

Wyświetl plik

@ -70,7 +70,7 @@ METERS="MyWarmWater supercom587 12345678 NOKEY
cat simulations/simulation_t1.txt | grep '^{' | jq --sort-keys . > $TEST/test_expected.txt
$PROG --format=json simulations/simulation_t1.txt $METERS 2> $TEST/test_stderr.txt | jq --sort-keys . > $TEST/test_output.txt
$PROG --format=json simulations/simulation_t1.txt $METERS | jq --sort-keys . > $TEST/test_output.txt
if [ "$?" = "0" ]
then
cat $TEST/test_output.txt | sed 's/"timestamp": "....-..-..T..:..:..Z"/"timestamp": "1111-11-11T11:11:11Z"/' > $TEST/test_responses.txt
@ -91,11 +91,10 @@ then
else
echo "wmbusmeters returned error code: $?"
cat $TEST/test_output.txt
cat $TEST/test_stderr.txt
fi
cat simulations/simulation_t1.txt | grep '^|' | sed 's/^|//' > $TEST/test_expected.txt
$PROG --format=fields simulations/simulation_t1.txt $METERS > $TEST/test_output.txt 2> $TEST/test_stderr.txt
$PROG --format=fields simulations/simulation_t1.txt $METERS > $TEST/test_output.txt
if [ "$?" = "0" ]
then
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
@ -116,7 +115,6 @@ then
else
echo "wmbusmeters returned error code: $?"
cat $TEST/test_output.txt
cat $TEST/test_stderr.txt
fi

54
tests/testit.sh 100755
Wyświetl plik

@ -0,0 +1,54 @@
#!/bin/bash
TEST=build/test
mkdir -p $TEST
PROG="$1"
ARGS="$2"
HEX="$3"
JSON="$4"
FIELDS="$5"
OK=true
rm -f $TEST/test_output.txt $TEST/test_expected.txt
$PROG --format=json $HEX $ARGS \
| jq . --sort-keys \
| sed 's/"timestamp": "....-..-..T..:..:..Z"/"timestamp": "1111-11-11T11:11:11Z"/' \
> $TEST/test_output.txt
echo "$JSON" | jq . --sort-keys > $TEST/test_expected.txt
if ! diff $TEST/test_expected.txt $TEST/test_output.txt
then
if [ "$USE_MELD" = "true" ]
then
meld $TEST/test_expected.txt $TEST/test_output.txt
fi
OK=false
fi
rm -f $TEST/test_output.txt $TEST/test_expected.txt
$PROG --format=fields $HEX $ARGS \
| sed 's/....-..-.. ..:..:../1111-11-11 11:11.11/' \
> $TEST/test_output.txt
echo "$FIELDS" > $TEST/test_expected.txt
if ! diff $TEST/test_expected.txt $TEST/test_output.txt
then
if [ "$USE_MELD" = "true" ]
then
meld $TEST/test_expected.txt $TEST/test_output.txt
fi
OK=false
fi
if [ "$OK" = "true" ]
then
echo "OK: $ARGS"
else
echo "ERROR: $ARGS $TELEGRAM"
fi