kopia lustrzana https://github.com/weetmuts/wmbusmeters
Add option pollinterval=10m to meter files.
rodzic
4c6fefa089
commit
8d164b7753
6
CHANGES
6
CHANGES
|
@ -1,4 +1,8 @@
|
|||
|
||||
ATTENTION! When a field is not optional in the driver description,
|
||||
but alas, no data has arrived in the telegram, then the json now
|
||||
contains a null for the value! Previousy 0 was used, which is misleading.
|
||||
|
||||
ATTENTION! The default location of the meter_readings directory has changed
|
||||
from /var/log/wmbusmeters/meter_readings to /var/lib/wmbusmeters/meter_readings
|
||||
This only affects new installations. Existing conf files will use the old location
|
||||
|
@ -9,7 +13,7 @@ Add detection of bad CUL firmware.
|
|||
Using :mbus as suffix to the meter driver now works to poll a meter of mbus instead of
|
||||
listening to wmbus telegrams.
|
||||
|
||||
wmbusmeters --pollinterval=1h --format=json MAIN=/dev/ttyUSB0:mbus MyTemp piigth:MAIN:2400:mbus 12301234 NOKEY
|
||||
wmbusmeters --pollinterval=1h --format=json MAIN=/dev/ttyUSB0:mbus:2400 MyTemp piigth:MAIN:mbus 12301234 NOKEY
|
||||
|
||||
Added --pollinterval=<time> to set the poll interval for all meters to 10 minutes.
|
||||
As <time> you can say 5s 10m 11h etc.
|
||||
|
|
3
Makefile
3
Makefile
|
@ -184,13 +184,14 @@ check_docs:
|
|||
@cat src/cmdline.cc | grep -o -- '--[a-z][a-z]*' | sort | uniq | grep -v internaltesting > /tmp/options_in_code
|
||||
@cat wmbusmeters.1 | grep -o -- '--[a-z][a-z]*' | sort | uniq | grep -v internaltesting > /tmp/options_in_man
|
||||
@cat README.md | grep -o -- '--[a-z][a-z]*' | sort | uniq | grep -v internaltesting > /tmp/options_in_readme
|
||||
@./build/wmbusmeters --help | grep -o -- '--[a-z][a-z]*' | sort | uniq | grep -v internaltesting > /tmp/options_in_binary
|
||||
@$(BUILD)/wmbusmeters --help | grep -o -- '--[a-z][a-z]*' | sort | uniq | grep -v internaltesting > /tmp/options_in_binary
|
||||
@diff /tmp/options_in_code /tmp/options_in_man || echo CODE_VS_MAN
|
||||
@diff /tmp/options_in_code /tmp/options_in_readme || echo CODE_VS_README
|
||||
@diff /tmp/options_in_code /tmp/options_in_binary || echo CODE_VS_BINARY
|
||||
@echo "OK docs"
|
||||
|
||||
install: $(BUILD)/wmbusmeters check_docs
|
||||
echo "Installing $(BUILD)/wmbusmeters"
|
||||
@./install.sh $(BUILD)/wmbusmeters $(DESTDIR) $(EXTRA_INSTALL_OPTIONS)
|
||||
|
||||
uninstall:
|
||||
|
|
25
README.md
25
README.md
|
@ -110,11 +110,10 @@ here we pick the bus alias MAIN for the mbus using 2400 bps for all meters on th
|
|||
```
|
||||
MAIN=/dev/ttyUSB0:mbus:2400
|
||||
```
|
||||
and here we pick the bus alias WIRELESS2 for an im871a dongle:
|
||||
and here we pick the bus alias OUT for an im871a dongle:
|
||||
```
|
||||
WIRELESS2=/dev/ttyUSB1:im871a:c2
|
||||
OUT=/dev/ttyUSB1:im871a:c2
|
||||
```
|
||||
(This is not yet fully functional.)
|
||||
|
||||
The bus alias is then used in the meter driver specification to specify which
|
||||
bus the mbus poll request should be sent to.
|
||||
|
@ -129,6 +128,8 @@ loglevel=normal
|
|||
# You can use auto:t1 to find the device you have connected to your system.
|
||||
# But do not use auto here since it will cause unnecessary and slow probing of the serial ports.
|
||||
device=/dev/ttyUSB0:im871a:c1,t1
|
||||
# And mbus
|
||||
device=MAIN=/dev/ttyUSB1:mbus:2400
|
||||
# But do not probe this serial tty.
|
||||
donotprobe=/dev/ttyACM2
|
||||
logtelegrams=false
|
||||
|
@ -154,10 +155,19 @@ key=00112233445566778899AABBCCDDEEFF
|
|||
driver=multical21
|
||||
```
|
||||
|
||||
And an mbus meter file in /etc/wmbusmeters.d/MyTempHygro
|
||||
|
||||
```ini
|
||||
name=MyTempHygro
|
||||
id=11223344
|
||||
driver=piigth:mbus
|
||||
pollinterval=60s
|
||||
```
|
||||
|
||||
# Important information about meter drivers and their names.
|
||||
|
||||
You can use `driver=auto` to have wmbusmeters automatically detect
|
||||
and use the best driver for your meter, but you should not use auto in production.
|
||||
and use the best driver for your meter, but you should >not< use auto in production.
|
||||
|
||||
You can find out which driver is recommended by running `wmbusmeters im871a:t1`.
|
||||
This will print information like:
|
||||
|
@ -172,15 +182,16 @@ Received telegram from: 71727374
|
|||
For production use it is very much recommended that you specify the exact driver
|
||||
in the meter file. The reason is that new and better drivers might be developed
|
||||
for your meter, where the keys and the content of the json might change.
|
||||
Such new drivers are guaranteed to have a different driver name!
|
||||
Such new drivers are guaranteed to have a different driver name.
|
||||
The auto look up will change to the new driver, but the old driver will still work.
|
||||
|
||||
So wmbusmeters makes a guarantee that if you have specified the driver name,
|
||||
So wmbusmeters strives to guarantee that if you have specified the driver name,
|
||||
then wmbusmeters can be safely upgraded at any time. The json will not
|
||||
change in an incompatible way. (The only allowed changes are: adding new fields
|
||||
and changing the ordering.)
|
||||
|
||||
Now plugin your wmbus dongle.
|
||||
|
||||
Wmbusmeters should start automatically, check with `tail -f /var/log/syslog` and `tail -f /var/log/wmbusmeters/wmbusmeters.log`
|
||||
(If you are using an rtlsdr dongle, then make sure that either the binaries `/usr/bin/rtl_sdr` and
|
||||
`/usr/bin/rtl_wmbus` exists and are executable. Or that the executable `rtl_sdr/rtl_wmbus` binaries
|
||||
|
@ -307,7 +318,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
|
||||
--pollinterval=<time> time between polling of meters, default is 10m
|
||||
--pollinterval=<time> time between polling of meters, must be set to get polling.
|
||||
--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
|
||||
|
|
|
@ -55,6 +55,7 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
|
|||
string id;
|
||||
string key = "";
|
||||
string linkmodes;
|
||||
int poll_interval = 0;
|
||||
vector<string> telegram_shells;
|
||||
vector<string> alarm_shells;
|
||||
vector<string> extra_constant_fields;
|
||||
|
@ -109,6 +110,19 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
|
|||
debug("(config) key=<notprinted>\n");
|
||||
}
|
||||
else
|
||||
if (p.first == "pollinterval") {
|
||||
if (poll_interval != 0)
|
||||
{
|
||||
error("You have already specified a poll interval for this meter!\n");
|
||||
}
|
||||
poll_interval = parseTime(p.second);
|
||||
|
||||
if (poll_interval == 0)
|
||||
{
|
||||
error("Poll interval must be non-zero \"%s\"!\n", p.second.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
if (p.first == "shell") {
|
||||
telegram_shells.push_back(p.second);
|
||||
}
|
||||
|
@ -136,6 +150,7 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
|
|||
|
||||
MeterInfo mi;
|
||||
mi.parse(name, driver, id, key); // sets driver, extras, name, bus, bps, link_modes, ids, name, key
|
||||
mi.poll_interval = poll_interval;
|
||||
|
||||
/*
|
||||
Ignore link mode checking until all drivers have been refactored.
|
||||
|
|
|
@ -96,7 +96,7 @@ struct Configuration
|
|||
std::string logfile;
|
||||
bool json {};
|
||||
bool pretty_print_json {};
|
||||
int pollinterval = 60*10; // Time between polling, default 10 minutes.
|
||||
int pollinterval {}; // Time between polling of mbus meters.
|
||||
bool fields {};
|
||||
char separator { ';' };
|
||||
std::vector<std::string> telegram_shells;
|
||||
|
|
|
@ -447,7 +447,7 @@ void setup_meters(Configuration *config, MeterManager *manager)
|
|||
{
|
||||
m.conversions = config->conversions;
|
||||
|
||||
if (m.link_modes.has(LinkMode::MBUS) || needsPolling(m.driver, m.driver_name))
|
||||
if (m.needsPolling() || driverNeedsPolling(m.driver, m.driver_name))
|
||||
{
|
||||
// A polling meter must be defined from the start.
|
||||
auto meter = createMeter(&m);
|
||||
|
|
|
@ -1015,8 +1015,11 @@ void MeterCommonImplementation::addStringFieldWithExtractorAndLookup(string vnam
|
|||
|
||||
void MeterCommonImplementation::poll(shared_ptr<BusManager> bus_manager)
|
||||
{
|
||||
if (link_modes_.has(LinkMode::MBUS))
|
||||
if (needsPolling())
|
||||
{
|
||||
// An valid poll interval must have been set!
|
||||
if (pollInterval() <= 0) return;
|
||||
|
||||
time_t now = time(NULL);
|
||||
time_t next_poll_time = timestampLastUpdate()+pollInterval();
|
||||
if (now < next_poll_time)
|
||||
|
@ -1029,7 +1032,7 @@ void MeterCommonImplementation::poll(shared_ptr<BusManager> bus_manager)
|
|||
|
||||
if (!bus_device)
|
||||
{
|
||||
debug("(meter) Could not find bus from name \"%s\"\n", bus().c_str());
|
||||
warning("(meter) warning! no bus specified for meter %s %s\n", name().c_str(), idsc().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1061,7 +1064,10 @@ void MeterCommonImplementation::poll(shared_ptr<BusManager> bus_manager)
|
|||
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());
|
||||
verbose("(meter) polling %s %s (primary) with req ud2 on bus %s\n",
|
||||
name().c_str(),
|
||||
id.c_str(),
|
||||
bus_device->busAlias().c_str(),id.c_str());
|
||||
bus_device->serial()->send(buf);
|
||||
}
|
||||
|
||||
|
@ -1118,7 +1124,10 @@ void MeterCommonImplementation::poll(shared_ptr<BusManager> bus_manager)
|
|||
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());
|
||||
verbose("(meter) polling %s %s (secondary) with req ud2 bus %s\n",
|
||||
name().c_str(),
|
||||
id.c_str(),
|
||||
bus_device->busAlias().c_str());
|
||||
bus_device->serial()->send(buf);
|
||||
}
|
||||
}
|
||||
|
@ -1187,6 +1196,10 @@ time_t MeterCommonImplementation::timestampLastUpdate()
|
|||
void MeterCommonImplementation::setPollInterval(time_t interval)
|
||||
{
|
||||
poll_interval_ = interval;
|
||||
if (needsPolling() && poll_interval_ == 0)
|
||||
{
|
||||
warning("(meter) %s %s needs polling but has no pollinterval set!\n", name().c_str(), idsc().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
time_t MeterCommonImplementation::pollInterval()
|
||||
|
@ -1194,7 +1207,15 @@ time_t MeterCommonImplementation::pollInterval()
|
|||
return poll_interval_;
|
||||
}
|
||||
|
||||
bool needsPolling(MeterDriver d, DriverName& dn)
|
||||
bool MeterCommonImplementation::needsPolling()
|
||||
{
|
||||
return link_modes_.has(LinkMode::MBUS) ||
|
||||
link_modes_.has(LinkMode::C2) ||
|
||||
link_modes_.has(LinkMode::T2) ||
|
||||
link_modes_.has(LinkMode::S2);
|
||||
}
|
||||
|
||||
bool driverNeedsPolling(MeterDriver d, DriverName& dn)
|
||||
{
|
||||
if (d != MeterDriver::UNKNOWN && d != MeterDriver::AUTO)
|
||||
{
|
||||
|
@ -1209,7 +1230,10 @@ LIST_OF_METERS
|
|||
DriverInfo& di = all_registered_drivers_[dn.str()];
|
||||
|
||||
// Return true for MBUS,S2,C2,T2 meters. Currently only mbus is implemented.
|
||||
return di.linkModes().has(LinkMode::MBUS);
|
||||
return di.linkModes().has(LinkMode::MBUS) ||
|
||||
di.linkModes().has(LinkMode::C2) ||
|
||||
di.linkModes().has(LinkMode::T2) ||
|
||||
di.linkModes().has(LinkMode::S2);
|
||||
}
|
||||
|
||||
const char *toString(MeterType type)
|
||||
|
@ -2091,6 +2115,7 @@ shared_ptr<Meter> createMeter(MeterInfo *mi)
|
|||
DriverInfo& di = all_registered_drivers_[mi->driver_name.str()];
|
||||
shared_ptr<Meter> newm = di.construct(*mi);
|
||||
newm->addConversions(mi->conversions);
|
||||
newm->setPollInterval(mi->poll_interval);
|
||||
verbose("(meter) constructed \"%s\" \"%s\" \"%s\" %s\n",
|
||||
mi->name.c_str(),
|
||||
di.name().str().c_str(),
|
||||
|
@ -2106,6 +2131,7 @@ shared_ptr<Meter> createMeter(MeterInfo *mi)
|
|||
{ \
|
||||
newm = create##cname(*mi); \
|
||||
newm->addConversions(mi->conversions); \
|
||||
newm->setPollInterval(mi->poll_interval); \
|
||||
verbose("(meter) created \"%s\" \"" #mname "\" \"%s\" %s\n", \
|
||||
mi->name.c_str(), mi->idsc.c_str(), keymsg); \
|
||||
return newm; \
|
||||
|
@ -2253,6 +2279,14 @@ bool MeterInfo::parse(string n, string d, string i, string k)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MeterInfo::needsPolling()
|
||||
{
|
||||
return link_modes.has(LinkMode::MBUS) ||
|
||||
link_modes.has(LinkMode::C2) ||
|
||||
link_modes.has(LinkMode::T2) ||
|
||||
link_modes.has(LinkMode::S2);
|
||||
}
|
||||
|
||||
bool isValidKey(string& key, MeterDriver mt)
|
||||
{
|
||||
if (key.length() == 0) return true;
|
||||
|
|
|
@ -226,6 +226,7 @@ struct MeterInfo
|
|||
}
|
||||
|
||||
bool parse(string name, string driver, string id, string key);
|
||||
bool needsPolling();
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -277,8 +278,8 @@ bool registerDriver(function<void(DriverInfo&di)> setup);
|
|||
bool lookupDriverInfo(string& driver, DriverInfo *di);
|
||||
// Return the best driver match for a telegram.
|
||||
DriverInfo pickMeterDriver(Telegram *t);
|
||||
// Return true for mbus and S2/C2/T2 meters.
|
||||
bool needsPolling(MeterDriver driver, DriverName& dn);
|
||||
// Return true for mbus and S2/C2/T2 drivers.
|
||||
bool driverNeedsPolling(MeterDriver driver, DriverName& dn);
|
||||
|
||||
vector<DriverInfo>& allRegisteredDrivers();
|
||||
|
||||
|
@ -433,6 +434,7 @@ struct Meter
|
|||
virtual time_t timestampLastUpdate() = 0;
|
||||
virtual void setPollInterval(time_t interval) = 0;
|
||||
virtual time_t pollInterval() = 0;
|
||||
virtual bool needsPolling() = 0;
|
||||
|
||||
virtual void setNumericValue(FieldInfo *fi, Unit u, double v) = 0;
|
||||
virtual double getNumericValue(FieldInfo *fi, Unit u) = 0;
|
||||
|
|
|
@ -65,7 +65,7 @@ struct MeterCommonImplementation : public virtual Meter
|
|||
time_t timestampLastUpdate();
|
||||
void setPollInterval(time_t interval);
|
||||
time_t pollInterval();
|
||||
|
||||
bool needsPolling();
|
||||
|
||||
void onUpdate(function<void(Telegram*,Meter*)> cb);
|
||||
int numUpdates();
|
||||
|
|
|
@ -72,7 +72,7 @@ int main(int argc, char **argv)
|
|||
/*
|
||||
test_linkmodes();*/
|
||||
test_ids();
|
||||
test_addresses();
|
||||
// test_addresses();
|
||||
test_kdf();
|
||||
test_periods();
|
||||
test_months();
|
||||
|
@ -924,7 +924,7 @@ void test_meters()
|
|||
"", // extras
|
||||
"", // bus
|
||||
"0", // bps
|
||||
"c1,t1,mbus"); // linkmodes
|
||||
"mbus,c1,t1"); // linkmodes
|
||||
|
||||
/*
|
||||
config_content =
|
||||
|
|
27
src/wmbus.h
27
src/wmbus.h
|
@ -81,18 +81,21 @@ void setIgnoreDuplicateTelegrams(bool idt);
|
|||
|
||||
#define LIST_OF_LINK_MODES \
|
||||
X(Any,any,--anylinkmode,0xffff) \
|
||||
X(C1,c1,--c1,0x1) \
|
||||
X(S1,s1,--s1,0x2) \
|
||||
X(S1m,s1m,--s1m,0x4) \
|
||||
X(T1,t1,--t1,0x8) \
|
||||
X(N1a,n1a,--n1a,0x10) \
|
||||
X(N1b,n1b,--n1b,0x20) \
|
||||
X(N1c,n1c,--n1c,0x40) \
|
||||
X(N1d,n1d,--n1d,0x80) \
|
||||
X(N1e,n1e,--n1e,0x100) \
|
||||
X(N1f,n1f,--n1f,0x200) \
|
||||
X(MBUS,mbus,--mbus,0x400) \
|
||||
X(LORA,lora,--lora,0x800) \
|
||||
X(MBUS,mbus,--mbus,0x1) \
|
||||
X(C1,c1,--c1,0x2) \
|
||||
X(S1,s1,--s1,0x4) \
|
||||
X(S1m,s1m,--s1m,0x8) \
|
||||
X(T1,t1,--t1,0x10) \
|
||||
X(C2,c2,--c2,0x20) \
|
||||
X(S2,s2,--s2,0x40) \
|
||||
X(T2,t2,--t2,0x80) \
|
||||
X(N1a,n1a,--n1a,0x100) \
|
||||
X(N1b,n1b,--n1b,0x200) \
|
||||
X(N1c,n1c,--n1c,0x400) \
|
||||
X(N1d,n1d,--n1d,0x800) \
|
||||
X(N1e,n1e,--n1e,0x1000) \
|
||||
X(N1f,n1f,--n1f,0x2000) \
|
||||
X(LORA,lora,--lora,0x400) \
|
||||
X(UNKNOWN,unknown,----,0x0)
|
||||
|
||||
enum class LinkMode {
|
||||
|
|
|
@ -93,6 +93,8 @@ Add :verbose to any analyze to get more verbose analyze output.
|
|||
|
||||
\fB\--oneshot\fR wait for an update from each meter, then quit
|
||||
|
||||
\fB\--pollinterval=\fR<interval> poll mbus meters every <interval>, default is 10m.
|
||||
|
||||
\fB\--ppjson\fR pretty print the json output
|
||||
|
||||
\fB\--resetafter=\fR<time> reset the wmbus dongle regularly, default is 23h
|
||||
|
|
Ładowanie…
Reference in New Issue