kopia lustrzana https://github.com/weetmuts/wmbusmeters
Merge master.
commit
27a590e135
5
CHANGES
5
CHANGES
|
@ -1,4 +1,9 @@
|
|||
|
||||
Added support for detection of the proper driver
|
||||
based on the manufacturer, media and version fields in the telegram.
|
||||
This driver is printed when listening without specifying any meters.
|
||||
The driver will be reported as unknown! for meters not yet supported by wmbusmeters.
|
||||
|
||||
Avandorp added support for the AquaMetro / Integra Topas Es Kr water meter.
|
||||
Thanks Avandorp!
|
||||
|
||||
|
|
1
Makefile
1
Makefile
|
@ -125,6 +125,7 @@ METER_OBJS:=\
|
|||
$(BUILD)/meter_hydrodigit.o \
|
||||
$(BUILD)/meter_iperl.o \
|
||||
$(BUILD)/meter_izar.o \
|
||||
$(BUILD)/meter_izar3.o \
|
||||
$(BUILD)/meter_lansendw.o \
|
||||
$(BUILD)/meter_lansensm.o \
|
||||
$(BUILD)/meter_lansenth.o \
|
||||
|
|
18
README.md
18
README.md
|
@ -236,6 +236,9 @@ Sensus iPERL (iperl)
|
|||
Techem MK Radio 3 (mkradio3) (non-standard protocol)
|
||||
Waterstar M (waterstarm)
|
||||
|
||||
Currently not supported, please help!
|
||||
Diehl/Sappel ACQUARIUS/IZAR R3 (izar3)
|
||||
|
||||
Supported heat cost allocators:
|
||||
Innotas EurisII (eurisii)
|
||||
Qundis Q caloric (qcaloric)
|
||||
|
@ -280,16 +283,25 @@ and T1 telegrams at the same time.
|
|||
# Usage examples
|
||||
|
||||
```
|
||||
wmbusmeters --listento=t1 /dev/ttyUSB1:amb8465
|
||||
wmbusmeters --listento=c1 /dev/ttyUSB1:amb8465
|
||||
```
|
||||
|
||||
Simply runs a scan with mode T1 to search for meters and print the IDs
|
||||
Simply runs a scan with mode C1 to search for meters and print the IDs and any detected driver,
|
||||
for example:
|
||||
```
|
||||
Received telegram from: 12345678
|
||||
manufacturer: (KAM) Kamstrup Energi (0x2c2d)
|
||||
device type: Cold water meter (0x16)
|
||||
device ver: 0x1b
|
||||
device driver: multical21
|
||||
```
|
||||
|
||||
Now listen to this specific meter.
|
||||
|
||||
```
|
||||
wmbusmeters /dev/ttyUSB0:im871a MyTapWater multical21:c1 12345678 00112233445566778899AABBCCDDEEFF
|
||||
```
|
||||
|
||||
|
||||
(The :c1 can be left out, since multical21 only transmits c1 telegrams. The suffix
|
||||
with the expected link mode might be necessary for other meters, like apator162 for example.
|
||||
The Multical21 uses compressed telegrams, which means that you might have to wait up to 8 telegrams
|
||||
|
|
|
@ -67,11 +67,11 @@ telegram=|2e44333003020100071b7a634820252f2f0265840842658308820165950802fb1aae01
|
|||
# Test Lansen door window telegram
|
||||
|
||||
telegram=|2e44333005020100071d7ab54800002f2f02fd1b110002fd971d01000efd3a2200000000008e40fd3a000000000000|
|
||||
{"media":"reserved","meter":"lansensm","name":"Dooro","id":"00010205","status":"CLOSED","timestamp":"1111-11-11T11:11:11Z"}
|
||||
{"media":"reserved","meter":"lansendw","name":"Dooro","id":"00010205","status":"CLOSED","timestamp":"1111-11-11T11:11:11Z"}
|
||||
|Dooro;00010205;CLOSED;1111-11-11 11:11.11
|
||||
|
||||
telegram=|2e44333005020100071d7ab66800002f2f02fd1b550002fd971d01000efd3a2300000000008e40fd3a000000000000|
|
||||
{"media":"reserved","meter":"lansensm","name":"Dooro","id":"00010205","status":"OPEN","timestamp":"1111-11-11T11:11:11Z"}
|
||||
{"media":"reserved","meter":"lansendw","name":"Dooro","id":"00010205","status":"OPEN","timestamp":"1111-11-11T11:11:11Z"}
|
||||
|Dooro;00010205;OPEN;1111-11-11 11:11.11
|
||||
|
||||
# Test Lansen pulse counter
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
# Test a broken telegram which MeterType cannot be detected from the telegram mfct,media and version.
|
||||
|
||||
telegram=|2e4433300502010007ff7ab66800002f2f02fd1b550002fd971d01000efd3a2300000000008e40fd3a000000000000|
|
||||
|
||||
# Now use a correct telegram but supply the wrong meter driver in the test.
|
||||
|
||||
telegram=|2e44333006020100071d7ab66800002f2f02fd1b550002fd971d01000efd3a2300000000008e40fd3a000000000000|
|
|
@ -42,24 +42,12 @@ private:
|
|||
};
|
||||
|
||||
MeterAmiplus::MeterAmiplus(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::AMIPLUS, 0)
|
||||
MeterCommonImplementation(mi, MeterType::AMIPLUS)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
// This is one manufacturer of Amiplus compatible meters.
|
||||
addManufacturer(MANUFACTURER_APA);
|
||||
addMedia(0x02); // Electricity meter
|
||||
|
||||
// This is another manufacturer
|
||||
addManufacturer(MANUFACTURER_DEV);
|
||||
// Oddly, this device has not been configured to send as a electricity meter,
|
||||
// but instead a device/media type that is used for gateway or relays or something?
|
||||
addMedia(0x37); // Radio converter (meter side)
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x02);
|
||||
|
||||
addPrint("total_energy_consumption", Quantity::Energy,
|
||||
[&](Unit u){ return totalEnergyConsumption(u); },
|
||||
"The total energy consumption recorded by this meter.",
|
||||
|
|
|
@ -44,16 +44,14 @@ unique_ptr<WaterMeter> createApator08(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterApator08::MeterApator08(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::APATOR08, 0x8614) // Not compliant! Will decode to APT.
|
||||
MeterCommonImplementation(mi, MeterType::APATOR08)
|
||||
{
|
||||
// manufacturer 0x8614 is not compliant with flags encoding.
|
||||
// forced decode will decode to APT.
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x03);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x03);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
"The total water consumption recorded by this meter.",
|
||||
|
|
|
@ -43,18 +43,13 @@ unique_ptr<WaterMeter> createApator162(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterApator162::MeterApator162(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::APATOR162, MANUFACTURER_APA)
|
||||
MeterCommonImplementation(mi, MeterType::APATOR162)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x06);
|
||||
addMedia(0x07);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
addLinkMode(LinkMode::C1);
|
||||
|
||||
addExpectedVersion(0x05);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
"The total water consumption recorded by this meter.",
|
||||
|
|
|
@ -36,16 +36,12 @@ private:
|
|||
};
|
||||
|
||||
MeterCMa12w::MeterCMa12w(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::CMA12W, MANUFACTURER_ELV)
|
||||
MeterCommonImplementation(mi, MeterType::CMA12W)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x1b);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x20);
|
||||
|
||||
addPrint("current_temperature", Quantity::Temperature,
|
||||
[&](Unit u){ return currentTemperature(u); },
|
||||
"The current temperature.",
|
||||
|
|
|
@ -46,16 +46,14 @@ unique_ptr<HeatMeter> createCompact5(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterCompact5::MeterCompact5(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::COMPACT5, MANUFACTURER_TCH)
|
||||
MeterCommonImplementation(mi, MeterType::COMPACT5)
|
||||
{
|
||||
addMedia(0x04); // C telegrams
|
||||
addMedia(0xC3); // T telegrams
|
||||
// media 0x04 is used for C telegrams
|
||||
// media 0xC3 is used for T telegrams
|
||||
|
||||
addLinkMode(LinkMode::C1);
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x45);
|
||||
|
||||
addPrint("total", Quantity::Energy,
|
||||
[&](Unit u){ return totalEnergyConsumption(u); },
|
||||
"The total energy consumption recorded by this meter.",
|
||||
|
|
|
@ -45,17 +45,15 @@ private:
|
|||
};
|
||||
|
||||
MeterEBZWMBE::MeterEBZWMBE(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::EBZWMBE, MANUFACTURER_EBZ)
|
||||
MeterCommonImplementation(mi, MeterType::EBZWMBE)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_NO_IV);
|
||||
|
||||
// The eBZ wWMB E01 is an addons to the electricity meters
|
||||
addMedia(0x37); // Radio converter (meter side)
|
||||
// media 0x37 Radio converter (meter side)
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x02);
|
||||
|
||||
addPrint("total_energy_consumption", Quantity::Energy,
|
||||
[&](Unit u){ return totalEnergyConsumption(u); },
|
||||
"The total energy consumption recorded by this meter.",
|
||||
|
|
|
@ -43,16 +43,12 @@ private:
|
|||
};
|
||||
|
||||
MeterEHZP::MeterEHZP(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::EHZP, MANUFACTURER_EMH)
|
||||
MeterCommonImplementation(mi, MeterType::EHZP)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_NO_IV);
|
||||
|
||||
addMedia(0x02); // Electricity meter
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x02);
|
||||
|
||||
addPrint("total_energy_consumption", Quantity::Energy,
|
||||
[&](Unit u){ return totalEnergyConsumption(u); },
|
||||
"The total energy consumption recorded by this meter.",
|
||||
|
|
|
@ -62,17 +62,15 @@ private:
|
|||
};
|
||||
|
||||
MeterESYSWM::MeterESYSWM(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::ESYSWM, MANUFACTURER_ESY)
|
||||
MeterCommonImplementation(mi, MeterType::ESYSWM)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_NO_IV);
|
||||
|
||||
// The ESYS-WM-20 and ESYS-WM15 are addons to the electricity meters.
|
||||
addMedia(0x37); // Radio converter (meter side)
|
||||
// media 0x37 Radio converter (meter side)
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x30);
|
||||
|
||||
addPrint("total_energy_consumption", Quantity::Energy,
|
||||
[&](Unit u){ return totalEnergyConsumption(u); },
|
||||
"The total energy consumption recorded by this meter.",
|
||||
|
|
|
@ -42,16 +42,12 @@ private:
|
|||
};
|
||||
|
||||
MeterEurisII::MeterEurisII(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::EURISII, MANUFACTURER_INE)
|
||||
MeterCommonImplementation(mi, MeterType::EURISII)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x08);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x55);
|
||||
|
||||
addPrint("current_consumption", Quantity::HCA,
|
||||
[&](Unit u){ return currentConsumption(u); },
|
||||
"The current heat cost allocation.",
|
||||
|
|
|
@ -56,10 +56,9 @@ unique_ptr<HeatCostMeter> createFHKVDataIII(MeterInfo &mi)
|
|||
|
||||
|
||||
MeterFHKVDataIII::MeterFHKVDataIII(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::FHKVDATAIII, MANUFACTURER_TCH)
|
||||
MeterCommonImplementation(mi, MeterType::FHKVDATAIII)
|
||||
{
|
||||
addMedia(0x80); // T telegrams
|
||||
addExpectedVersion(0x69);
|
||||
// media 0x80 T telegrams
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addPrint("current", Quantity::HCA,
|
||||
|
|
|
@ -44,12 +44,10 @@ unique_ptr<WaterMeter> createHydrodigit(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterHydrodigit::MeterHydrodigit(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::HYDRODIGIT, MANUFACTURER_BMT)
|
||||
MeterCommonImplementation(mi, MeterType::HYDRODIGIT)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x07);
|
||||
addExpectedVersion(0x13);
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
|
|
|
@ -45,16 +45,12 @@ private:
|
|||
};
|
||||
|
||||
MeterHydrus::MeterHydrus(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::HYDRUS, MANUFACTURER_DME)
|
||||
MeterCommonImplementation(mi, MeterType::HYDRUS)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x07);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x70);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
"The total water consumption recorded by this meter.",
|
||||
|
|
|
@ -41,17 +41,14 @@ private:
|
|||
};
|
||||
|
||||
MeterIperl::MeterIperl(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::IPERL, MANUFACTURER_SEN)
|
||||
MeterCommonImplementation(mi, MeterType::IPERL)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x06);
|
||||
addMedia(0x07);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x68);
|
||||
addExpectedVersion(0x7c); // Sensus 640
|
||||
// version 0x68
|
||||
// version 0x7c Sensus 640
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
|
|
|
@ -81,10 +81,8 @@ unique_ptr<WaterMeter> createIzar(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterIzar::MeterIzar(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::IZAR, MANUFACTURER_SAP)
|
||||
MeterCommonImplementation(mi, MeterType::IZAR)
|
||||
{
|
||||
addManufacturer(MANUFACTURER_DME);
|
||||
|
||||
MeterKeys *mk = meterKeys();
|
||||
if (!mk->confidentiality_key.empty())
|
||||
keys.push_back(convertKey(mk->confidentiality_key));
|
||||
|
@ -96,9 +94,9 @@ MeterIzar::MeterIzar(MeterInfo &mi) :
|
|||
keys.push_back(convertKey(PRIOS_DEFAULT_KEY2));
|
||||
}
|
||||
|
||||
addMedia(0x01); // Oil meter? why?
|
||||
addMedia(0x15); // Hot water
|
||||
addMedia(0x66); // Woot?
|
||||
// media 0x01 Oil meter? why?
|
||||
// media 0x15 Hot water
|
||||
// medua 0x66 Woot?
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
Copyright (C) 2020 Fredrik Öhrström
|
||||
|
||||
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.h"
|
||||
#include"meters_common_implementation.h"
|
||||
#include"wmbus.h"
|
||||
#include"wmbus_utils.h"
|
||||
|
||||
#include<algorithm>
|
||||
#include<stdbool.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct MeterIzar3 : public virtual WaterMeter, public virtual MeterCommonImplementation {
|
||||
MeterIzar3(MeterInfo &mi);
|
||||
|
||||
double totalWaterConsumption(Unit u);
|
||||
bool hasTotalWaterConsumption();
|
||||
|
||||
private:
|
||||
|
||||
void processContent(Telegram *t);
|
||||
double total_water_consumption_l_ {};
|
||||
};
|
||||
|
||||
unique_ptr<WaterMeter> createIzar3(MeterInfo &mi)
|
||||
{
|
||||
return unique_ptr<WaterMeter>(new MeterIzar3(mi));
|
||||
}
|
||||
|
||||
MeterIzar3::MeterIzar3(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::IZAR3)
|
||||
{
|
||||
// We do not know how to decode the IZAR r3 aka Diehl AQUARIUS!
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
"The total water consumption recorded by this meter.",
|
||||
true, true);
|
||||
}
|
||||
|
||||
double MeterIzar3::totalWaterConsumption(Unit u)
|
||||
{
|
||||
assertQuantity(u, Quantity::Volume);
|
||||
return convert(total_water_consumption_l_, Unit::L, u);
|
||||
}
|
||||
|
||||
bool MeterIzar3::hasTotalWaterConsumption()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeterIzar3::processContent(Telegram *t)
|
||||
{
|
||||
vector<uchar> frame;
|
||||
t->extractFrame(&frame);
|
||||
|
||||
warning("(izar3) cannot decode content of telegram!\n");
|
||||
total_water_consumption_l_ = 123456789;
|
||||
}
|
|
@ -41,16 +41,12 @@ private:
|
|||
};
|
||||
|
||||
MeterLansenDW::MeterLansenDW(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::LANSENSM, MANUFACTURER_LAS)
|
||||
MeterCommonImplementation(mi, MeterType::LANSENDW)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x1d);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x07);
|
||||
|
||||
addPrint("status", Quantity::Text,
|
||||
[&](){ return status(); },
|
||||
"The current status: OPEN or CLOSED.",
|
||||
|
|
|
@ -39,16 +39,14 @@ private:
|
|||
};
|
||||
|
||||
MeterLansenPU::MeterLansenPU(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::LANSENPU, MANUFACTURER_LAS)
|
||||
MeterCommonImplementation(mi, MeterType::LANSENPU)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x00);
|
||||
|
||||
// version 0x14 for which we have a test telegram
|
||||
// other version 0x0b reported, but we lack telegram
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x14);
|
||||
|
||||
addPrint("counter_a", Quantity::Counter,
|
||||
[&](Unit u) { assertQuantity(u, Quantity::Counter); return counterA(); },
|
||||
"The current number of counted pulses from counter a.",
|
||||
|
|
|
@ -41,16 +41,12 @@ private:
|
|||
};
|
||||
|
||||
MeterLansenSM::MeterLansenSM(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::LANSENSM, MANUFACTURER_LAS)
|
||||
MeterCommonImplementation(mi, MeterType::LANSENSM)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x1a);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x03);
|
||||
|
||||
addPrint("status", Quantity::Text,
|
||||
[&](){ return status(); },
|
||||
"The current status: OK, SMOKE, TEST or 'SMOKE TEST'.",
|
||||
|
|
|
@ -40,16 +40,12 @@ private:
|
|||
};
|
||||
|
||||
MeterLansenTH::MeterLansenTH(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::LANSENTH, MANUFACTURER_LAS)
|
||||
MeterCommonImplementation(mi, MeterType::LANSENTH)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x1b);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x07);
|
||||
|
||||
addPrint("current_temperature", Quantity::Temperature,
|
||||
[&](Unit u){ return currentTemperature(u); },
|
||||
"The current temperature.",
|
||||
|
|
|
@ -41,17 +41,12 @@ private:
|
|||
};
|
||||
|
||||
MKRadio3::MKRadio3(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::MKRADIO3, MANUFACTURER_TCH)
|
||||
MeterCommonImplementation(mi, MeterType::MKRADIO3)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x62);
|
||||
addMedia(0x72);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x74);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
"The total water consumption recorded by this meter.",
|
||||
|
|
|
@ -92,22 +92,12 @@ private:
|
|||
};
|
||||
|
||||
MeterMultical21::MeterMultical21(MeterInfo &mi, MeterType mt) :
|
||||
MeterCommonImplementation(mi, mt, MANUFACTURER_KAM)
|
||||
MeterCommonImplementation(mi, mt)
|
||||
{
|
||||
setExpectedELLSecurityMode(ELLSecurityMode::AES_CTR);
|
||||
|
||||
addMedia(0x16); // Water media
|
||||
|
||||
addLinkMode(LinkMode::C1);
|
||||
|
||||
if (type() == MeterType::MULTICAL21) {
|
||||
addExpectedVersion(0x1b);
|
||||
} else if (type() == MeterType::FLOWIQ3100) {
|
||||
addExpectedVersion(0x1d);
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
"The total water consumption recorded by this meter.",
|
||||
|
|
|
@ -52,13 +52,10 @@ private:
|
|||
};
|
||||
|
||||
MeterMultical302::MeterMultical302(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::MULTICAL302, MANUFACTURER_KAM)
|
||||
MeterCommonImplementation(mi, MeterType::MULTICAL302)
|
||||
{
|
||||
setExpectedELLSecurityMode(ELLSecurityMode::AES_CTR);
|
||||
|
||||
addMedia(0x04); // Heat media
|
||||
addMedia(0x0d); // Heat/Cooling load
|
||||
addExpectedVersion(0x30);
|
||||
addLinkMode(LinkMode::C1);
|
||||
|
||||
addPrint("total_energy_consumption", Quantity::Energy,
|
||||
|
|
|
@ -61,15 +61,10 @@ private:
|
|||
};
|
||||
|
||||
MeterMultical403::MeterMultical403(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::MULTICAL403, MANUFACTURER_KAM)
|
||||
MeterCommonImplementation(mi, MeterType::MULTICAL403)
|
||||
{
|
||||
setExpectedELLSecurityMode(ELLSecurityMode::AES_CTR);
|
||||
|
||||
addMedia(0x0a); // Heat/Cooling load
|
||||
addMedia(0x0b); // Heat/Cooling load
|
||||
addMedia(0x0c); // Heat/Cooling load
|
||||
addMedia(0x0d); // Heat/Cooling load
|
||||
addExpectedVersion(0x34);
|
||||
addLinkMode(LinkMode::C1);
|
||||
|
||||
addPrint("total_energy_consumption", Quantity::Energy,
|
||||
|
|
|
@ -40,16 +40,12 @@ unique_ptr<ElectricityMeter> createOmnipower(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterOmnipower::MeterOmnipower(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::OMNIPOWER, MANUFACTURER_KAM)
|
||||
MeterCommonImplementation(mi, MeterType::OMNIPOWER)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x02);
|
||||
|
||||
addLinkMode(LinkMode::C1);
|
||||
|
||||
addExpectedVersion(0x01);
|
||||
|
||||
addPrint("total_energy_consumption", Quantity::Energy,
|
||||
[&](Unit u){ return totalEnergyConsumption(u); },
|
||||
"The total energy consumption recorded by this meter.",
|
||||
|
|
|
@ -48,16 +48,12 @@ unique_ptr<WaterMeter> createQ400(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterQ400::MeterQ400(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::Q400, MANUFACTURER_AXI)
|
||||
MeterCommonImplementation(mi, MeterType::Q400)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x07);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x10);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
"The total water consumption recorded by this meter.",
|
||||
|
|
|
@ -46,16 +46,12 @@ private:
|
|||
};
|
||||
|
||||
MeterQCaloric::MeterQCaloric(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::QCALORIC, MANUFACTURER_QDS)
|
||||
MeterCommonImplementation(mi, MeterType::QCALORIC)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x08);
|
||||
|
||||
addLinkMode(LinkMode::C1);
|
||||
|
||||
addExpectedVersion(0x35);
|
||||
|
||||
addPrint("current_consumption", Quantity::HCA,
|
||||
[&](Unit u){ return currentConsumption(u); },
|
||||
"The current heat cost allocation.",
|
||||
|
|
|
@ -59,16 +59,12 @@ private:
|
|||
};
|
||||
|
||||
MeterRfmAmb::MeterRfmAmb(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::RFMAMB, MANUFACTURER_BMT)
|
||||
MeterCommonImplementation(mi, MeterType::RFMAMB)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x1b);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x10);
|
||||
|
||||
addPrint("current_temperature", Quantity::Temperature,
|
||||
[&](Unit u){ return currentTemperature(u); },
|
||||
"The current temperature.",
|
||||
|
|
|
@ -44,12 +44,10 @@ unique_ptr<WaterMeter> createRfmTX1(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterRfmTX1::MeterRfmTX1(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::RFMTX1, MANUFACTURER_BMT)
|
||||
MeterCommonImplementation(mi, MeterType::RFMTX1)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x07);
|
||||
addExpectedVersion(0x05);
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
|
|
|
@ -43,17 +43,12 @@ unique_ptr<WaterMeter> createSupercom587(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterSupercom587::MeterSupercom587(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::SUPERCOM587, MANUFACTURER_SON)
|
||||
MeterCommonImplementation(mi, MeterType::SUPERCOM587)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x06);
|
||||
addMedia(0x07);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x3c);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
"The total water consumption recorded by this meter.",
|
||||
|
|
|
@ -72,17 +72,15 @@ unique_ptr<WaterMeter> createTopasEsKr(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterTopasEsKr::MeterTopasEsKr(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::TOPASESKR, MANUFACTURER_AMT)
|
||||
MeterCommonImplementation(mi, MeterType::TOPASESKR)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x06); // specified temperature range is 0°C to 50 °C, not sure it ever reports 0x06 for warm water, possibly configurable
|
||||
addMedia(0x07);
|
||||
// media 0x06 specified temperature range is 0°C to 50 °C, not sure it ever reports 0x06 for warm water, possibly configurable
|
||||
// media 0x07 used
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0xf1);
|
||||
|
||||
addPrint("total", Quantity::Volume,
|
||||
[&](Unit u){ return totalWaterConsumption(u); },
|
||||
"The total water consumption recorded by this meter.",
|
||||
|
|
|
@ -46,16 +46,14 @@ unique_ptr<HeatMeter> createVario451(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterVario451::MeterVario451(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::VARIO451, MANUFACTURER_TCH)
|
||||
MeterCommonImplementation(mi, MeterType::VARIO451)
|
||||
{
|
||||
addMedia(0x04); // C telegrams
|
||||
addMedia(0xC3); // T telegrams
|
||||
// media 0x04 C telegrams
|
||||
// media 0xC3 T telegrams
|
||||
|
||||
addLinkMode(LinkMode::C1);
|
||||
addLinkMode(LinkMode::T1);
|
||||
|
||||
addExpectedVersion(0x27);
|
||||
|
||||
addPrint("total", Quantity::Energy,
|
||||
[&](Unit u){ return totalEnergyConsumption(u); },
|
||||
"The total energy consumption recorded by this meter.",
|
||||
|
|
|
@ -50,17 +50,13 @@ unique_ptr<WaterMeter> createWaterstarM(MeterInfo &mi)
|
|||
}
|
||||
|
||||
MeterWaterstarM::MeterWaterstarM(MeterInfo &mi) :
|
||||
MeterCommonImplementation(mi, MeterType::WATERSTARM, MANUFACTURER_DWZ)
|
||||
MeterCommonImplementation(mi, MeterType::WATERSTARM)
|
||||
{
|
||||
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
|
||||
|
||||
addMedia(0x06);
|
||||
|
||||
addLinkMode(LinkMode::T1);
|
||||
addLinkMode(LinkMode::C1);
|
||||
|
||||
addExpectedVersion(0x02);
|
||||
|
||||
addPrint("meter_timestamp", Quantity::Text,
|
||||
[&](){ return meter_timestamp_; },
|
||||
"Date time for this reading.",
|
||||
|
|
|
@ -26,8 +26,7 @@
|
|||
#include<time.h>
|
||||
|
||||
MeterCommonImplementation::MeterCommonImplementation(MeterInfo &mi,
|
||||
MeterType type,
|
||||
int manufacturer) :
|
||||
MeterType type) :
|
||||
type_(type), name_(mi.name)
|
||||
{
|
||||
ids_ = splitMatchExpressions(mi.id);
|
||||
|
@ -38,10 +37,7 @@ MeterCommonImplementation::MeterCommonImplementation(MeterInfo &mi,
|
|||
/*if (bus->type() == DEVICE_SIMULATOR)
|
||||
{
|
||||
meter_keys_.simulation = true;
|
||||
}*/
|
||||
if (manufacturer) {
|
||||
manufacturers_.insert(manufacturer);
|
||||
}
|
||||
}*/
|
||||
for (auto s : mi.shells) {
|
||||
addShell(s);
|
||||
}
|
||||
|
@ -84,16 +80,6 @@ MeterType MeterCommonImplementation::type()
|
|||
return type_;
|
||||
}
|
||||
|
||||
vector<int> MeterCommonImplementation::media()
|
||||
{
|
||||
return media_;
|
||||
}
|
||||
|
||||
void MeterCommonImplementation::addMedia(int m)
|
||||
{
|
||||
media_.push_back(m);
|
||||
}
|
||||
|
||||
void MeterCommonImplementation::addLinkMode(LinkMode lm)
|
||||
{
|
||||
link_modes_.addLinkMode(lm);
|
||||
|
@ -120,11 +106,6 @@ void MeterCommonImplementation::addPrint(string vname, Quantity vquantity,
|
|||
prints_.push_back( { vname, vquantity, defaultUnitForQuantity(vquantity), NULL, getValueFunc, help, field, json } );
|
||||
}
|
||||
|
||||
void MeterCommonImplementation::addManufacturer(int m)
|
||||
{
|
||||
manufacturers_.insert(m);
|
||||
}
|
||||
|
||||
vector<string> MeterCommonImplementation::ids()
|
||||
{
|
||||
return ids_;
|
||||
|
@ -203,23 +184,16 @@ bool MeterCommonImplementation::isTelegramForMe(Telegram *t)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (manufacturers_.size() > 0 && manufacturers_.count(t->dll_mfct) == 0)
|
||||
if (!isMeterDriverValid(type_, t->dll_mfct, t->dll_type, t->dll_version))
|
||||
{
|
||||
// We are not that strict for the manufacturer.
|
||||
// Simply warn.
|
||||
warning("(meter) %s: probably not for me since manufacturer differs\n", name_.c_str());
|
||||
}
|
||||
|
||||
bool media_match = false;
|
||||
for (auto m : media_) {
|
||||
if (m == t->dll_type) {
|
||||
media_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!media_match) {
|
||||
warning("(meter) %s: probably not for me since received media 0x%02x does not match\n", name_.c_str(), t->dll_type);
|
||||
// Are we using the right driver? Perhaps not since
|
||||
// this particular driver, mfct, media, version combo
|
||||
// is not registered in the METER_DETECTION list in meters.h
|
||||
string possible_drivers = t->autoDetectPossibleDrivers();
|
||||
warning("(meter) %s: meter detection did not match the selected driver %s! correct driver is: %s\n",
|
||||
name_.c_str(),
|
||||
toMeterName(type()).c_str(),
|
||||
possible_drivers.c_str());
|
||||
}
|
||||
|
||||
debug("(meter) %s: yes for me\n", name_.c_str());
|
||||
|
@ -380,11 +354,6 @@ bool MeterCommonImplementation::handleTelegram(vector<uchar> input_frame)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!isExpectedVersion(t.dll_version))
|
||||
{
|
||||
warning("(%s) unexpected meter version 0x%02x !\n", meterName().c_str(), t.dll_version);
|
||||
}
|
||||
|
||||
char log_prefix[256];
|
||||
snprintf(log_prefix, 255, "(%s) log", meterName().c_str());
|
||||
logTelegram(log_prefix, t.frame, t.header_size, t.suffix_size);
|
||||
|
@ -551,12 +520,19 @@ ELLSecurityMode MeterCommonImplementation::expectedELLSecurityMode()
|
|||
return expected_ell_sec_mode_;
|
||||
}
|
||||
|
||||
void MeterCommonImplementation::addExpectedVersion(int version)
|
||||
void detectMeterDriver(int manufacturer, int media, int version, vector<string> *drivers)
|
||||
{
|
||||
expected_versions_.insert(version);
|
||||
drivers->clear();
|
||||
#define X(TY,MA,ME,VE) { if (manufacturer == MA && (media == ME || ME == -1) && (version == VE || VE == -1)) { drivers->push_back(toMeterName(MeterType::TY)); }}
|
||||
METER_DETECTION
|
||||
#undef X
|
||||
}
|
||||
|
||||
bool MeterCommonImplementation::isExpectedVersion(int version)
|
||||
bool isMeterDriverValid(MeterType type, int manufacturer, int media, int version)
|
||||
{
|
||||
return expected_versions_.size() == 0 || expected_versions_.count(version) > 0;
|
||||
#define X(TY,MA,ME,VE) { if (type == MeterType::TY && manufacturer == MA && (media == ME || ME == -1) && (version == VE || VE == -1)) { return true; }}
|
||||
METER_DETECTION
|
||||
#undef X
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
82
src/meters.h
82
src/meters.h
|
@ -41,6 +41,7 @@
|
|||
X(hydrodigit, T1_bit, Water, HYDRODIGIT, Hydrodigit) \
|
||||
X(iperl, T1_bit, Water, IPERL, Iperl) \
|
||||
X(izar, T1_bit, Water, IZAR, Izar) \
|
||||
X(izar3, T1_bit, Water, IZAR3, Izar3) \
|
||||
X(lansensm, T1_bit, Smoke, LANSENSM, LansenSM) \
|
||||
X(lansenth, T1_bit, TempHygro, LANSENTH, LansenTH) \
|
||||
X(lansendw, T1_bit, DoorWindow, LANSENDW, LansenDW) \
|
||||
|
@ -60,6 +61,70 @@
|
|||
X(topaseskr, T1_bit, Water, TOPASESKR, TopasEsKr) \
|
||||
|
||||
|
||||
// List of numbers that can be used to detect the meter driver
|
||||
// from a telegram. Currently these values are checked against
|
||||
// the outermost DLL layer. Thus this cannot handle if a telegram
|
||||
// is relayed and the meter telegram is wrapped in an outer
|
||||
// DLL which identifies the relayer. Something to fix in the future
|
||||
// is someone reports problems using a relay.
|
||||
//
|
||||
// The future solution might have RELAY_DETECTION and
|
||||
// for such telegrams it will strip the outer layer and
|
||||
// recreate the inner telegram.
|
||||
//
|
||||
// meter driver, manufacturer, media, version
|
||||
//
|
||||
#define METER_DETECTION \
|
||||
X(AMIPLUS, MANUFACTURER_APA, 0x02, 0x02) \
|
||||
X(AMIPLUS, MANUFACTURER_DEV, 0x37, 0x02) \
|
||||
X(APATOR08, 0x8614/*APT?*/, 0x03, 0x03) \
|
||||
X(APATOR162, MANUFACTURER_APA, 0x06, 0x05) \
|
||||
X(APATOR162, MANUFACTURER_APA, 0x07, 0x05) \
|
||||
X(CMA12W, MANUFACTURER_ELV, 0x1b, 0x20) \
|
||||
X(COMPACT5, MANUFACTURER_TCH, 0x04, 0x45) \
|
||||
X(COMPACT5, MANUFACTURER_TCH, 0xc3, 0x45) \
|
||||
X(EBZWMBE, MANUFACTURER_EBZ, 0x37, 0x02) \
|
||||
X(EURISII, MANUFACTURER_INE, 0x08, 0x55) \
|
||||
X(EHZP, MANUFACTURER_EMH, 0x02, 0x02) \
|
||||
X(ESYSWM, MANUFACTURER_ESY, 0x37, 0x30) \
|
||||
X(FLOWIQ3100,MANUFACTURER_KAM, 0x16, 0x1d) \
|
||||
X(FHKVDATAIII,MANUFACTURER_TCH, 0x80, 0x69) \
|
||||
X(HYDRUS, MANUFACTURER_DME, 0x07, 0x70) \
|
||||
X(HYDRODIGIT,MANUFACTURER_BMT, 0x07, 0x13) \
|
||||
X(IPERL, MANUFACTURER_SEN, 0x06, 0x68) \
|
||||
X(IPERL, MANUFACTURER_SEN, 0x07, 0x68) \
|
||||
X(IPERL, MANUFACTURER_SEN, 0x07, 0x7c) \
|
||||
X(IZAR, MANUFACTURER_SAP, 0x01, -1) \
|
||||
X(IZAR, MANUFACTURER_SAP, 0x15, -1) \
|
||||
X(IZAR, MANUFACTURER_SAP, 0x66, -1) \
|
||||
X(IZAR, MANUFACTURER_DME, 0x66, -1) \
|
||||
X(IZAR3, MANUFACTURER_SAP, 0x00, 0x88) \
|
||||
X(LANSENSM, MANUFACTURER_LAS, 0x1a, 0x03) \
|
||||
X(LANSENTH, MANUFACTURER_LAS, 0x1b, 0x07) \
|
||||
X(LANSENDW, MANUFACTURER_LAS, 0x1d, 0x07) \
|
||||
X(LANSENPU, MANUFACTURER_LAS, 0x00, 0x14) \
|
||||
X(LANSENPU, MANUFACTURER_LAS, 0x00, 0x0b) \
|
||||
X(MKRADIO3, MANUFACTURER_TCH, 0x62, 0x74) \
|
||||
X(MKRADIO3, MANUFACTURER_TCH, 0x72, 0x74) \
|
||||
X(MULTICAL21, MANUFACTURER_KAM, 0x16, 0x1b) \
|
||||
X(MULTICAL302,MANUFACTURER_KAM, 0x04, 0x30) \
|
||||
X(MULTICAL302,MANUFACTURER_KAM, 0x0d, 0x30) \
|
||||
X(MULTICAL403,MANUFACTURER_KAM, 0x0a, 0x34) \
|
||||
X(MULTICAL403,MANUFACTURER_KAM, 0x0b, 0x34) \
|
||||
X(MULTICAL403,MANUFACTURER_KAM, 0x0c, 0x34) \
|
||||
X(MULTICAL403,MANUFACTURER_KAM, 0x0d, 0x34) \
|
||||
X(OMNIPOWER, MANUFACTURER_KAM, 0x02, 0x01) \
|
||||
X(RFMAMB, MANUFACTURER_BMT, 0x1b, 0x10) \
|
||||
X(RFMTX1, MANUFACTURER_BMT, 0x07, 0x05) \
|
||||
X(Q400, MANUFACTURER_AXI, 0x07, 0x10) \
|
||||
X(QCALORIC, MANUFACTURER_QDS, 0x08, 0x35) \
|
||||
X(SUPERCOM587,MANUFACTURER_SON, 0x06, 0x3c) \
|
||||
X(SUPERCOM587,MANUFACTURER_SON, 0x07, 0x3c) \
|
||||
X(VARIO451, MANUFACTURER_TCH, 0x04, 0x27) \
|
||||
X(VARIO451, MANUFACTURER_TCH, 0xc3, 0x27) \
|
||||
X(WATERSTARM, MANUFACTURER_DWZ, 0x06, 0x02) \
|
||||
X(TOPASESKR, MANUFACTURER_AMT, 0x06, 0xf1) \
|
||||
X(TOPASESKR, MANUFACTURER_AMT, 0x07, 0xf1) \
|
||||
|
||||
enum class MeterType {
|
||||
#define X(mname,linkmode,info,type,cname) type,
|
||||
|
@ -68,6 +133,20 @@ LIST_OF_METERS
|
|||
UNKNOWN
|
||||
};
|
||||
|
||||
struct MeterMatch
|
||||
{
|
||||
MeterType driver;
|
||||
int manufacturer;
|
||||
int media;
|
||||
int version;
|
||||
};
|
||||
|
||||
// Return a list of matching drivers, like: multical21
|
||||
void detectMeterDriver(int manufacturer, int media, int version, std::vector<std::string> *drivers);
|
||||
// When entering the driver, check that the telegram is indeed known to be
|
||||
// compatible with the driver(type), if not then print a warning.
|
||||
bool isMeterDriverValid(MeterType type, int manufacturer, int media, int version);
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
@ -103,7 +182,6 @@ struct Meter
|
|||
virtual string meterName() = 0;
|
||||
virtual string name() = 0;
|
||||
virtual MeterType type() = 0;
|
||||
virtual vector<int> media() = 0;
|
||||
|
||||
virtual string datetimeOfUpdateHumanReadable() = 0;
|
||||
virtual string datetimeOfUpdateRobot() = 0;
|
||||
|
@ -123,7 +201,6 @@ struct Meter
|
|||
bool handleTelegram(vector<uchar> input_frame);
|
||||
virtual bool isTelegramForMe(Telegram *t) = 0;
|
||||
virtual MeterKeys *meterKeys() = 0;
|
||||
virtual bool isExpectedVersion(int version) = 0;
|
||||
|
||||
// Dynamically access all data received for the meter.
|
||||
virtual std::vector<std::string> getRecords() = 0;
|
||||
|
@ -242,6 +319,7 @@ unique_ptr<WaterMeter> createIperl(MeterInfo &m);
|
|||
unique_ptr<WaterMeter> createHydrus(MeterInfo &m);
|
||||
unique_ptr<WaterMeter> createHydrodigit(MeterInfo &m);
|
||||
unique_ptr<WaterMeter> createIzar(MeterInfo &m);
|
||||
unique_ptr<WaterMeter> createIzar3(MeterInfo &m);
|
||||
unique_ptr<WaterMeter> createQ400(MeterInfo &m);
|
||||
unique_ptr<HeatCostMeter> createQCaloric(MeterInfo &m);
|
||||
unique_ptr<HeatCostMeter> createEurisII(MeterInfo &m);
|
||||
|
|
|
@ -42,7 +42,6 @@ struct MeterCommonImplementation : public virtual Meter
|
|||
vector<string> fields();
|
||||
string name();
|
||||
MeterType type();
|
||||
vector<int> media();
|
||||
|
||||
ELLSecurityMode expectedELLSecurityMode();
|
||||
TPLSecurityMode expectedTPLSecurityMode();
|
||||
|
@ -60,7 +59,7 @@ struct MeterCommonImplementation : public virtual Meter
|
|||
double getRecordAsDouble(std::string record);
|
||||
uint16_t getRecordAsUInt16(std::string record);
|
||||
|
||||
MeterCommonImplementation(MeterInfo &mi, MeterType type, int manufacturer);
|
||||
MeterCommonImplementation(MeterInfo &mi, MeterType type);
|
||||
|
||||
~MeterCommonImplementation() = default;
|
||||
|
||||
|
@ -69,18 +68,14 @@ struct MeterCommonImplementation : public virtual Meter
|
|||
protected:
|
||||
|
||||
void triggerUpdate(Telegram *t);
|
||||
void addExpectedVersion(int version);
|
||||
void setExpectedELLSecurityMode(ELLSecurityMode dsm);
|
||||
void setExpectedTPLSecurityMode(TPLSecurityMode tsm);
|
||||
bool isExpectedVersion(int version);
|
||||
void addConversions(std::vector<Unit> cs);
|
||||
void addShell(std::string cmdline);
|
||||
void addJson(std::string json);
|
||||
std::vector<std::string> &shellCmdlines();
|
||||
std::vector<std::string> &additionalJsons();
|
||||
void addMedia(int media);
|
||||
void addLinkMode(LinkMode lm);
|
||||
void addManufacturer(int m);
|
||||
// Print with the default unit for this quantity.
|
||||
void addPrint(string vname, Quantity vquantity,
|
||||
function<double(Unit)> getValueFunc, string help, bool field, bool json);
|
||||
|
@ -107,9 +102,6 @@ private:
|
|||
MeterKeys meter_keys_ {};
|
||||
ELLSecurityMode expected_ell_sec_mode_ {};
|
||||
TPLSecurityMode expected_tpl_sec_mode_ {};
|
||||
set<int> expected_versions_;
|
||||
vector<int> media_;
|
||||
set<int> manufacturers_;
|
||||
string name_;
|
||||
vector<string> ids_;
|
||||
WMBus *bus_ {};
|
||||
|
|
85
src/wmbus.cc
85
src/wmbus.cc
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include"aescmac.h"
|
||||
#include"timings.h"
|
||||
#include"meters.h"
|
||||
#include"wmbus.h"
|
||||
#include"wmbus_utils.h"
|
||||
#include"dvparser.h"
|
||||
|
@ -191,7 +192,8 @@ LIST_OF_MANUFACTURERS
|
|||
|
||||
}
|
||||
|
||||
void Telegram::print() {
|
||||
void Telegram::print()
|
||||
{
|
||||
uchar a=0, b=0, c=0, d=0;
|
||||
if (dll_id.size() >= 4)
|
||||
{
|
||||
|
@ -201,17 +203,24 @@ void Telegram::print() {
|
|||
d = dll_id[3];
|
||||
}
|
||||
notice("Received telegram from: %02x%02x%02x%02x\n", a,b,c,d);
|
||||
notice(" manufacturer: (%s) %s\n",
|
||||
notice(" manufacturer: (%s) %s (0x%02x)\n",
|
||||
manufacturerFlag(dll_mfct).c_str(),
|
||||
manufacturer(dll_mfct).c_str());
|
||||
notice(" device type: %s\n",
|
||||
mediaType(dll_type).c_str());
|
||||
manufacturer(dll_mfct).c_str(),
|
||||
dll_mfct);
|
||||
notice(" device type: %s (0x%02x)\n", mediaType(dll_type).c_str(), dll_type);
|
||||
|
||||
notice(" device ver: 0x%02x\n", dll_version);
|
||||
|
||||
string possible_drivers = autoDetectPossibleDrivers();
|
||||
notice(" device driver: %s\n", possible_drivers.c_str());
|
||||
}
|
||||
|
||||
void Telegram::printDLL()
|
||||
{
|
||||
string possible_drivers = autoDetectPossibleDrivers();
|
||||
|
||||
string man = manufacturerFlag(dll_mfct);
|
||||
verbose("(telegram) DLL L=%02x C=%02x (%s) M=%04x (%s) A=%02x%02x%02x%02x VER=%02x TYPE=%02x (%s)\n",
|
||||
verbose("(telegram) DLL L=%02x C=%02x (%s) M=%04x (%s) A=%02x%02x%02x%02x VER=%02x TYPE=%02x (%s) (driver %s)\n",
|
||||
dll_len,
|
||||
dll_c, cType(dll_c).c_str(),
|
||||
dll_mfct,
|
||||
|
@ -219,7 +228,8 @@ void Telegram::printDLL()
|
|||
dll_id[0], dll_id[1], dll_id[2], dll_id[3],
|
||||
dll_version,
|
||||
dll_type,
|
||||
mediaType(dll_type).c_str());
|
||||
mediaType(dll_type).c_str(),
|
||||
possible_drivers.c_str());
|
||||
}
|
||||
|
||||
void Telegram::printELL()
|
||||
|
@ -290,45 +300,6 @@ void Telegram::printTPL()
|
|||
verbose("\n");
|
||||
}
|
||||
|
||||
void Telegram::verboseFields()
|
||||
{
|
||||
printDLL();
|
||||
printELL();
|
||||
printNWL();
|
||||
printAFL();
|
||||
printTPL();
|
||||
|
||||
/*
|
||||
if (ell_ci_field == 0x72) {
|
||||
// Long tpl header
|
||||
verbose(" CC-field=%02x (%s) long tpl header ACC=%02x SN=%02x%02x%02x%02x",
|
||||
cc_field, ccType(cc_field).c_str(),
|
||||
acc,
|
||||
sn[3],sn[2],sn[1],sn[0]);
|
||||
}
|
||||
|
||||
if (ell_ci_field == 0x7a) {
|
||||
// Short data header
|
||||
verbose(" CC-field=%02x (%s) short header ACC=%02x ",
|
||||
cc_field, ccType(cc_field).c_str(),
|
||||
acc,
|
||||
sn[3],sn[2],sn[1],sn[0]);
|
||||
}
|
||||
|
||||
if (ell_ci_field == 0x8d) {
|
||||
// ELL header
|
||||
verbose(" CC-field=%02x (%s) ell header ACC=%02x SN=%02x%02x%02x%02x",
|
||||
cc_field, ccType(cc_field).c_str(),
|
||||
acc,
|
||||
sn[3],sn[2],sn[1],sn[0]);
|
||||
}
|
||||
if (ell_ci_field == 0x8c) {
|
||||
verbose(" CC-field=%02x (%s) ACC=%02x",
|
||||
cc_field, ccType(cc_field).c_str(),
|
||||
acc);
|
||||
}*/
|
||||
}
|
||||
|
||||
string manufacturer(int m_field) {
|
||||
for (auto &m : manufacturers_) {
|
||||
if (m.m_field == m_field) return m.name;
|
||||
|
@ -1675,6 +1646,8 @@ bool Telegram::parse(vector<uchar> &input_frame, MeterKeys *mk)
|
|||
ok = parseDLL(pos);
|
||||
if (!ok) return false;
|
||||
|
||||
printDLL();
|
||||
|
||||
// ┌──────────────────────────────────────────────┐
|
||||
// │ │
|
||||
// │ Is this an ELL block? │
|
||||
|
@ -1684,6 +1657,8 @@ bool Telegram::parse(vector<uchar> &input_frame, MeterKeys *mk)
|
|||
ok = parseELL(pos);
|
||||
if (!ok) return false;
|
||||
|
||||
printELL();
|
||||
|
||||
// ┌──────────────────────────────────────────────┐
|
||||
// │ │
|
||||
// │ Is this an NWL block? │
|
||||
|
@ -1693,6 +1668,8 @@ bool Telegram::parse(vector<uchar> &input_frame, MeterKeys *mk)
|
|||
ok = parseNWL(pos);
|
||||
if (!ok) return false;
|
||||
|
||||
printNWL();
|
||||
|
||||
// ┌──────────────────────────────────────────────┐
|
||||
// │ │
|
||||
// │ Is this an AFL block? │
|
||||
|
@ -1702,6 +1679,8 @@ bool Telegram::parse(vector<uchar> &input_frame, MeterKeys *mk)
|
|||
ok = parseAFL(pos);
|
||||
if (!ok) return false;
|
||||
|
||||
printAFL();
|
||||
|
||||
// ┌──────────────────────────────────────────────┐
|
||||
// │ │
|
||||
// │ Is this a TPL block? It ought to be! │
|
||||
|
@ -1711,7 +1690,7 @@ bool Telegram::parse(vector<uchar> &input_frame, MeterKeys *mk)
|
|||
ok = parseTPL(pos);
|
||||
if (!ok) return false;
|
||||
|
||||
verboseFields();
|
||||
printTPL();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1723,6 +1702,18 @@ void Telegram::explainParse(string intro, int from)
|
|||
}
|
||||
}
|
||||
|
||||
string Telegram::autoDetectPossibleDrivers()
|
||||
{
|
||||
vector<string> drivers;
|
||||
detectMeterDriver(dll_mfct, dll_type, dll_version, &drivers);
|
||||
string possibles;
|
||||
for (string d : drivers) possibles = possibles+d+" ";
|
||||
if (possibles != "") possibles.pop_back();
|
||||
else possibles = "unknown!";
|
||||
|
||||
return possibles;
|
||||
}
|
||||
|
||||
string cType(int c_field)
|
||||
{
|
||||
string s;
|
||||
|
|
|
@ -383,7 +383,6 @@ struct Telegram
|
|||
bool parse(vector<uchar> &input_frame, MeterKeys *mk);
|
||||
void parserNoWarnings() { parser_warns_ = false; }
|
||||
void print();
|
||||
void verboseFields();
|
||||
|
||||
// A vector of indentations and explanations, to be printed
|
||||
// below the raw data bytes to explain the telegram content.
|
||||
|
@ -394,11 +393,11 @@ struct Telegram
|
|||
|
||||
bool isSimulated() { return is_simulated_; }
|
||||
|
||||
void expectVersion(const char *info, int v);
|
||||
|
||||
// Extracted mbus values.
|
||||
std::map<std::string,std::pair<int,DVEntry>> values;
|
||||
|
||||
string autoDetectPossibleDrivers();
|
||||
|
||||
private:
|
||||
|
||||
bool is_simulated_ {};
|
||||
|
|
3
test.sh
3
test.sh
|
@ -15,6 +15,9 @@ if [ "$?" != "0" ]; then RC="1"; fi
|
|||
tests/test_t1_meters.sh $PROG
|
||||
if [ "$?" != "0" ]; then RC="1"; fi
|
||||
|
||||
tests/test_unknown.sh $PROG
|
||||
if [ "$?" != "0" ]; then RC="1"; fi
|
||||
|
||||
tests/test_apas.sh $PROG
|
||||
if [ "$?" != "0" ]; then RC="1"; fi
|
||||
|
||||
|
|
|
@ -22,92 +22,150 @@ cat > $LOGFILE_EXPECTED <<EOF
|
|||
No meters configured. Printing id:s of all telegrams heard!
|
||||
|
||||
Received telegram from: 12345678
|
||||
manufacturer: (SON) Sontex, Switzerland
|
||||
device type: Warm Water (30°C-90°C) meter
|
||||
manufacturer: (SON) Sontex, Switzerland (0x4dee)
|
||||
device type: Warm Water (30°C-90°C) meter (0x06)
|
||||
device ver: 0x3c
|
||||
device driver: supercom587
|
||||
Received telegram from: 11111111
|
||||
manufacturer: (SON) Sontex, Switzerland
|
||||
device type: Water meter
|
||||
manufacturer: (SON) Sontex, Switzerland (0x4dee)
|
||||
device type: Water meter (0x07)
|
||||
device ver: 0x3c
|
||||
device driver: supercom587
|
||||
Received telegram from: 12345699
|
||||
manufacturer: (SEN) Sensus Metering Systems, Germany
|
||||
device type: Water meter
|
||||
manufacturer: (SEN) Sensus Metering Systems, Germany (0x4cae)
|
||||
device type: Water meter (0x07)
|
||||
device ver: 0x68
|
||||
device driver: iperl
|
||||
Received telegram from: 33225544
|
||||
manufacturer: (SEN) Sensus Metering Systems, Germany
|
||||
device type: Water meter
|
||||
manufacturer: (SEN) Sensus Metering Systems, Germany (0x4cae)
|
||||
device type: Water meter (0x07)
|
||||
device ver: 0x68
|
||||
device driver: iperl
|
||||
Received telegram from: 10101010
|
||||
manufacturer: (APA) Apator, Poland
|
||||
device type: Electricity meter
|
||||
manufacturer: (APA) Apator, Poland (0x601)
|
||||
device type: Electricity meter (0x02)
|
||||
device ver: 0x02
|
||||
device driver: amiplus
|
||||
Received telegram from: 34333231
|
||||
manufacturer: (TCH) Techem Service
|
||||
device type: Warm water
|
||||
manufacturer: (TCH) Techem Service (0x5068)
|
||||
device type: Warm water (0x62)
|
||||
device ver: 0x74
|
||||
device driver: mkradio3
|
||||
Received telegram from: 58234965
|
||||
manufacturer: (TCH) Techem Service
|
||||
device type: Heat meter
|
||||
manufacturer: (TCH) Techem Service (0x5068)
|
||||
device type: Heat meter (0xc3)
|
||||
device ver: 0x27
|
||||
device driver: vario451
|
||||
Received telegram from: 11776622
|
||||
manufacturer: (TCH) Techem Service
|
||||
device type: Heat Cost Allocator
|
||||
manufacturer: (TCH) Techem Service (0x5068)
|
||||
device type: Heat Cost Allocator (0x80)
|
||||
device ver: 0x69
|
||||
device driver: fhkvdataiii
|
||||
Received telegram from: 88018801
|
||||
manufacturer: (INE) INNOTAS Elektronik, Germany
|
||||
device type: Heat Cost Allocator
|
||||
manufacturer: (INE) INNOTAS Elektronik, Germany (0x25c5)
|
||||
device type: Heat Cost Allocator (0x08)
|
||||
device ver: 0x55
|
||||
device driver: eurisii
|
||||
Received telegram from: 00010204
|
||||
manufacturer: (LAS) Lansen Systems, Sweden
|
||||
device type: Smoke detector
|
||||
manufacturer: (LAS) Lansen Systems, Sweden (0x3033)
|
||||
device type: Smoke detector (0x1a)
|
||||
device ver: 0x03
|
||||
device driver: lansensm
|
||||
Received telegram from: 00010204
|
||||
manufacturer: (LAS) Lansen Systems, Sweden
|
||||
device type: Smoke detector
|
||||
manufacturer: (LAS) Lansen Systems, Sweden (0x3033)
|
||||
device type: Smoke detector (0x1a)
|
||||
device ver: 0x03
|
||||
device driver: lansensm
|
||||
Received telegram from: 00010203
|
||||
manufacturer: (LAS) Lansen Systems, Sweden
|
||||
device type: Room sensor (eg temperature or humidity)
|
||||
manufacturer: (LAS) Lansen Systems, Sweden (0x3033)
|
||||
device type: Room sensor (eg temperature or humidity) (0x1b)
|
||||
device ver: 0x07
|
||||
device driver: lansenth
|
||||
Received telegram from: 00010205
|
||||
manufacturer: (LAS) Lansen Systems, Sweden
|
||||
device type: Reserved for sensors
|
||||
manufacturer: (LAS) Lansen Systems, Sweden (0x3033)
|
||||
device type: Reserved for sensors (0x1d)
|
||||
device ver: 0x07
|
||||
device driver: lansendw
|
||||
Received telegram from: 00010205
|
||||
manufacturer: (LAS) Lansen Systems, Sweden
|
||||
device type: Reserved for sensors
|
||||
manufacturer: (LAS) Lansen Systems, Sweden (0x3033)
|
||||
device type: Reserved for sensors (0x1d)
|
||||
device ver: 0x07
|
||||
device driver: lansendw
|
||||
Received telegram from: 00010206
|
||||
manufacturer: (LAS) Lansen Systems, Sweden
|
||||
device type: Other
|
||||
manufacturer: (LAS) Lansen Systems, Sweden (0x3033)
|
||||
device type: Other (0x00)
|
||||
device ver: 0x14
|
||||
device driver: lansenpu
|
||||
Received telegram from: 11772288
|
||||
manufacturer: (BMT) BMETERS, Italy
|
||||
device type: Room sensor (eg temperature or humidity)
|
||||
manufacturer: (BMT) BMETERS, Italy (0x9b4)
|
||||
device type: Room sensor (eg temperature or humidity) (0x1b)
|
||||
device ver: 0x10
|
||||
device driver: rfmamb
|
||||
Received telegram from: 21242472
|
||||
manufacturer: (SAP) Sappel
|
||||
device type: Oil meter
|
||||
manufacturer: (SAP) Sappel (0x4c30)
|
||||
device type: Oil meter (0x01)
|
||||
device ver: 0xd4
|
||||
device driver: izar
|
||||
Received telegram from: 66290778
|
||||
manufacturer: (DME) DIEHL Metering, Germany
|
||||
device type: Unknown
|
||||
manufacturer: (DME) DIEHL Metering, Germany (0x11a5)
|
||||
device type: Unknown (0x66)
|
||||
device ver: 0x23
|
||||
device driver: izar
|
||||
Received telegram from: 64646464
|
||||
manufacturer: (DME) DIEHL Metering, Germany
|
||||
device type: Water meter
|
||||
manufacturer: (DME) DIEHL Metering, Germany (0x11a5)
|
||||
device type: Water meter (0x07)
|
||||
device ver: 0x70
|
||||
device driver: hydrus
|
||||
Received telegram from: 86868686
|
||||
manufacturer: (BMT) BMETERS, Italy
|
||||
device type: Water meter
|
||||
manufacturer: (BMT) BMETERS, Italy (0x9b4)
|
||||
device type: Water meter (0x07)
|
||||
device ver: 0x13
|
||||
device driver: hydrodigit
|
||||
Received telegram from: 72727272
|
||||
manufacturer: (AXI) UAB Axis Industries, Lithuania
|
||||
device type: Water meter
|
||||
manufacturer: (AXI) UAB Axis Industries, Lithuania (0x709)
|
||||
device type: Water meter (0x07)
|
||||
device ver: 0x10
|
||||
device driver: q400
|
||||
Received telegram from: 22992299
|
||||
manufacturer: (EBZ) eBZ, Germany
|
||||
device type: Radio converter (meter side)
|
||||
manufacturer: (EBZ) eBZ, Germany (0x145a)
|
||||
device type: Radio converter (meter side) (0x37)
|
||||
device ver: 0x02
|
||||
device driver: ebzwmbe
|
||||
Received telegram from: 77997799
|
||||
manufacturer: (ESY) EasyMeter
|
||||
device type: Radio converter (meter side)
|
||||
manufacturer: (ESY) EasyMeter (0x1679)
|
||||
device type: Radio converter (meter side) (0x37)
|
||||
device ver: 0x30
|
||||
device driver: esyswm
|
||||
Received telegram from: 77997799
|
||||
manufacturer: (ESY) EasyMeter
|
||||
device type: Radio converter (meter side)
|
||||
manufacturer: (ESY) EasyMeter (0x1679)
|
||||
device type: Radio converter (meter side) (0x37)
|
||||
device ver: 0x30
|
||||
device driver: esyswm
|
||||
Received telegram from: 55995599
|
||||
manufacturer: (EMH) EMH metering formerly EMH Elektrizitatszahler
|
||||
device type: Electricity meter
|
||||
manufacturer: (EMH) EMH metering formerly EMH Elektrizitatszahler (0x15a8)
|
||||
device type: Electricity meter (0x02)
|
||||
device ver: 0x02
|
||||
device driver: ehzp
|
||||
Received telegram from: 004444dd
|
||||
manufacturer: (APT) Unknown
|
||||
device type: Gas meter
|
||||
manufacturer: (APT) Unknown (0x8614)
|
||||
device type: Gas meter (0x03)
|
||||
device ver: 0x03
|
||||
device driver: apator08
|
||||
Received telegram from: 74737271
|
||||
manufacturer: (BMT) BMETERS, Italy
|
||||
device type: Water meter
|
||||
manufacturer: (BMT) BMETERS, Italy (0x9b4)
|
||||
device type: Water meter (0x07)
|
||||
device ver: 0x05
|
||||
device driver: rfmtx1
|
||||
Received telegram from: 20096221
|
||||
manufacturer: (DWZ) Lorenz, Germany
|
||||
device type: Warm Water (30°C-90°C) meter
|
||||
manufacturer: (DWZ) Lorenz, Germany (0x12fa)
|
||||
device type: Warm Water (30°C-90°C) meter (0x06)
|
||||
device ver: 0x02
|
||||
device driver: waterstarm
|
||||
Received telegram from: 78563412
|
||||
manufacturer: (AMT) INTEGRA METERING
|
||||
device type: Water meter
|
||||
manufacturer: (AMT) INTEGRA METERING (0x5b4)
|
||||
device type: Water meter (0x07)
|
||||
device ver: 0xf1
|
||||
device driver: topaseskr
|
||||
EOF
|
||||
|
||||
RES=$($PROG --logfile=$LOGFILE --t1 simulations/simulation_t1.txt 2>&1)
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/sh
|
||||
|
||||
PROG="$1"
|
||||
|
||||
mkdir -p testoutput
|
||||
TEST=testoutput
|
||||
|
||||
TESTNAME="Test meter with unknown driver"
|
||||
TESTRESULT="ERROR"
|
||||
|
||||
METERS="Dorren lansendw 00010205 NOKEY
|
||||
Forren lansensm 00010206 NOKEY
|
||||
"
|
||||
|
||||
cat > $TEST/test_expected.txt <<EOF
|
||||
(meter) Dorren: meter detection did not match the selected driver lansendw! correct driver is: unknown!
|
||||
{"media":"Unknown","meter":"lansendw","name":"Dorren","id":"00010205","status":"OPEN","timestamp":"1111-11-11T11:11:11Z"}
|
||||
(meter) Forren: meter detection did not match the selected driver lansensm! correct driver is: lansendw
|
||||
{"media":"reserved","meter":"lansensm","name":"Forren","id":"00010206","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
|
||||
EOF
|
||||
|
||||
$PROG --format=json simulations/simulation_unknown.txt $METERS > $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
|
||||
diff $TEST/test_expected.txt $TEST/test_responses.txt
|
||||
if [ "$?" = "0" ]
|
||||
then
|
||||
echo OK: $TESTNAME
|
||||
TESTRESULT="OK"
|
||||
else
|
||||
TESTRESULT="ERROR"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ "$TESTRESULT" = "ERROR" ]
|
||||
then
|
||||
echo ERROR: $TESTNAME
|
||||
exit 1
|
||||
fi
|
Ładowanie…
Reference in New Issue