42 return "Safety Monitor";
50 ConnectionStringsTP[0].
fill(
"DEVICES",
"Devices",
"");
53 ConnectionStringsTP.
load();
60 OverrideSP[0].
fill(
"OVERRIDE",
"Override Status",
ISS_OFF);
83 if (SafetyStatusLP.
count() > 0)
89 if (SafetyStatusLP.
count() > 0)
100 rebuildSafetyStatusProperty();
107 for (
auto &client : m_Clients)
109 client->disconnectServer();
120 ConnectionStringsTP.
update(texts, names, n);
122 ConnectionStringsTP.
apply();
125 rebuildSafetyStatusProperty();
140 OverrideSP.
update(states, names, n);
142 if (OverrideSP[0].getState() ==
ISS_ON)
144 LOG_WARN(
"Safety override is enabled. Observatory safety is overridden. Turn off as soon as possible.");
149 LOG_INFO(
"Safety override is disabled");
156 updateOverallStatus();
169 ConnectionStringsTP.
save(fp);
174void SafetyMonitor::parseConnectionStrings()
176 std::string connStr = ConnectionStringsTP[0].
getText();
180 LOG_WARN(
"No connection strings configured");
192 std::istringstream iss(connStr);
193 std::string deviceEntry;
195 while (std::getline(iss, deviceEntry,
','))
198 size_t start = deviceEntry.find_first_not_of(
" \t\n\r");
199 size_t end = deviceEntry.find_last_not_of(
" \t\n\r");
201 if (start == std::string::npos)
204 deviceEntry = deviceEntry.substr(start, end - start + 1);
206 if (deviceEntry.empty())
211 std::string deviceName, host;
214 size_t atPos = deviceEntry.find(
'@');
215 if (atPos != std::string::npos)
218 deviceName = deviceEntry.substr(0, atPos);
219 std::string hostPort = deviceEntry.substr(atPos + 1);
222 size_t nameEnd = deviceName.find_last_not_of(
" \t");
223 if (nameEnd != std::string::npos)
224 deviceName = deviceName.substr(0, nameEnd + 1);
227 size_t colonPos = hostPort.find(
':');
228 if (colonPos != std::string::npos)
231 host = hostPort.substr(0, colonPos);
233 port = std::stoi(hostPort.substr(colonPos + 1));
235 LOGF_ERROR(
"Invalid port in '%s', using default 7624", deviceEntry.c_str());
245 size_t hostStart = host.find_first_not_of(
" \t");
246 size_t hostEnd = host.find_last_not_of(
" \t");
247 if (hostStart != std::string::npos)
248 host = host.substr(hostStart, hostEnd - hostStart + 1);
253 deviceName = deviceEntry;
257 if (deviceName.empty())
259 LOGF_WARN(
"Empty device name in entry: %s", deviceEntry.c_str());
263 LOGF_INFO(
"Configuring connection to '%s'@%s:%d",
264 deviceName.c_str(), host.c_str(), port);
267 auto client = std::make_unique<SafetyMonitorClient>(
269 [
this]() { this->updateOverallStatus(); }
272 if (client->connectToServer(host, port))
274 m_Clients.push_back(std::move(client));
278 LOGF_ERROR(
"Failed to create client for %s", deviceName.c_str());
282 if (m_Clients.empty())
284 LOG_WARN(
"No valid device connections configured");
288void SafetyMonitor::rebuildSafetyStatusProperty()
291 if (SafetyStatusLP.
count() > 0)
297 for (
auto &client : m_Clients)
299 client->disconnectServer();
304 parseConnectionStrings();
309 for (
auto &client : m_Clients)
312 oneLight.
fill(client->getMonitoredDeviceName().c_str(),
313 client->getMonitoredDeviceName().c_str(),
315 SafetyStatusLP.
push(std::move(oneLight));
324 updateOverallStatus();
328void SafetyMonitor::updateOverallStatus()
330 if (SafetyStatusLP.
count() == 0)
337 for (
size_t i = 0; i < m_Clients.size() && i < SafetyStatusLP.
count(); i++)
339 auto &client = m_Clients[i];
340 auto &light = SafetyStatusLP[i];
342 if (client->isDeviceOnline() && client->hasSafetyStatus())
344 IPState deviceState = client->getSafetyStatus();
348 if (deviceState > worstState)
349 worstState = deviceState;
359 if (OverrideSP[0].getState() ==
ISS_ON)
362 LOGF_DEBUG(
"Safety override active, forcing status to OK (actual worst: %d)", worstState);
366 SafetyStatusLP.
setState(worstState);
367 SafetyStatusLP.
apply();
369 LOGF_DEBUG(
"Overall safety status updated: %d", worstState);
const char * getDeviceName() const
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool initProperties()
Initialize properties initial state and value. The child class must implement this function.
void addDebugControl()
Add Debug control to the driver.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
void push(WidgetView< T > &&item)
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool load()
load Attempt to load property values from configuration file.
void save(FILE *f) const
save Save property to configuration file.
bool isNameMatch(const char *otherName) const
void fill(const char *device, const char *name, const char *label, const char *group, IPState state)
bool update(const ISState states[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
bool update(const char *const texts[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
INDI::PropertyViewText * getText() const
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
const char * getDefaultName() override
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool Disconnect() override
Disconnect from device.
virtual bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
#define LOGF_INFO(fmt,...)
#define LOGF_WARN(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)
std::unique_ptr< SafetyMonitor > safetyMonitor(new SafetyMonitor())