Instrument Neutral Distributed Interface INDI  1.9.5
weather_safety_proxy.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2019 Hans Lambermont. All rights reserved.
3 
4  INDI Weather Safety Proxy
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the Free
8  Software Foundation; either version 2 of the License, or (at your option)
9  any later version.
10 
11  This program is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 
21  The full GNU General Public License is included in this distribution in the
22  file called LICENSE.
23 *******************************************************************************/
24 
25 #include <memory>
26 #include <unistd.h>
27 #include <sys/wait.h>
28 #include <cstring>
29 #include <curl/curl.h>
30 
31 #include "gason.h"
32 #include "weather_safety_proxy.h"
33 
34 std::unique_ptr<WeatherSafetyProxy> weatherSafetyProxy(new WeatherSafetyProxy());
35 
36 static size_t WSP_WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
37 {
38  ((std::string *)userp)->append((char *)contents, size * nmemb);
39  return size * nmemb;
40 }
41 
43 {
44  setVersion(1, 0);
45 
47 }
48 
50 
52 {
53  return "Weather Safety Proxy";
54 }
55 
57 {
58  return true;
59 }
60 
62 {
63  return true;
64 }
65 
67 {
69 
70  IUFillText(&keywordT[0], "WEATHER_CONDITION", "Weather Condition", "condition");
71  IUFillTextVector(&keywordTP, keywordT, 1, getDeviceName(), "KEYWORD", "Keywords", OPTIONS_TAB, IP_RW, 60, IPS_IDLE);
72 
73  IUFillText(&ScriptsT[WSP_SCRIPT], "WEATHER_SAFETY_SCRIPT", "Weather safety script", "/usr/local/share/indi/scripts/weather_status.py");
74  IUFillTextVector(&ScriptsTP, ScriptsT, WSP_SCRIPT_COUNT, getDefaultName(), "WEATHER_SAFETY_SCRIPTS", "Script", OPTIONS_TAB, IP_RW, 100, IPS_IDLE);
75 
76  IUFillText(&UrlT[WSP_URL], "WEATHER_SAFETY_URL", "Weather safety URL", "http://0.0.0.0:5000/weather/safety");
77  IUFillTextVector(&UrlTP, UrlT, WSP_URL_COUNT, getDefaultName(), "WEATHER_SAFETY_URLS", "Url", OPTIONS_TAB, IP_RW, 100, IPS_IDLE);
78 
79  IUFillSwitch(&ScriptOrCurlS[WSP_USE_SCRIPT], "Use script", "", ISS_ON);
80  IUFillSwitch(&ScriptOrCurlS[WSP_USE_CURL], "Use url", "", ISS_OFF);
81  IUFillSwitchVector(&ScriptOrCurlSP, ScriptOrCurlS, WSP_USE_COUNT, getDeviceName(), "SCRIPT_OR_CURL", "Script or url", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
82 
83  IUFillNumber(&softErrorHysteresisN[WSP_SOFT_ERROR_MAX], "SOFT_ERROR_MAX", "Max soft errors", "%g", 0.0, 1000.0, 1.0, 30.0);
84  IUFillNumber(&softErrorHysteresisN[WSP_SOFT_ERROR_RECOVERY], "SOFT_ERROR_RECOVERY", "Minimum soft error for recovery", "%g", 0.0, 1000.0, 1.0, 7.0);
85  IUFillNumberVector(&softErrorHysteresisNP, softErrorHysteresisN, 2, getDeviceName(), "SOFT_ERROR_HYSTERESIS", "Soft error hysterese", OPTIONS_TAB, IP_RW, 0, IPS_IDLE);
86 
87  addParameter("WEATHER_SAFETY", "Weather Safety", 0.9, 1.1, 0); // 0 is unsafe, 1 is safe
88  setCriticalParameter("WEATHER_SAFETY");
89 
90  IUFillText(&reasonsT[0], "Reasons", "", nullptr);
91  IUFillTextVector(&reasonsTP, reasonsT, 1, getDeviceName(), "WEATHER_SAFETY_REASONS", "Weather Safety Reasons", MAIN_CONTROL_TAB, IP_RO, 120, IPS_IDLE);
92 
94 
95  return true;
96 }
97 
99 {
101 
102  if (isConnected())
103  {
104  defineProperty(&reasonsTP);
105  }
106  else
107  {
108  deleteProperty(reasonsTP.name);
109  }
110 
111  return true;
112 }
113 
115 {
117  IUSaveConfigText(fp, &ScriptsTP);
118  IUSaveConfigText(fp, &UrlTP);
119  IUSaveConfigSwitch(fp, &ScriptOrCurlSP);
120  IUSaveConfigNumber(fp, &softErrorHysteresisNP);
121  return true;
122 }
123 
125 {
127  static bool once = true;
128  if (once)
129  {
130  once = false;
131  defineProperty(&ScriptsTP);
132  defineProperty(&UrlTP);
133  defineProperty(&ScriptOrCurlSP);
134  defineProperty(&softErrorHysteresisNP);
135  loadConfig(false, "WEATHER_SAFETY_SCRIPTS");
136  loadConfig(false, "WEATHER_SAFETY_URLS");
137  loadConfig(false, "SCRIPT_OR_CURL");
138  loadConfig(false, "SOFT_ERROR_HYSTERESIS");
139  }
140 }
141 
142 bool WeatherSafetyProxy::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
143 {
144  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
145  {
146  if (strcmp(name, softErrorHysteresisNP.name) == 0)
147  {
148  LOG_DEBUG("WeatherSafetyProxy::ISNewNumber");
149  IUUpdateNumber(&softErrorHysteresisNP, values, names, n);
150  softErrorHysteresisNP.s = IPS_OK;
151  IDSetNumber(&softErrorHysteresisNP, nullptr);
152  return true;
153  }
154  }
155  return INDI::Weather::ISNewNumber(dev, name, values, names, n);
156 }
157 
158 bool WeatherSafetyProxy::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
159 {
160  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
161  {
162  if (strcmp(name, keywordTP.name) == 0)
163  {
164  keywordTP.s = IPS_OK;
165  IUUpdateText(&keywordTP, texts, names, n);
166  // update client display
167  IDSetText(&keywordTP, nullptr);
168  return true;
169  }
170  if (strcmp(name, ScriptsTP.name) == 0)
171  {
172  ScriptsTP.s = IPS_OK;
173  IUUpdateText(&ScriptsTP, texts, names, n);
174  // update client display
175  IDSetText(&ScriptsTP, nullptr);
176  return true;
177  }
178  if (strcmp(name, UrlTP.name) == 0)
179  {
180  UrlTP.s = IPS_OK;
181  IUUpdateText(&UrlTP, texts, names, n);
182  // update client display
183  IDSetText(&UrlTP, nullptr);
184  return true;
185  }
186  }
187 
188  return INDI::Weather::ISNewText(dev, name, texts, names, n);
189 }
190 
191 bool WeatherSafetyProxy::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
192 {
193  if (!strcmp(getDeviceName(), dev))
194  {
195  if (!strcmp(name, ScriptOrCurlSP.name))
196  {
197  LOG_DEBUG("WeatherSafetyProxy::ISNewSwitch");
198  IUUpdateSwitch(&ScriptOrCurlSP, states, names, n);
199  ScriptOrCurlSP.s = IPS_OK;
200  IDSetSwitch(&ScriptOrCurlSP, nullptr);
201  return true;
202  }
203  }
204 
205  return INDI::Weather::ISNewSwitch(dev, name, states, names, n);
206 }
207 
208 // Called by Weather::TimerHit every UpdatePeriodN[0].value seconds if we return IPS_OK or every 5 seconds otherwise
210 {
211  IPState ret = IPS_ALERT;
212  if (ScriptOrCurlS[WSP_USE_SCRIPT].s == ISS_ON)
213  {
214  ret = executeScript();
215  }
216  else
217  {
218  ret = executeCurl();
219  }
220  if (ret != IPS_OK)
221  {
222  if (Safety == WSP_SAFE)
223  {
224  SofterrorCount++;
225  LOGF_WARN("Soft error %d occurred during SAFE conditions, counting", SofterrorCount);
226  if (SofterrorCount > softErrorHysteresisN[WSP_SOFT_ERROR_MAX].value)
227  {
228  char Warning[] = "Max softerrors reached while Weather was SAFE";
229  LOG_WARN(Warning);
230  Safety = WSP_UNSAFE;
231  setParameterValue("WEATHER_SAFETY", WSP_UNSAFE);
232  IUSaveText(&reasonsT[0], Warning);
233  reasonsTP.s = IPS_OK;
234  IDSetText(&reasonsTP, nullptr);
235  SofterrorRecoveryMode = true;
236  ret = IPS_OK; // So that indiweather actually syncs the CriticalParameters we just set
237  }
238  }
239  else
240  {
241  LOG_WARN("Soft error occurred during UNSAFE conditions, ignore");
242  SofterrorCount = 0;
243  SofterrorRecoveryCount = 0;
244  }
245  }
246  else
247  {
248  SofterrorCount = 0;
249  }
250  return ret;
251 }
252 
253 IPState WeatherSafetyProxy::executeScript()
254 {
255  const char *cmd = ScriptsT[WSP_SCRIPT].text;
256 
257  if (access(cmd, F_OK|X_OK) == -1)
258  {
259  LOGF_ERROR("Cannot use script [%s], check its existence and permissions", cmd);
260  LastParseSuccess = false;
261  return IPS_ALERT;
262  }
263 
264  LOGF_DEBUG("Run script: %s", cmd);
265  FILE *handle = popen(cmd, "r");
266  if (handle == nullptr)
267  {
268  LOGF_ERROR("Failed to run script [%s]", strerror(errno));
269  LastParseSuccess = false;
270  return IPS_ALERT;
271  }
272  char buf[BUFSIZ];
273  size_t byte_count = fread(buf, 1, BUFSIZ - 1, handle);
274  pclose(handle);
275  buf[byte_count] = 0;
276  if (byte_count == 0)
277  {
278  LOGF_ERROR("Got no output from script [%s]", cmd);
279  LastParseSuccess = false;
280  return IPS_ALERT;
281  }
282  LOGF_DEBUG("Read %d bytes output [%s]", byte_count, buf);
283 
284  return parseSafetyJSON(buf, byte_count);
285 }
286 
287 IPState WeatherSafetyProxy::executeCurl()
288 {
289  CURL *curl_handle;
290  CURLcode res;
291  std::string readBuffer;
292 
293  curl_handle = curl_easy_init();
294  if (curl_handle)
295  {
296  curl_easy_setopt(curl_handle, CURLOPT_URL, UrlT[WSP_URL].text);
297  curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WSP_WriteCallback);
298  curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &readBuffer);
299  curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
300  LOGF_DEBUG("Call curl %s", UrlT[WSP_URL].text);
301  res = curl_easy_perform(curl_handle);
302  if (res != CURLE_OK)
303  {
304  LOGF_ERROR("curl_easy_perform failed with [%s]", curl_easy_strerror(res));
305  return IPS_ALERT;
306  }
307  curl_easy_cleanup(curl_handle);
308  LOGF_DEBUG("Read %d bytes output [%s]", readBuffer.size(), readBuffer.c_str());
309  return parseSafetyJSON(readBuffer.c_str(), readBuffer.size());
310  }
311  else
312  {
313  LOG_ERROR("curl_easy_init failed");
314  return IPS_ALERT;
315  }
316 }
317 
318 IPState WeatherSafetyProxy::parseSafetyJSON(const char *clean_buf, int byte_count)
319 {
320  // copy clean_buf to buf which jsonParse can destroy
321  char buf[BUFSIZ];
322  strncpy(buf, clean_buf, byte_count);
323 
324  char *source = buf;
325  char *endptr;
326  JsonValue value;
327  JsonAllocator allocator;
328  int status = jsonParse(source, &endptr, &value, allocator);
329  if (status != JSON_OK)
330  {
331  LOGF_ERROR("jsonParse %s at position %zd", jsonStrError(status), endptr - source);
332  LastParseSuccess = false;
333  return IPS_ALERT;
334  }
335 
336  JsonIterator it;
337  JsonIterator observationIterator;
338  bool roof_status_found = false;
339  bool open_ok_found = false;
340  bool reasons_found = false;
341  bool error_found = false;
342  for (it = begin(value); it != end(value); ++it)
343  {
344  if (!strcmp(it->key, "roof_status"))
345  {
346  roof_status_found = true;
347  for (observationIterator = begin(it->value); observationIterator != end(it->value); ++observationIterator)
348  {
349  if (!strcmp(observationIterator->key, "open_ok"))
350  {
351  open_ok_found = true;
352  int NewSafety = observationIterator->value.toNumber();
353  if (NewSafety != Safety)
354  {
355  if (NewSafety == WSP_UNSAFE)
356  {
357  LOG_WARN("Weather is UNSAFE");
358  }
359  else if (NewSafety == WSP_SAFE)
360  {
361  if (SofterrorRecoveryMode == true)
362  {
363  SofterrorRecoveryCount++;
364  if (SofterrorRecoveryCount > softErrorHysteresisN[WSP_SOFT_ERROR_RECOVERY].value)
365  {
366  LOG_INFO("Minimum soft recovery errors reached while Weather was SAFE");
367  SofterrorRecoveryCount = 0;
368  SofterrorRecoveryMode = false;
369  }
370  else
371  {
372  LOGF_INFO("Weather is SAFE but soft error recovery %d is still counting", SofterrorRecoveryCount);
373  NewSafety = WSP_UNSAFE;
374  }
375  }
376  else
377  {
378  LOG_INFO("Weather is SAFE");
379  }
380  }
381  Safety = NewSafety;
382  }
383  setParameterValue("WEATHER_SAFETY", NewSafety);
384  }
385  else if (!strcmp(observationIterator->key, "reasons"))
386  {
387  reasons_found = true;
388  char *reasons = observationIterator->value.toString();
389  if (SofterrorRecoveryMode == true)
390  {
391  char newReasons[MAXRBUF];
392  snprintf(newReasons, MAXRBUF, "SofterrorRecoveryMode, %s", reasons);
393  IUSaveText(&reasonsT[0], newReasons);
394  }
395  else
396  {
397  IUSaveText(&reasonsT[0], reasons);
398  }
399  reasonsTP.s = IPS_OK;
400  IDSetText(&reasonsTP, nullptr);
401  }
402  }
403  }
404  if (!strcmp(it->key, "error"))
405  {
406  error_found = true;
407  }
408  }
409 
410  if (error_found)
411  {
412  LOGF_ERROR("Error hint found in JSON [%s]", clean_buf);
413  LastParseSuccess = false;
414  return IPS_ALERT;
415  }
416  if (!roof_status_found)
417  {
418  LOGF_ERROR("Found no roof_status field in JSON [%s]", clean_buf);
419  LastParseSuccess = false;
420  return IPS_ALERT;
421  }
422  if (!open_ok_found)
423  {
424  LOGF_ERROR("Found no open_ok field in roof_status JSON [%s]", clean_buf);
425  LastParseSuccess = false;
426  return IPS_ALERT;
427  }
428  // do not error if reasons are missing, they're not required for safety
429  if (!LastParseSuccess)
430  {
431  // show the good news. Once.
432  LOGF_INFO("Script output fully parsed, weather is %s", (Safety == 1) ? "SAFE" : "UNSAFE");
433  LastParseSuccess = true;
434  }
435  return IPS_OK;
436 }
WeatherSafetyProxy::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: weather_safety_proxy.cpp:114
WeatherSafetyProxy::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: weather_safety_proxy.cpp:142
WeatherSafetyProxy::Disconnect
bool Disconnect() override
Disconnect from device.
Definition: weather_safety_proxy.cpp:61
IP_RO
@ IP_RO
Definition: indiapi.h:183
jsonParse
int jsonParse(char *s, char **endptr, JsonValue *value, JsonAllocator &allocator)
Definition: gason.cpp:182
cmd
__u8 cmd[4]
Definition: pwc-ioctl.h:4
INDI::WeatherInterface::setCriticalParameter
bool setCriticalParameter(std::string param)
setCriticalParameter Set parameter that is considered critical to the operation of the observatory....
Definition: indiweatherinterface.cpp:167
IPState
IPState
Property state.
Definition: indiapi.h:158
WeatherSafetyProxy::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: weather_safety_proxy.cpp:191
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
WeatherSafetyProxy::getDefaultName
const char * getDefaultName() override
Definition: weather_safety_proxy.cpp:51
WSP_SOFT_ERROR_RECOVERY
@ WSP_SOFT_ERROR_RECOVERY
Definition: weather_safety_proxy.h:57
INDI::Weather::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indiweather.cpp:41
ISS_OFF
@ ISS_OFF
Definition: indiapi.h:150
JsonValue
Definition: gason.h:48
IDSetText
void IDSetText(const ITextVectorProperty *t, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing text vector property.
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
IUFillNumber
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
Definition: indidriver.c:348
INDI::DefaultDevice::defineProperty
void defineProperty(INumberVectorProperty *property)
Definition: defaultdevice.cpp:997
OPTIONS_TAB
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
Definition: defaultdevice.cpp:39
MAIN_CONTROL_TAB
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
Definition: defaultdevice.cpp:34
WeatherSafetyProxy::ISNewText
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
Definition: weather_safety_proxy.cpp:158
IUFillTextVector
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidriver.c:477
INDI::DefaultDevice::setVersion
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
Definition: defaultdevice.cpp:1219
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
WeatherSafetyProxy::~WeatherSafetyProxy
virtual ~WeatherSafetyProxy()
Definition: weather_safety_proxy.cpp:49
IUSaveConfigNumber
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indicom.c:1455
IUFillText
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
Definition: indidriver.c:369
INDI::Weather::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: indiweather.cpp:133
IUUpdateText
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:259
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
MAXRBUF
#define MAXRBUF
Definition: indidriver.c:52
JsonAllocator
Definition: gason.h:135
WeatherSafetyProxy::Connect
bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
Definition: weather_safety_proxy.cpp:56
jsonStrError
const char * jsonStrError(int err)
Definition: gason.cpp:31
WSP_USE_SCRIPT
@ WSP_USE_SCRIPT
Definition: weather_safety_proxy.h:43
WSP_UNSAFE
@ WSP_UNSAFE
Definition: weather_safety_proxy.h:50
WSP_SCRIPT
@ WSP_SCRIPT
Definition: weather_safety_proxy.h:53
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
INDI::Weather::setWeatherConnection
void setWeatherConnection(const uint8_t &value)
setWeatherConnection Set Weather connection mode. Child class should call this in the constructor bef...
Definition: indiweather.cpp:402
begin
JsonIterator begin(JsonValue o)
Definition: gason.h:104
WSP_URL_COUNT
@ WSP_URL_COUNT
Definition: weather_safety_proxy.h:38
INDI::Weather::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: indiweather.cpp:369
INDI::Weather::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: indiweather.cpp:176
IUSaveConfigText
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition: indicom.c:1460
JsonNode::value
JsonValue value
Definition: gason.h:89
LOGF_WARN
#define LOGF_WARN(fmt,...)
Definition: indilogger.h:81
weatherSafetyProxy
std::unique_ptr< WeatherSafetyProxy > weatherSafetyProxy(new WeatherSafetyProxy())
INDI::Weather::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: indiweather.cpp:101
IUFillSwitchVector
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidriver.c:412
IUFillNumberVector
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidriver.c:455
ISR_1OFMANY
@ ISR_1OFMANY
Definition: indiapi.h:172
WSP_SOFT_ERROR_MAX
@ WSP_SOFT_ERROR_MAX
Definition: weather_safety_proxy.h:56
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
WeatherSafetyProxy::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: weather_safety_proxy.cpp:98
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
INDI::DefaultDevice::loadConfig
virtual bool loadConfig(bool silent=false, const char *property=nullptr)
Load the last saved configuration file.
Definition: defaultdevice.cpp:147
WeatherSafetyProxy::WeatherSafetyProxy
WeatherSafetyProxy()
Definition: weather_safety_proxy.cpp:42
IUUpdateSwitch
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:171
end
JsonIterator end(JsonValue)
Definition: gason.h:108
_ITextVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:249
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
gason.h
LOG_DEBUG
#define LOG_DEBUG(txt)
Definition: indilogger.h:75
WSP_URL
@ WSP_URL
Definition: weather_safety_proxy.h:37
weather_safety_proxy.h
WSP_SAFE
@ WSP_SAFE
Definition: weather_safety_proxy.h:51
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
INDI::Weather::ISNewText
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
Definition: indiweather.cpp:228
WeatherSafetyProxy::ISGetProperties
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...
Definition: weather_safety_proxy.cpp:124
LOG_ERROR
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition: indilogger.h:72
WSP_SCRIPT_COUNT
@ WSP_SCRIPT_COUNT
Definition: weather_safety_proxy.h:54
INDI::WeatherInterface::addParameter
void addParameter(std::string name, std::string label, double numMinOk, double numMaxOk, double percWarning)
addParameter Add a physical weather measurable parameter to the weather driver. The weather value has...
Definition: indiweatherinterface.cpp:131
IUSaveText
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indicom.c:1449
WSP_USE_COUNT
@ WSP_USE_COUNT
Definition: weather_safety_proxy.h:45
INDI::DefaultDevice::ISGetProperties
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
Definition: defaultdevice.cpp:750
WeatherSafetyProxy::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: weather_safety_proxy.cpp:66
name
const char * name
Definition: indiserver.c:116
_ISwitchVectorProperty::s
IPState s
Definition: indiapi.h:382
_ITextVectorProperty::s
IPState s
Definition: indiapi.h:259
WeatherSafetyProxy
Definition: weather_safety_proxy.h:61
INDI::Weather::CONNECTION_NONE
@ CONNECTION_NONE
Definition: indiweather.h:83
IUUpdateNumber
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:225
IP_RW
@ IP_RW
Definition: indiapi.h:185
LOG_WARN
#define LOG_WARN(txt)
Definition: indilogger.h:73
JsonIterator
Definition: gason.h:94
JsonValue::toString
char * toString() const
Definition: gason.h:75
JsonValue::toNumber
double toNumber() const
Definition: gason.h:70
WeatherSafetyProxy::updateWeather
virtual IPState updateWeather() override
updateWeather Update weather conditions from device or service. The function should not change the st...
Definition: weather_safety_proxy.cpp:209
ISState
ISState
Switch state.
Definition: indiapi.h:148
WSP_USE_CURL
@ WSP_USE_CURL
Definition: weather_safety_proxy.h:44
INDI::DefaultDevice::addDebugControl
void addDebugControl()
Add Debug control to the driver.
Definition: defaultdevice.cpp:639
IUSaveConfigSwitch
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indicom.c:1465
JsonNode::key
char * key
Definition: gason.h:91
INDI::DefaultDevice::deleteProperty
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
Definition: defaultdevice.cpp:965
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
IDSetSwitch
void void void void void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing switch vector property.
errno
int errno
IUFillSwitch
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition: indidriver.c:320
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
INDI::WeatherInterface::setParameterValue
void setParameterValue(std::string name, double value)
setParameterValue Update weather parameter value
Definition: indiweatherinterface.cpp:155
ISS_ON
@ ISS_ON
Definition: indiapi.h:151