kopia lustrzana https://github.com/weetmuts/wmbusmeters
Added resetafter, regular reset.
rodzic
7c361ce9ac
commit
7e07af03e7
|
@ -166,6 +166,7 @@ As <options> you can use:
|
|||
--meterfilestimestamp=(never|day|hour|minute|micros) the meter file is suffixed with a
|
||||
timestamp (localtime) with the given resolution.
|
||||
--oneshot wait for an update from each meter, then quit
|
||||
--resetafter=<time> reset the wmbus dongle regularly, default is 24h
|
||||
--selectfields=id,timestamp,total_m3 select fields to be printed
|
||||
--separator=<c> change field separator to c
|
||||
--shell=<cmdline> invokes cmdline with env variables containing the latest reading
|
||||
|
|
|
@ -429,6 +429,14 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv) {
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--resetafter=", 13) && strlen(argv[i]) > 13) {
|
||||
c->resetafter = parseTime(argv[i]+13);
|
||||
if (c->resetafter <= 0) {
|
||||
error("Not a valid time to regularly reset after. \"%s\"\n", argv[i]+13);
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--alarmtimeout=", 15)) {
|
||||
c->alarm_timeout = parseTime(argv[i]+15);
|
||||
if (c->alarm_timeout <= 0) {
|
||||
|
|
|
@ -189,6 +189,22 @@ void handleInternalTesting(Configuration *c, string value)
|
|||
}
|
||||
}
|
||||
|
||||
void handleResetAfter(Configuration *c, string s)
|
||||
{
|
||||
if (s.length() >= 1)
|
||||
{
|
||||
c->resetafter = parseTime(s.c_str());
|
||||
if (c->resetafter <= 0)
|
||||
{
|
||||
warning("Not a valid time to reset wmbus devices after. \"%s\"\n", s.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
warning("Reset after must be a valid number of seconds.\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool handleDevice(Configuration *c, string devicefile)
|
||||
{
|
||||
Device device;
|
||||
|
@ -456,6 +472,7 @@ shared_ptr<Configuration> loadConfiguration(string root, string device_override,
|
|||
else if (p.first == "addconversions") handleConversions(c, p.second);
|
||||
else if (p.first == "selectfields") handleSelectedFields(c, p.second);
|
||||
else if (p.first == "shell") handleShell(c, p.second);
|
||||
else if (p.first == "resetafter") handleResetAfter(c, p.second);
|
||||
else if (p.first == "alarmshell") handleAlarmShell(c, p.second);
|
||||
else if (startsWith(p.first, "json_"))
|
||||
{
|
||||
|
|
|
@ -82,6 +82,7 @@ struct Configuration
|
|||
std::string list_meter;
|
||||
bool oneshot {};
|
||||
int exitafter {}; // Seconds to exit.
|
||||
int resetafter {}; // Reset the wmbus devices regularly.
|
||||
std::vector<Device> supplied_wmbus_devices; // /dev/ttyUSB0, simulation.txt, rtlwmbus, /dev/ttyUSB1:9600
|
||||
bool use_auto_detect {}; // Set to true if auto was supplied as device.
|
||||
std::vector<Device> supplied_mbus_devices; // /dev/ttyACM0
|
||||
|
|
10
src/main.cc
10
src/main.cc
|
@ -563,8 +563,14 @@ void open_wmbus_device(Configuration *config, string how, string device, Detecte
|
|||
wmbus_devices_.push_back(w);
|
||||
WMBus *wmbus = wmbus_devices_.back().get();
|
||||
wmbus->setLinkModes(config->listen_to_link_modes);
|
||||
//string using_link_modes = wmbus->getLinkModes().hr();
|
||||
//verbose("(config) listen to link modes: %s\n", using_link_modes.c_str());
|
||||
|
||||
// By default, reset your dongle once every day.
|
||||
int regular_reset = 24*3600;
|
||||
if (config->resetafter != 0) regular_reset = config->resetafter;
|
||||
wmbus->setResetInterval(regular_reset);
|
||||
|
||||
string using_link_modes = wmbus->getLinkModes().hr();
|
||||
verbose("(config) listen to link modes: %s\n", using_link_modes.c_str());
|
||||
bool simulated = false;
|
||||
if (detected->type == DEVICE_SIMULATOR)
|
||||
{
|
||||
|
|
|
@ -154,6 +154,14 @@ struct SerialDeviceImp : public SerialDevice
|
|||
SerialCommunicationManager *manager() { return manager_; }
|
||||
void resetInitiated() { debug("(serial) initiate reset\n"); resetting_ = true; }
|
||||
void resetCompleted() { debug("(serial) reset completed\n"); resetting_ = false; }
|
||||
bool checkIfDataIsPending()
|
||||
{
|
||||
if (!opened() || !working()) return false; // No data can be pending if device is not opened nor working.
|
||||
int available = -1;
|
||||
int rc = ioctl(fd_, FIONREAD, &available);
|
||||
if (rc == -1) return false;
|
||||
return available > 0;
|
||||
}
|
||||
|
||||
SerialDeviceImp(SerialCommunicationManagerImp *manager)
|
||||
{
|
||||
|
@ -249,7 +257,6 @@ struct SerialDeviceTTY : public SerialDeviceImp
|
|||
|
||||
AccessCheck open(bool fail_if_not_ok);
|
||||
void close();
|
||||
void checkIfShouldReopen();
|
||||
bool send(vector<uchar> &data);
|
||||
bool working();
|
||||
string device() { return device_; }
|
||||
|
@ -321,32 +328,6 @@ void SerialDeviceTTY::close()
|
|||
verbose("(serialtty) closed %s\n", device_.c_str());
|
||||
}
|
||||
|
||||
void SerialDeviceTTY::checkIfShouldReopen()
|
||||
{
|
||||
assert(0);
|
||||
/* if (fd_ != -1 && reopen_after_ > 0)
|
||||
{
|
||||
time_t curr = time(NULL);
|
||||
time_t diff = curr-start_since_reopen_;
|
||||
int available = 0;
|
||||
|
||||
ioctl(fd_, FIONREAD, &available);
|
||||
// Is it time to reopen AND there is no data available for reading?
|
||||
if (diff > reopen_after_ && !available)
|
||||
{
|
||||
start_since_reopen_ = curr;
|
||||
|
||||
debug("(serialtty) reopened after %ld seconds\n", diff);
|
||||
::flock(fd_, LOCK_UN);
|
||||
::close(fd_);
|
||||
fd_ = openSerialTTY(device_.c_str(), baud_rate_);
|
||||
if (fd_ == -1) {
|
||||
error("Could not re-open %s with %d baud N81\n", device_.c_str(), baud_rate_);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
bool SerialDeviceTTY::send(vector<uchar> &data)
|
||||
{
|
||||
LOCK_WRITE_SERIAL(send);
|
||||
|
@ -400,7 +381,6 @@ struct SerialDeviceCommand : public SerialDeviceImp
|
|||
|
||||
AccessCheck open(bool fail_if_not_ok);
|
||||
void close();
|
||||
void checkIfShouldReopen() {}
|
||||
bool send(vector<uchar> &data);
|
||||
int available();
|
||||
bool working();
|
||||
|
@ -528,7 +508,6 @@ struct SerialDeviceFile : public SerialDeviceImp
|
|||
AccessCheck open(bool fail_if_not_ok);
|
||||
void close();
|
||||
bool working();
|
||||
void checkIfShouldReopen();
|
||||
bool send(vector<uchar> &data);
|
||||
int available();
|
||||
string device() { return file_; }
|
||||
|
@ -615,10 +594,6 @@ bool SerialDeviceFile::working()
|
|||
return true;
|
||||
}
|
||||
|
||||
void SerialDeviceFile::checkIfShouldReopen()
|
||||
{
|
||||
}
|
||||
|
||||
bool SerialDeviceFile::send(vector<uchar> &data)
|
||||
{
|
||||
return true;
|
||||
|
@ -635,7 +610,6 @@ struct SerialDeviceSimulator : public SerialDeviceImp
|
|||
|
||||
AccessCheck open(bool fail_if_not_ok) { return AccessCheck::AccessOK; };
|
||||
void close() { };
|
||||
void checkIfShouldReopen() { }
|
||||
bool readonly() { return true; }
|
||||
bool send(vector<uchar> &data) { return true; };
|
||||
void fill(vector<uchar> &data) { data_ = data; on_data_(); }; // Fill buffer and trigger callback.
|
||||
|
|
|
@ -55,7 +55,7 @@ struct SerialDevice
|
|||
// Return underlying device as string.
|
||||
virtual std::string device() = 0;
|
||||
|
||||
virtual void checkIfShouldReopen() = 0;
|
||||
virtual bool checkIfDataIsPending() = 0;
|
||||
virtual void fill(std::vector<uchar> &data) = 0; // Fill buffer with raw data.
|
||||
virtual SerialCommunicationManager *manager() = 0;
|
||||
virtual void resetInitiated() = 0;
|
||||
|
|
23
src/wmbus.cc
23
src/wmbus.cc
|
@ -3278,6 +3278,7 @@ WMBusCommonImplementation::WMBusCommonImplementation(WMBusDeviceType t,
|
|||
{
|
||||
// Initialize timeout from now.
|
||||
last_received_ = time(NULL);
|
||||
last_reset_ = time(NULL);
|
||||
sem_init(&command_wait_, 0, 0);
|
||||
manager_->listenTo(this->serial(),call(this,processSerialData));
|
||||
manager_->onDisappear(this->serial(),call(this,disconnectedFromDevice));
|
||||
|
@ -3339,6 +3340,7 @@ LinkModeSet WMBusCommonImplementation::protectedGetLinkModes()
|
|||
|
||||
bool WMBusCommonImplementation::reset()
|
||||
{
|
||||
last_reset_ = time(NULL);
|
||||
bool resetting = false;
|
||||
if (serial())
|
||||
{
|
||||
|
@ -3393,6 +3395,22 @@ bool WMBusCommonImplementation::isWorking()
|
|||
void WMBusCommonImplementation::checkStatus()
|
||||
{
|
||||
trace("[ALARM] check status\n");
|
||||
|
||||
time_t since_last_reset = time(NULL) - last_reset_;
|
||||
if (reset_timeout_ > 1 &&
|
||||
since_last_reset > reset_timeout_ &&
|
||||
!serial()->checkIfDataIsPending() &&
|
||||
!serial()->readonly())
|
||||
{
|
||||
verbose("(wmbus) regular reset of %s %s\n", device().c_str(), toString(type()));
|
||||
bool ok = reset();
|
||||
if (ok) return;
|
||||
string msg;
|
||||
strprintf(msg, "failed regular reset of %s %s", device().c_str(), toString(type()));
|
||||
logAlarm("regular_reset", msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (protocol_error_count_ >= 20)
|
||||
{
|
||||
string msg;
|
||||
|
@ -3465,6 +3483,11 @@ void WMBusCommonImplementation::checkStatus()
|
|||
}
|
||||
}
|
||||
|
||||
void WMBusCommonImplementation::setResetInterval(int seconds)
|
||||
{
|
||||
reset_timeout_ = seconds;
|
||||
}
|
||||
|
||||
void WMBusCommonImplementation::setTimeout(int seconds, string expected_activity)
|
||||
{
|
||||
assert(seconds >= 0);
|
||||
|
|
|
@ -495,6 +495,9 @@ struct WMBus
|
|||
// within seconds, then invoke reset(). However do not reset
|
||||
// when no activity is expected.
|
||||
virtual void setTimeout(int seconds, std::string expected_activity) = 0;
|
||||
// Set a regular interval for resetting the wmbus device.
|
||||
// Default is once ever 24 hours.
|
||||
virtual void setResetInterval(int seconds) = 0;
|
||||
virtual ~WMBus() = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ struct WMBusCommonImplementation : public virtual WMBus
|
|||
void checkStatus();
|
||||
bool isWorking();
|
||||
void setTimeout(int seconds, std::string expected_activity);
|
||||
void setResetInterval(int seconds);
|
||||
void setLinkModes(LinkModeSet lms);
|
||||
virtual void processSerialData() = 0;
|
||||
void disconnectedFromDevice();
|
||||
|
@ -69,7 +70,7 @@ struct WMBusCommonImplementation : public virtual WMBus
|
|||
string expected_activity_ {}; // During which times should we care about timeouts?
|
||||
time_t last_received_ {}; // When as the last telegram reception?
|
||||
time_t last_reset_ {}; // When did we last attempt a reset of the dongle?
|
||||
|
||||
int reset_timeout_ {}; // When set to 24*3600 reset the device once every 24 hours.
|
||||
bool link_modes_configured_ {};
|
||||
LinkModeSet link_modes_ {};
|
||||
|
||||
|
|
|
@ -65,6 +65,8 @@ mqtt_publish) sent to a REST API (eg curl) or store it in a database
|
|||
|
||||
\fB\--oneshot\fR wait for an update from each meter, then quit
|
||||
|
||||
\fB\--resetafter=\fR<time> reset the wmbus dongle regularly, default is 24h
|
||||
|
||||
\fB\--separator=\fR<c> change field separator to c
|
||||
|
||||
\fB\--selectfields=\fRid,timestamp,total_m3 select fields to be printed (--listfields=<meter> to list available fields)
|
||||
|
|
Ładowanie…
Reference in New Issue