31#ifdef _USE_SYSTEM_JSONLIB
32#include <nlohmann/json.hpp>
43static size_t WSP_WriteCallback(
void *contents,
size_t size,
size_t nmemb,
void *userp)
45 ((std::string *)userp)->append((
char *)contents, size * nmemb);
60 return "Weather Safety Proxy";
77 keywordTP[0].
fill(
"WEATHER_CONDITION",
"Weather Condition",
"condition");
80 ScriptsTP[
WSP_SCRIPT].
fill(
"WEATHER_SAFETY_SCRIPT",
"Weather safety script",
81 "/usr/local/share/indi/scripts/weather_status.py");
85 UrlTP[
WSP_URL].
fill(
"WEATHER_SAFETY_URL",
"Weather safety URL",
"http://0.0.0.0:5000/weather/safety");
94 softErrorHysteresisNP[
WSP_SOFT_ERROR_MAX].
fill(
"SOFT_ERROR_MAX",
"Max soft errors",
"%g", 0.0, 1000.0, 1.0, 30.0);
96 0.0, 1000.0, 1.0, 7.0);
100 addParameter(
"WEATHER_SAFETY",
"Weather Safety", 0.9, 1.1, 0);
103 reasonsTP[0].
fill(
"Reasons",
"",
nullptr);
104 reasonsTP.
fill(
getDeviceName(),
"WEATHER_SAFETY_REASONS",
"Weather Safety Reasons",
133 ScriptOrCurlSP.
save(fp);
134 softErrorHysteresisNP.
save(fp);
141 static bool once =
true;
162 softErrorHysteresisNP.
update(values, names, n);
164 softErrorHysteresisNP.
apply();
178 keywordTP.
update(texts, names, n);
186 ScriptsTP.
update(texts, names, n);
194 UrlTP.
update(texts, names, n);
210 LOG_DEBUG(
"WeatherSafetyProxy::ISNewSwitch");
211 ScriptOrCurlSP.
update(states, names, n);
213 ScriptOrCurlSP.
apply();
227 ret = executeScript();
238 LOGF_WARN(
"Soft error %d occurred during SAFE conditions, counting", SofterrorCount);
241 char Warning[] =
"Max softerrors reached while Weather was SAFE";
245 reasonsTP[0].setText(Warning);
248 SofterrorRecoveryMode =
true;
254 LOG_WARN(
"Soft error occurred during UNSAFE conditions, ignore");
256 SofterrorRecoveryCount = 0;
266IPState WeatherSafetyProxy::executeScript()
270 if (access(
cmd, F_OK | X_OK) == -1)
272 LOGF_ERROR(
"Cannot use script [%s], check its existence and permissions",
cmd);
273 LastParseSuccess =
false;
278 FILE *handle = popen(
cmd,
"r");
279 if (handle ==
nullptr)
282 LastParseSuccess =
false;
286 size_t byte_count = fread(buf, 1, BUFSIZ - 1, handle);
292 LastParseSuccess =
false;
295 LOGF_DEBUG(
"Read %d bytes output [%s]", byte_count, buf);
297 return parseSafetyJSON(buf);
300IPState WeatherSafetyProxy::executeCurl()
304 std::string readBuffer;
306 curl_handle = curl_easy_init();
309 curl_easy_setopt(curl_handle, CURLOPT_URL, UrlTP[
WSP_URL].
getText());
310 curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WSP_WriteCallback);
311 curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &readBuffer);
312 curl_easy_setopt(curl_handle, CURLOPT_USERAGENT,
"libcurl-agent/1.0");
314 res = curl_easy_perform(curl_handle);
317 LOGF_ERROR(
"curl_easy_perform failed with [%s]", curl_easy_strerror(res));
320 curl_easy_cleanup(curl_handle);
321 LOGF_DEBUG(
"Read %d bytes output [%s]", readBuffer.size(), readBuffer.c_str());
322 return parseSafetyJSON(readBuffer);
331IPState WeatherSafetyProxy::parseSafetyJSON(
const std::string &buffer)
333 json report = json::parse(buffer);
337 report[
"roof_status"][
"open_ok"].
get_to(NewSafety);
339 if (NewSafety != Safety)
347 if (SofterrorRecoveryMode ==
true)
349 SofterrorRecoveryCount++;
352 LOG_INFO(
"Minimum soft recovery errors reached while Weather was SAFE");
353 SofterrorRecoveryCount = 0;
354 SofterrorRecoveryMode =
false;
358 LOGF_INFO(
"Weather is SAFE but soft error recovery %d is still counting", SofterrorRecoveryCount);
375 report[
"roof_status"][
"reasons"].
get_to(reasons);
376 if (SofterrorRecoveryMode ==
true)
379 snprintf(newReasons,
MAXRBUF,
"SofterrorRecoveryMode, %s", reasons.c_str());
380 reasonsTP[0].setText(newReasons);
384 reasonsTP[0].setText(reasons.c_str());
INDI::PropertyText getText(const char *name) const
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool loadConfig(bool silent=false, const char *property=nullptr)
Load the last saved configuration file.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
void addDebugControl()
Add Debug control to the driver.
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
bool isNameMatch(const char *otherName) const
bool update(const double values[], 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)
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
void addParameter(std::string name, std::string label, double numMinOk, double numMaxOk, double percWarning, bool flipWarning=false)
Add a physical weather measurable parameter to the weather driver.
bool setCriticalParameter(std::string name)
setCriticalParameter Set parameter that is considered critical to the operation of the observatory....
void setParameterValue(std::string name, double value)
setParameterValue Update weather parameter value
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
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 saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
void setWeatherConnection(const uint8_t &value)
setWeatherConnection Set Weather connection mode. Child class should call this in the constructor bef...
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
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 saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
const char * getDefaultName() override
virtual IPState updateWeather() override
updateWeather Update weather conditions from device or service. The function should not change the st...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual ~WeatherSafetyProxy()
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
bool Disconnect() override
Disconnect from device.
a class to store JSON values
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
general exception of the basic_json class
const int id
the id of the exception
const char * what() const noexcept override
returns the explanatory string
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 LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
basic_json<> json
default specialization
std::unique_ptr< WeatherSafetyProxy > weatherSafetyProxy(new WeatherSafetyProxy())
@ WSP_SOFT_ERROR_RECOVERY