kopia lustrzana https://github.com/weetmuts/wmbusmeters
Add mbus support.
rodzic
1146fae2c2
commit
3a6bb0a03d
29
README.md
29
README.md
|
@ -2,7 +2,7 @@
|
|||
# wmbusmeters
|
||||
|
||||
The program receives and decodes C1,T1 or S1 telegrams
|
||||
(using the wireless mbus protocol) to acquire
|
||||
(using the wireless mbus protocol or the wired mbus protocol) to acquire
|
||||
utility meter readings. The readings can then be published using
|
||||
MQTT, curled to a REST api, inserted into a database or stored in a log file.
|
||||
|
||||
|
@ -45,6 +45,8 @@ from your computer. Then do:
|
|||
|
||||
`./configure; make; sudo make install` will install wmbusmeters as a daemon.
|
||||
|
||||
# Usage
|
||||
|
||||
Check the contents of your `/etc/wmbusmeters.conf` file, assuming it
|
||||
has `device=auto:t1` and you are using a im871a,amb8465,rc1180,cul or rtlsdr device,
|
||||
then you can now start the daemon with `sudo systemctl start wmbusmeters`
|
||||
|
@ -102,6 +104,25 @@ device=/dev/ttyUSB0:im871a[00102759]:c1,t1
|
|||
device=/dev/ttyUSB1:rc1800:t1
|
||||
```
|
||||
|
||||
# Bus aliases and polling
|
||||
|
||||
To poll an C2/T2/S2 wireless meter or an wired m-bus meter you need to give the (w)mbus device a bus-alias, for example
|
||||
here we pick the bus alias MAIN:
|
||||
```
|
||||
MAIN=/dev/ttyUSB0:mbus
|
||||
```
|
||||
and here we pick the bus alias WIRELESS2 for an im871a dongle:
|
||||
```
|
||||
WIRELESS2=/dev/ttyUSB1:im871a:c2
|
||||
```
|
||||
|
||||
The bus alias is then used in the meter driver specification to specify which
|
||||
bus the mbus poll request should be sent to.
|
||||
```
|
||||
wmbusmeters MAIN=/dev/ttyUSB0:mbus MyTempMeter piigth:MAIN:2400:mbus 12001932 NOKEY
|
||||
```
|
||||
|
||||
# Example wmbusmeter.conf file
|
||||
|
||||
```ini
|
||||
loglevel=normal
|
||||
|
@ -262,6 +283,7 @@ As {options} you can use:
|
|||
--normal for normal logging
|
||||
--oneshot wait for an update from each meter, then quit
|
||||
--ppjson pretty print the json
|
||||
--pollevery=<time> time between polling of meters, default is 10m
|
||||
--resetafter=<time> reset the wmbus dongle regularly, default is 23h
|
||||
--selectfields=id,timestamp,total_m3 select only these fields to be printed (--listfields=<meter> to list available fields)
|
||||
--separator=<c> change field separator to c
|
||||
|
@ -297,6 +319,7 @@ rtlsdr dongle like this `rtlwmbus[1234]`.
|
|||
`/dev/ttyUSB0:38400`, to have wmbusmeters set the baud rate to 38400 and listen for raw wmbus telegrams.
|
||||
These telegrams are expected to have the data link layer crc bytes removed already!
|
||||
|
||||
`MAIN=/dev/ttyUSB0`
|
||||
`rtlwmbus`, to spawn the background process: `rtl_sdr -f 868.625M -s 1600000 - 2>/dev/null | rtl_wmbus -s`
|
||||
for each attached rtlsdr dongle. This will listen to S1,T1 and C1 meters in parallel.
|
||||
|
||||
|
@ -363,6 +386,9 @@ Radiocraft (RC1180)
|
|||
rtl_wmbus (rtlwmbus)
|
||||
rtl_433 (rtl433)
|
||||
|
||||
Supported mbus dongles:
|
||||
Any bus controller dongle/board behaving like a plain serial port.
|
||||
|
||||
Supported water meters:
|
||||
Aventies (aventieswm)
|
||||
Apator at-wmbus-08 (apator08) (non-standard protocol)
|
||||
|
@ -416,6 +442,7 @@ Bmeters RFM-AMB Thermometer/Hygrometer (rfmamb)
|
|||
Elvaco CMa12w Thermometer (cma12w)
|
||||
Lansen Thermometer/Hygrometer (lansenth)
|
||||
Weptech Munia Thermometer/Hygrometer (munia)
|
||||
PiiGAB Thermometer/Hygrometer (piigth) wired
|
||||
|
||||
Supported smoke detectors:
|
||||
Lansen Smoke Detector (lansensm)
|
||||
|
|
|
@ -526,6 +526,14 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--pollevery=", 12) && strlen(argv[i]) > 12) {
|
||||
c->pollevery = parseTime(argv[i]+12);
|
||||
if (c->pollevery <= 0) {
|
||||
error("Not a valid time to regularly poll meters. \"%s\"\n", argv[i]+12);
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--resetafter=", 13) && strlen(argv[i]) > 13) {
|
||||
c->resetafter = parseTime(argv[i]+13);
|
||||
if (c->resetafter <= 0) {
|
||||
|
|
|
@ -96,6 +96,7 @@ struct Configuration
|
|||
std::string logfile;
|
||||
bool json {};
|
||||
bool pretty_print_json {};
|
||||
int pollevery {}; // Time between polling.
|
||||
bool fields {};
|
||||
char separator { ';' };
|
||||
std::vector<std::string> telegram_shells;
|
||||
|
|
|
@ -16,250 +16,76 @@
|
|||
*/
|
||||
|
||||
#include"meters_common_implementation.h"
|
||||
#include"bus.h"
|
||||
|
||||
struct MeterPIIGTH : public virtual MeterCommonImplementation
|
||||
namespace
|
||||
{
|
||||
MeterPIIGTH(MeterInfo &mi, DriverInfo &di);
|
||||
|
||||
void poll(shared_ptr<BusManager> bus_manager);
|
||||
|
||||
double temperature_c_ {};
|
||||
double average_temperature_1h_c_ {};
|
||||
double average_temperature_24h_c_ {};
|
||||
double relative_humidity_rh_ {};
|
||||
double average_relative_humidity_1h_rh_ {};
|
||||
double average_relative_humidity_24h_rh_ {};
|
||||
string fabrication_no_txt_ {};
|
||||
};
|
||||
|
||||
static bool ok = registerDriver([](DriverInfo&di)
|
||||
{
|
||||
di.setName("piigth");
|
||||
di.setMeterType(MeterType::TempHygroMeter);
|
||||
di.addLinkMode(LinkMode::MBUS);
|
||||
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new MeterPIIGTH(mi, di)); });
|
||||
di.addDetection(MANUFACTURER_PII, 0x1b, 0x01);
|
||||
});
|
||||
|
||||
MeterPIIGTH::MeterPIIGTH(MeterInfo &mi, DriverInfo &di) :
|
||||
MeterCommonImplementation(mi, di)
|
||||
{
|
||||
addNumericFieldWithExtractor(
|
||||
"temperature",
|
||||
Quantity::Temperature,
|
||||
NoDifVifKey,
|
||||
VifScaling::Auto,
|
||||
MeasurementType::Instantaneous,
|
||||
VIFRange::ExternalTemperature,
|
||||
StorageNr(0),
|
||||
TariffNr(0),
|
||||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The current temperature.",
|
||||
SET_FUNC(temperature_c_, Unit::C),
|
||||
GET_FUNC(temperature_c_, Unit::C));
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"average_temperature_1h",
|
||||
Quantity::Temperature,
|
||||
NoDifVifKey,
|
||||
VifScaling::Auto,
|
||||
MeasurementType::Instantaneous,
|
||||
VIFRange::ExternalTemperature,
|
||||
StorageNr(1),
|
||||
TariffNr(0),
|
||||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The average temperature over the last hour.",
|
||||
SET_FUNC(average_temperature_1h_c_, Unit::C),
|
||||
GET_FUNC(average_temperature_1h_c_, Unit::C));
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"average_temperature_24h",
|
||||
Quantity::Temperature,
|
||||
NoDifVifKey,
|
||||
VifScaling::Auto,
|
||||
MeasurementType::Instantaneous,
|
||||
VIFRange::ExternalTemperature,
|
||||
StorageNr(2),
|
||||
TariffNr(0),
|
||||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The average temperature over the last 24 hours.",
|
||||
SET_FUNC(average_temperature_24h_c_, Unit::C),
|
||||
GET_FUNC(average_temperature_24h_c_, Unit::C));
|
||||
|
||||
/*
|
||||
addNumericFieldWithExtractor(
|
||||
"relative_humidity",
|
||||
Quantity::Temperature,
|
||||
DifVifKey("02FB1A"),
|
||||
VifScaling::Auto,
|
||||
MeasurementType::Instantaneous,
|
||||
VIFRange::RelativeHumidity,
|
||||
StorageNr(0),
|
||||
TariffNr(0),
|
||||
IndexNr(1),
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
"The current relative humidity.",
|
||||
SET_FUNC(relative_humidity_rh_, Unit::RH),
|
||||
GET_FUNC(relative_humidity_rh_, Unit::RH));
|
||||
*/
|
||||
addStringFieldWithExtractor(
|
||||
"fabrication_no",
|
||||
Quantity::Text,
|
||||
NoDifVifKey,
|
||||
MeasurementType::Instantaneous,
|
||||
VIFRange::FabricationNo,
|
||||
StorageNr(0),
|
||||
TariffNr(0),
|
||||
IndexNr(1),
|
||||
PrintProperty::JSON,
|
||||
"Fabrication number.",
|
||||
SET_STRING_FUNC(fabrication_no_txt_),
|
||||
GET_STRING_FUNC(fabrication_no_txt_));
|
||||
|
||||
}
|
||||
/*
|
||||
|
||||
addPrint("current_relative_humidity", Quantity::RelativeHumidity,
|
||||
[&](Unit u){ return currentRelativeHumidity(); },
|
||||
"The current relative humidity.",
|
||||
true, true);
|
||||
|
||||
addPrint("average_temperature_1h", Quantity::Temperature,
|
||||
[&](Unit u){ return convert(average_temperature_1h_c_, Unit::C, u); },
|
||||
"The average temperature over the last hour.",
|
||||
false, true);
|
||||
|
||||
addPrint("average_relative_humidity_1h", Quantity::RelativeHumidity,
|
||||
[&](Unit u){ return average_relative_humidity_1h_rh_; },
|
||||
"The average relative humidity over the last hour.",
|
||||
false, true);
|
||||
|
||||
addPrint("average_temperature_24h", Quantity::Temperature,
|
||||
[&](Unit u){ return convert(average_temperature_24h_c_, Unit::C, u); },
|
||||
"The average temperature over the last 24 hours.",
|
||||
false, true);
|
||||
|
||||
addPrint("average_relative_humidity_24h", Quantity::RelativeHumidity,
|
||||
[&](Unit u){ return average_relative_humidity_24h_rh_; },
|
||||
"The average relative humidity over the last 24 hours.",
|
||||
false, true);
|
||||
}
|
||||
*/
|
||||
|
||||
void MeterPIIGTH::poll(shared_ptr<BusManager> bus_manager)
|
||||
{
|
||||
WMBus *dev = bus_manager->findBus(bus());
|
||||
|
||||
if (!dev)
|
||||
struct Driver : public virtual MeterCommonImplementation
|
||||
{
|
||||
fprintf(stderr, "Could not find bus from name %s\n", bus().c_str());
|
||||
return;
|
||||
}
|
||||
Driver(MeterInfo &mi, DriverInfo &di);
|
||||
};
|
||||
|
||||
vector<uchar> buf;
|
||||
|
||||
/*
|
||||
buf[0] = 0x10; // Start
|
||||
buf[1] = 0x40; // SND_NKE
|
||||
buf[2] = 0x00; // address 0
|
||||
uchar cs = 0;
|
||||
for (int i=1; i<3; ++i) cs += buf[i];
|
||||
buf[3] = cs; // checksum
|
||||
buf[4] = 0x16; // Stop
|
||||
|
||||
dev->serial()->send(buf);
|
||||
|
||||
sleep(2);
|
||||
*/
|
||||
// 10000284
|
||||
/*
|
||||
10000284 2941 01 1B
|
||||
*/
|
||||
buf.resize(17);
|
||||
buf[0] = 0x68;
|
||||
buf[1] = 0x0b;
|
||||
buf[2] = 0x0b;
|
||||
buf[3] = 0x68;
|
||||
buf[4] = 0x73; // SND_UD
|
||||
buf[5] = 0xfd; // address 253
|
||||
buf[6] = 0x52; // ci 52
|
||||
buf[7] = 0x84; // id 78
|
||||
buf[8] = 0x02; // id 56
|
||||
buf[9] = 0x00; // id 34
|
||||
buf[10] = 0x10; // id 12
|
||||
buf[11] = 0x29; // mfct 29
|
||||
buf[12] = 0x41; // mfct 41 2941 == PII
|
||||
buf[13] = 0x01; // version/generation
|
||||
buf[14] = 0x1b; // type/media/device
|
||||
|
||||
uchar cs = 0;
|
||||
for (int i=4; i<15; ++i) cs += buf[i];
|
||||
buf[15] = cs; // checksum
|
||||
buf[16] = 0x16; // Stop
|
||||
|
||||
dev->serial()->send(buf);
|
||||
|
||||
sleep(1);
|
||||
// 10 5B FD 58 16
|
||||
buf.resize(5);
|
||||
buf[0] = 0x10; // Start
|
||||
buf[1] = 0x5b; // REQ_UD2
|
||||
buf[2] = 0xfd; // 00 or address 253 previously setup
|
||||
cs = 0;
|
||||
for (int i=1; i<3; ++i) cs += buf[i];
|
||||
buf[3] = cs; // checksum
|
||||
buf[4] = 0x16; // Stop
|
||||
|
||||
dev->serial()->send(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
void MeterPIIGTH::processContent(Telegram *t)
|
||||
{
|
||||
int offset;
|
||||
string key;
|
||||
|
||||
if (findKey(MeasurementType::Instantaneous, VIFRange::ExternalTemperature, 1, 0, &key, &t->dv_entries))
|
||||
static bool ok = registerDriver([](DriverInfo&di)
|
||||
{
|
||||
extractDVdouble(&t->dv_entries, key, &offset, &average_temperature_1h_c_);
|
||||
t->addMoreExplanation(offset, " average temperature 1h (%f C))", average_temperature_1h_c_);
|
||||
}
|
||||
di.setName("piigth");
|
||||
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_PII, 0x1b, 0x01);
|
||||
});
|
||||
|
||||
if (findKey(MeasurementType::Instantaneous, VIFRange::ExternalTemperature, 2, 0, &key, &t->dv_entries))
|
||||
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
|
||||
{
|
||||
extractDVdouble(&t->dv_entries, key, &offset, &average_temperature_24h_c_);
|
||||
t->addMoreExplanation(offset, " average temperature 24h (%f C))", average_temperature_24h_c_);
|
||||
}
|
||||
addNumericFieldWithExtractor(
|
||||
"temperature",
|
||||
"The current temperature.",
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
Quantity::Temperature,
|
||||
VifScaling::Auto,
|
||||
FieldMatcher::build()
|
||||
.set(MeasurementType::Instantaneous)
|
||||
.set(VIFRange::ExternalTemperature)
|
||||
);
|
||||
|
||||
// Temporarily silly solution until the dvparser is upgraded with support for extension
|
||||
addNumericFieldWithExtractor(
|
||||
"average_temperature_1h",
|
||||
"The average temperature over the last hour.",
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
Quantity::Temperature,
|
||||
VifScaling::Auto,
|
||||
FieldMatcher::build()
|
||||
.set(MeasurementType::Instantaneous)
|
||||
.set(VIFRange::ExternalTemperature)
|
||||
);
|
||||
|
||||
key = "02FB1A"; // 1A = 0001 1010 = First extension vif code Relative Humidity 10^-1
|
||||
if (hasKey(&t->dv_entries, key))
|
||||
{
|
||||
double tmp;
|
||||
extractDVdouble(&t->dv_entries, key, &offset, &tmp, false);
|
||||
current_relative_humidity_rh_ = tmp / (double)10.0;
|
||||
t->addMoreExplanation(offset, " current relative humidity (%f RH)", current_relative_humidity_rh_);
|
||||
}
|
||||
key = "42FB1A"; // 1A = 0001 1010 = First extension vif code Relative Humidity 10^-1
|
||||
if (hasKey(&t->dv_entries, key))
|
||||
{
|
||||
double tmp;
|
||||
extractDVdouble(&t->dv_entries, key, &offset, &tmp, false);
|
||||
average_relative_humidity_1h_rh_ = tmp / (double)10.0;
|
||||
t->addMoreExplanation(offset, " average relative humidity 1h (%f RH)", average_relative_humidity_1h_rh_);
|
||||
}
|
||||
key = "8201FB1A"; // 1A = 0001 1010 = First extension vif code Relative Humidity 10^-1
|
||||
if (hasKey(&t->dv_entries, key))
|
||||
{
|
||||
double tmp;
|
||||
extractDVdouble(&t->dv_entries, key, &offset, &tmp, false);
|
||||
average_relative_humidity_24h_rh_ = tmp / (double)10.0;
|
||||
t->addMoreExplanation(offset, " average relative humidity 24h (%f RH)", average_relative_humidity_24h_rh_);
|
||||
addNumericFieldWithExtractor(
|
||||
"average_temperature_24h",
|
||||
"The average temperature over the last 24 hours.",
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
Quantity::Temperature,
|
||||
VifScaling::Auto,
|
||||
FieldMatcher::build()
|
||||
.set(MeasurementType::Instantaneous)
|
||||
.set(VIFRange::ExternalTemperature)
|
||||
.set(StorageNr(2))
|
||||
);
|
||||
|
||||
addNumericFieldWithExtractor(
|
||||
"relative_humidity",
|
||||
"The current relative humidity.",
|
||||
PrintProperty::JSON | PrintProperty::FIELD,
|
||||
Quantity::RelativeHumidity,
|
||||
VifScaling::Auto,
|
||||
FieldMatcher::build().
|
||||
set(DifVifKey("02FB1A"))
|
||||
);
|
||||
|
||||
addStringFieldWithExtractor(
|
||||
"fabrication_no",
|
||||
"Fabrication number.",
|
||||
PrintProperty::JSON,
|
||||
FieldMatcher::build()
|
||||
.set(MeasurementType::Instantaneous)
|
||||
.set(VIFRange::FabricationNo)
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
117
src/meters.cc
117
src/meters.cc
|
@ -15,6 +15,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include"bus.h"
|
||||
#include"config.h"
|
||||
#include"meters.h"
|
||||
#include"meter_detection.h"
|
||||
|
@ -1009,8 +1010,118 @@ void MeterCommonImplementation::addStringFieldWithExtractorAndLookup(string vnam
|
|||
));
|
||||
}
|
||||
|
||||
void MeterCommonImplementation::poll(shared_ptr<BusManager> bus)
|
||||
void MeterCommonImplementation::poll(shared_ptr<BusManager> bus_manager)
|
||||
{
|
||||
if (link_modes_.has(LinkMode::MBUS))
|
||||
{
|
||||
WMBus *bus_device = bus_manager->findBus(bus());
|
||||
|
||||
if (!bus_device)
|
||||
{
|
||||
debug("(meter) Could not find bus from name \"%s\"\n", bus().c_str());
|
||||
return;
|
||||
}
|
||||
/*
|
||||
Reset mbus...
|
||||
vector<uchar> buf;
|
||||
buf[0] = 0x10; // Start
|
||||
buf[1] = 0x40; // SND_NKE
|
||||
buf[2] = 0x00; // address 0
|
||||
uchar cs = 0;
|
||||
for (int i=1; i<3; ++i) cs += buf[i];
|
||||
buf[3] = cs; // checksum
|
||||
buf[4] = 0x16; // Stop
|
||||
dev->serial()->send(buf);
|
||||
|
||||
sleep(2);
|
||||
*/
|
||||
|
||||
string id = ids().back();
|
||||
if (id.length() != 2 && id.length() != 3 && id.length() != 8)
|
||||
{
|
||||
debug("(meter) not polling from bad id \"%s\" with wrong length\n", id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (id.length() == 2 || id.length() == 3)
|
||||
{
|
||||
vector<uchar> idhex;
|
||||
int idnum = atoi(id.c_str());
|
||||
|
||||
if (idnum < 0 || idnum > 250 || idhex.size() != 1)
|
||||
{
|
||||
debug("(meter) not polling from bad id \"%s\"\n", id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
vector<uchar> buf;
|
||||
buf.resize(5);
|
||||
buf[0] = 0x10; // Start
|
||||
buf[1] = 0x5b; // REQ_UD2
|
||||
buf[2] = idhex[0];
|
||||
uchar cs = 0;
|
||||
for (int i=1; i<3; ++i) cs += buf[i];
|
||||
buf[3] = cs; // checksum
|
||||
buf[4] = 0x16; // Stop
|
||||
|
||||
verbose("(meter) req ud2 bus %s address %s\n", bus_device->busAlias().c_str(),id.c_str());
|
||||
bus_device->serial()->send(buf);
|
||||
}
|
||||
|
||||
if (id.length() == 8)
|
||||
{
|
||||
// A full secondary address 12345678 was specified.
|
||||
|
||||
vector<uchar> idhex;
|
||||
bool ok = hex2bin(id, &idhex);
|
||||
|
||||
if (!ok || idhex.size() != 4)
|
||||
{
|
||||
debug("(meter) not polling from bad id \"%s\"\n", id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
vector<uchar> buf;
|
||||
buf.resize(17);
|
||||
buf[0] = 0x68;
|
||||
buf[1] = 0x0b;
|
||||
buf[2] = 0x0b;
|
||||
buf[3] = 0x68;
|
||||
buf[4] = 0x73; // SND_UD
|
||||
buf[5] = 0xfd; // address 253
|
||||
buf[6] = 0x52; // ci 52
|
||||
buf[7] = idhex[3]; // id 78
|
||||
buf[8] = idhex[2]; // id 56
|
||||
buf[9] = idhex[1]; // id 34
|
||||
buf[10] = idhex[0]; // id 12
|
||||
buf[11] = 0x29; // mfct 29
|
||||
buf[12] = 0x41; // mfct 41 2941 == PII
|
||||
buf[13] = 0x01; // version/generation
|
||||
buf[14] = 0x1b; // type/media/device
|
||||
|
||||
uchar cs = 0;
|
||||
for (int i=4; i<15; ++i) cs += buf[i];
|
||||
buf[15] = cs; // checksum
|
||||
buf[16] = 0x16; // Stop
|
||||
|
||||
debug("(meter) secondary addressing bus %s to address %s\n", bus_device->busAlias().c_str(), id.c_str());
|
||||
bus_device->serial()->send(buf);
|
||||
|
||||
usleep(1000*500);
|
||||
|
||||
buf.resize(5);
|
||||
buf[0] = 0x10; // Start
|
||||
buf[1] = 0x5b; // REQ_UD2
|
||||
buf[2] = 0xfd; // 00 or address 253 previously setup
|
||||
cs = 0;
|
||||
for (int i=1; i<3; ++i) cs += buf[i];
|
||||
buf[3] = cs; // checksum
|
||||
buf[4] = 0x16; // Stop
|
||||
|
||||
verbose("(meter) req ud2 bus %s address %s\n", bus_device->busAlias().c_str(),id.c_str());
|
||||
bus_device->serial()->send(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<string>& MeterCommonImplementation::ids()
|
||||
|
@ -1991,7 +2102,7 @@ LIST_OF_METERS
|
|||
return newm;
|
||||
}
|
||||
|
||||
bool is_driver_extras(string t, MeterDriver *out_driver, DriverName *out_driver_name, string *out_extras)
|
||||
bool is_driver_and_extras(string t, MeterDriver *out_driver, DriverName *out_driver_name, string *out_extras)
|
||||
{
|
||||
// piigth(jump=foo)
|
||||
// multical21
|
||||
|
@ -2084,7 +2195,7 @@ bool MeterInfo::parse(string n, string d, string i, string k)
|
|||
|
||||
for (auto& p : parts)
|
||||
{
|
||||
if (!driverextras_checked && is_driver_extras(p, &driver, &driver_name, &extras))
|
||||
if (!driverextras_checked && is_driver_and_extras(p, &driver, &driver_name, &extras))
|
||||
{
|
||||
driverextras_checked = true;
|
||||
}
|
||||
|
|
|
@ -801,13 +801,21 @@ void testm(string arg, bool xok,
|
|||
}
|
||||
if (ok == false) return;
|
||||
|
||||
if (toString(mi.driver) != xdriver,
|
||||
mi.extras != xextras ||
|
||||
mi.bus != xbus ||
|
||||
to_string(mi.bps) != xbps ||
|
||||
mi.link_modes.hr() != xlm)
|
||||
bool driver_ok = toString(mi.driver) == xdriver || mi.driverName().str() == xdriver;
|
||||
bool extras_ok = mi.extras == xextras;
|
||||
bool bus_ok = mi.bus == xbus;
|
||||
bool bps_ok = to_string(mi.bps) == xbps;
|
||||
bool link_modes_ok = mi.link_modes.hr() == xlm;
|
||||
|
||||
if (!driver_ok || !extras_ok || !bus_ok || !bps_ok || !link_modes_ok)
|
||||
{
|
||||
printf("ERROR in meter parsing parts \"%s\" - got (driver: %s, extras: %s, bus: %s, bbps: %s, linkmodes: %s)\n", arg.c_str(), toString(mi.driver).c_str(), mi.extras.c_str(), mi.bus.c_str(), to_string(mi.bps).c_str(), mi.link_modes.hr().c_str());
|
||||
printf("ERROR in meterm parsing parts \"%s\" - got (driver: \"%s/%s\" (%d), extras: \"%s\" (%d), bus: \"%s\" (%d), bbps: \"%s\" (%d), linkmodes: \"%s\" (%d))\n",
|
||||
arg.c_str(),
|
||||
toString(mi.driver).c_str(), mi.driverName().str().c_str(), driver_ok,
|
||||
mi.extras.c_str(), extras_ok,
|
||||
mi.bus.c_str(), bus_ok,
|
||||
to_string(mi.bps).c_str(), bps_ok,
|
||||
mi.link_modes.hr().c_str(), link_modes_ok);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -823,13 +831,16 @@ void testc(string file, string file_content,
|
|||
parseMeterConfig(&c, meter_conf, file);
|
||||
|
||||
mi = c.meters.back();
|
||||
if (toString(mi.driver) != xdriver,
|
||||
if ((toString(mi.driver) != xdriver && mi.driverName().str() != xdriver) ||
|
||||
mi.extras != xextras ||
|
||||
mi.bus != xbus ||
|
||||
to_string(mi.bps) != xbps ||
|
||||
mi.link_modes.hr() != xlm)
|
||||
{
|
||||
printf("ERROR in meter parsing parts \"%s\" - got (driver: %s, extras: %s, bus: %s, bbps: %s, linkmodes: %s)\n", file.c_str(), toString(mi.driver).c_str(), mi.extras.c_str(), mi.bus.c_str(), to_string(mi.bps).c_str(), mi.link_modes.hr().c_str());
|
||||
printf("ERROR in meterc parsing parts \"%s\" - got (driver: %s/%s, extras: %s, bus: %s, bbps: %s, linkmodes: %s)\n",
|
||||
file.c_str(),
|
||||
toString(mi.driver).c_str(), mi.driverName().str().c_str(),
|
||||
mi.extras.c_str(), mi.bus.c_str(), to_string(mi.bps).c_str(), mi.link_modes.hr().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -837,18 +848,38 @@ void test_meters()
|
|||
{
|
||||
string config_content;
|
||||
|
||||
/*
|
||||
testm("piigth:BUS1:2400", true,
|
||||
"piigth", // driver
|
||||
"", // extras
|
||||
"BUS1", // bus
|
||||
"2400", // bps
|
||||
"none"); // linkmodes
|
||||
|
||||
testm("c5isf:MAINO:9600:mbus", true,
|
||||
"c5isf", // driver
|
||||
"", // extras
|
||||
"MAINO", // bus
|
||||
"9600", // bps
|
||||
"mbus"); // linkmodes
|
||||
*/
|
||||
|
||||
testm("c5isf:DONGLE:t1", true,
|
||||
"c5isf", // driver
|
||||
"", // extras
|
||||
"DONGLE", // bus
|
||||
"0", // bps
|
||||
"t1"); // linkmodes
|
||||
|
||||
testm("c5isf:t1,c1,mbus", true,
|
||||
"c5isf", // driver
|
||||
"", // extras
|
||||
"", // bus
|
||||
"0", // bps
|
||||
"c1,t1,mbus"); // linkmodes
|
||||
|
||||
/*
|
||||
config_content =
|
||||
"name=test\n"
|
||||
"driver=piigth:BUS1:2400\n"
|
||||
"driver=piigth:BUS1:2400:mbus\n"
|
||||
"id=01234567\n";
|
||||
|
||||
testc("meter/piigth:BUS1:2400", config_content,
|
||||
|
|
|
@ -4760,7 +4760,7 @@ FrameStatus checkMBusFrame(vector<uchar> &data,
|
|||
return ErrorInFrame;
|
||||
}
|
||||
|
||||
*payload_len_out = *frame_length-2; // Drop checksum byte and stop byte.
|
||||
*payload_len_out = *frame_length; // Drop checksum byte and stop byte.
|
||||
*payload_offset = 0; // Drop 0x68 len len 0x68.
|
||||
if (!only_test)
|
||||
{
|
||||
|
|
Ładowanie…
Reference in New Issue