Instrument Neutral Distributed Interface INDI  1.9.5
indiweatherinterface.cpp
Go to the documentation of this file.
1 /*
2  Weather Interface
3  Copyright (C) 2018 Jasem Mutlaq (mutlaqja@ikarustech.com)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
21 #include "indiweatherinterface.h"
22 
23 #include "indilogger.h"
24 
25 #include <cstring>
26 
27 namespace INDI
28 {
29 
30 WeatherInterface::WeatherInterface(DefaultDevice *defaultDevice) : m_defaultDevice(defaultDevice)
31 {
32 }
33 
35 {
36  for (int i = 0; i < ParametersNP.nnp; i++)
37  {
38  free(ParametersN[i].aux0);
39  free(ParametersN[i].aux1);
40  free(ParametersRangeNP[i].np);
41  }
42 
43  free(ParametersN);
44  free(ParametersRangeNP);
45  free(critialParametersL);
46 }
47 
48 void WeatherInterface::initProperties(const char *statusGroup, const char *paramsGroup)
49 {
50  m_ParametersGroup = paramsGroup;
51 
52  // Parameters
53  IUFillNumberVector(&ParametersNP, nullptr, 0, m_defaultDevice->getDeviceName(), "WEATHER_PARAMETERS", "Parameters",
54  paramsGroup, IP_RO, 60, IPS_OK);
55 
56  // Weather Status
57  IUFillLightVector(&critialParametersLP, nullptr, 0, m_defaultDevice->getDeviceName(), "WEATHER_STATUS", "Status",
58  statusGroup, IPS_IDLE);
59 }
60 
62 {
63  if (m_defaultDevice->isConnected())
64  {
66  m_defaultDevice->defineProperty(&critialParametersLP);
67 
68  if (ParametersN)
69  m_defaultDevice->defineProperty(&ParametersNP);
70 
72  {
73  for (int i = 0; i < nRanges; i++)
74  m_defaultDevice->defineProperty(&ParametersRangeNP[i]);
75  }
76  }
77  else
78  {
80  m_defaultDevice->deleteProperty(critialParametersLP.name);
81 
82  if (ParametersN)
83  m_defaultDevice->deleteProperty(ParametersNP.name);
84 
86  {
87  for (int i = 0; i < nRanges; i++)
88  m_defaultDevice->deleteProperty(ParametersRangeNP[i].name);
89  }
90 
91  }
92 
93  return true;
94 }
95 
96 bool WeatherInterface::processNumber(const char *dev, const char *name, double values[], char *names[], int n)
97 {
98  INDI_UNUSED(dev);
99 
100  // Parameter ranges
101  for (int i = 0; i < nRanges; i++)
102  {
103  if (!strcmp(name, ParametersRangeNP[i].name))
104  {
105  IUUpdateNumber(&ParametersRangeNP[i], values, names, n);
106 
107  ParametersN[i].min = ParametersRangeNP[i].np[0].value;
108  ParametersN[i].max = ParametersRangeNP[i].np[1].value;
109  *(static_cast<double *>(ParametersN[i].aux0)) = ParametersRangeNP[i].np[2].value;
110 
112  IDSetLight(&critialParametersLP, nullptr);
113 
115  IDSetNumber(&ParametersRangeNP[i], nullptr);
116 
117  return true;
118  }
119  }
120 
121  return false;
122 }
123 
125 {
126  DEBUGDEVICE(m_defaultDevice->getDeviceName(), Logger::DBG_ERROR,
127  "updateWeather() must be implemented in Weather device child class to update GEOGRAPHIC_COORD properties.");
128  return IPS_ALERT;
129 }
130 
131 void WeatherInterface::addParameter(std::string name, std::string label, double numMinOk, double numMaxOk,
132  double percWarning)
133 {
134  DEBUGFDEVICE(m_defaultDevice->getDeviceName(), Logger::DBG_DEBUG, "Parameter %s is added. Ok (%g,%g,%g) ", name.c_str(),
135  numMinOk,
136  numMaxOk, percWarning);
137 
138  ParametersN = (ParametersN == nullptr) ? static_cast<INumber *>(malloc(sizeof(INumber))) :
139  static_cast<INumber *>(realloc(ParametersN, (ParametersNP.nnp + 1) * sizeof(INumber)));
140 
141  double *warn = static_cast<double *>(malloc(sizeof(double)));
142 
143  *warn = percWarning;
144 
145  IUFillNumber(&ParametersN[ParametersNP.nnp], name.c_str(), label.c_str(), "%4.2f", numMinOk, numMaxOk, 0, 0);
146 
147  ParametersN[ParametersNP.nnp].aux0 = warn;
148 
150  ParametersNP.nnp++;
151 
152  createParameterRange(name, label);
153 }
154 
155 void WeatherInterface::setParameterValue(std::string name, double value)
156 {
157  for (int i = 0; i < ParametersNP.nnp; i++)
158  {
159  if (!strcmp(ParametersN[i].name, name.c_str()))
160  {
161  ParametersN[i].value = value;
162  return;
163  }
164  }
165 }
166 
168 {
169  for (int i = 0; i < ParametersNP.nnp; i++)
170  {
171  if (!strcmp(ParametersN[i].name, param.c_str()))
172  {
174  (critialParametersL == nullptr) ?
175  static_cast<ILight *>(malloc(sizeof(ILight))) :
176  static_cast<ILight *>(realloc(critialParametersL, (critialParametersLP.nlp + 1) * sizeof(ILight)));
177 
179 
181 
183 
184  return true;
185  }
186  }
187 
188  DEBUGFDEVICE(m_defaultDevice->getDeviceName(), Logger::DBG_WARNING,
189  "Unable to find parameter %s in list of existing parameters!", param.c_str());
190  return false;
191 }
192 
194 {
195  double warn = *(static_cast<double *>(parameter.aux0));
196  double rangeWarn = (parameter.max - parameter.min) * (warn / 100);
197 
198  if ((parameter.value < parameter.min) || (parameter.value > parameter.max))
199  {
200  return IPS_ALERT;
201  }
202  //else if (parameter.value < (parameter.min + rangeWarn) || parameter.value > (parameter.max - rangeWarn))
203  // FIXME This is a hack to prevent warnings parameters which minimum values are zero (e.g. Wind)
204  else if ( ((parameter.value < (parameter.min + rangeWarn)) && parameter.min != 0)
205  || ((parameter.value > (parameter.max - rangeWarn)) && parameter.max != 0))
206  {
207  return IPS_BUSY;
208  }
209  else
210  {
211  return IPS_OK;
212  }
213 
214  return IPS_IDLE;
215 }
216 
217 IPState WeatherInterface::checkParameterState(const std::string &param) const
218 {
219  for (int i = 0; i < ParametersNP.nnp; i++)
220  {
221  if (!strcmp(ParametersN[i].name, param.c_str()))
222  {
223  return checkParameterState(ParametersN[i]);
224  }
225  }
226 
227  return IPS_IDLE;
228 }
229 
231 {
232  if (critialParametersL == nullptr)
233  return false;
234 
235  std::vector<IPState> preStates(critialParametersLP.nlp);
236  for (int i = 0; i < critialParametersLP.nlp; i++)
237  preStates[i] = critialParametersL[i].s;
238 
240 
241  for (int i = 0; i < critialParametersLP.nlp; i++)
242  {
243  for (int j = 0; j < ParametersNP.nnp; j++)
244  {
245  if (!strcmp(critialParametersL[i].name, ParametersN[j].name))
246  {
248  switch (state)
249  {
250  case IPS_BUSY:
252  DEBUGFDEVICE(m_defaultDevice->getDeviceName(), Logger::DBG_WARNING,
253  "Warning: Parameter %s value (%g) is in the warning zone!",
254  ParametersN[j].label, ParametersN[j].value);
255  break;
256 
257  case IPS_ALERT:
259  DEBUGFDEVICE(m_defaultDevice->getDeviceName(), Logger::DBG_WARNING,
260  "Caution: Parameter %s value (%g) is in the danger zone!",
261  ParametersN[j].label, ParametersN[j].value);
262  break;
263 
264  case IPS_IDLE:
265  case IPS_OK:
266  critialParametersL[i].s = IPS_OK;
267  }
268  }
269  }
270 
271  // The overall state is the worst individual state.
274  }
275 
276  // if Any state changed, return true.
277  for (int i = 0; i < critialParametersLP.nlp; i++)
278  {
279  if (preStates[i] != critialParametersL[i].s)
280  return true;
281  }
282 
283  return false;
284 }
285 
286 void WeatherInterface::createParameterRange(std::string name, std::string label)
287 {
289  (ParametersRangeNP == nullptr) ?
290  static_cast<INumberVectorProperty *>(malloc(sizeof(INumberVectorProperty))) :
291  static_cast<INumberVectorProperty *>(realloc(ParametersRangeNP, (nRanges + 1) * sizeof(INumberVectorProperty)));
292 
293  INumber *rangesN = static_cast<INumber *>(malloc(sizeof(INumber) * 3));
294 
295  IUFillNumber(&rangesN[0], "MIN_OK", "OK range min", "%4.2f", -1e6, 1e6, 0, ParametersN[nRanges].min);
296  IUFillNumber(&rangesN[1], "MAX_OK", "OK range max", "%4.2f", -1e6, 1e6, 0, ParametersN[nRanges].max);
297  IUFillNumber(&rangesN[2], "PERC_WARN", "% for Warning", "%g", 0, 100, 1,
298  *(static_cast<double *>(ParametersN[nRanges].aux0)));
299 
300  char propName[MAXINDINAME];
301  char propLabel[MAXINDILABEL];
302  snprintf(propName, MAXINDINAME, "%s", name.c_str());
303  snprintf(propLabel, MAXINDILABEL, "%s", label.c_str());
304 
305  IUFillNumberVector(&ParametersRangeNP[nRanges], rangesN, 3, m_defaultDevice->getDeviceName(), propName, propLabel,
306  m_ParametersGroup.c_str(),
307  IP_RW, 60, IPS_IDLE);
308 
309  nRanges++;
310 }
311 
313 {
314  for (int i = 0; i < nRanges; i++)
316  return true;
317 }
318 
319 
320 }
IP_RO
@ IP_RO
Definition: indiapi.h:183
INDI::WeatherInterface::initProperties
void initProperties(const char *statusGroup, const char *paramsGroup)
Initilize focuser properties. It is recommended to call this function within initProperties() of your...
Definition: indiweatherinterface.cpp:48
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
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
INDI::WeatherInterface::critialParametersL
ILight * critialParametersL
Definition: indiweatherinterface.h:157
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
min
double min(void)
INDI::Logger::DBG_WARNING
@ DBG_WARNING
Definition: indilogger.h:193
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
INumber
One number descriptor.
_INumberVectorProperty::nnp
int nnp
Definition: indiapi.h:336
MAXINDINAME
#define MAXINDINAME
Definition: indiapi.h:190
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
INDI::Logger::DBG_ERROR
@ DBG_ERROR
Definition: indilogger.h:192
INDI::WeatherInterface::syncCriticalParameters
bool syncCriticalParameters()
updateWeatherState Send update weather state to client
Definition: indiweatherinterface.cpp:230
INDI_UNUSED
#define INDI_UNUSED(x)
Definition: indidevapi.h:799
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
_ILightVectorProperty::s
IPState s
Definition: indiapi.h:426
IUFillLight
void IUFillLight(ILight *lp, const char *name, const char *label, IPState s)
Assign attributes for a light property. The light's auxiliary elements will be set to NULL.
Definition: indidriver.c:334
IUSaveConfigNumber
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indicom.c:1455
_ILightVectorProperty::nlp
int nlp
Definition: indiapi.h:430
DEBUGDEVICE
#define DEBUGDEVICE(device, priority, msg)
Definition: indilogger.h:60
INDI::WeatherInterface::ParametersNP
INumberVectorProperty ParametersNP
Definition: indiweatherinterface.h:150
max
double max(void)
_ILightVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:420
INDI::Logger::DBG_DEBUG
@ DBG_DEBUG
Definition: indilogger.h:195
indilogger.h
ILight
One light descriptor.
_INumberVectorProperty
Number vector property descriptor.
Definition: indiapi.h:317
IDSetLight
void void void void void void void IDSetLight(const ILightVectorProperty *l, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing light vector property.
INDI::WeatherInterface::nRanges
uint8_t nRanges
Definition: indiweatherinterface.h:154
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
IPS_BUSY
@ IPS_BUSY
Definition: indiapi.h:162
INDI::WeatherInterface::critialParametersLP
ILightVectorProperty critialParametersLP
Definition: indiweatherinterface.h:158
_INumberVectorProperty::np
INumber * np
Definition: indiapi.h:334
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
INDI::WeatherInterface::saveConfigItems
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save parameters ranges in the config file.
Definition: indiweatherinterface.cpp:312
INDI::WeatherInterface::processNumber
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
Definition: indiweatherinterface.cpp:96
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
INDI::WeatherInterface::checkParameterState
IPState checkParameterState(const std::string &param) const
checkParameterState Checks the given parameter against the defined bounds
Definition: indiweatherinterface.cpp:217
name
const char * name
Definition: indiserver.c:116
INDI::WeatherInterface::WeatherInterface
WeatherInterface(DefaultDevice *defaultDevice)
Definition: indiweatherinterface.cpp:30
DEBUGFDEVICE
#define DEBUGFDEVICE(device, priority, msg,...)
Definition: indilogger.h:61
indiweatherinterface.h
INDI::WeatherInterface::~WeatherInterface
virtual ~WeatherInterface()
Definition: indiweatherinterface.cpp:34
INDI
Namespace to encapsulate INDI client, drivers, and mediator classes.
Definition: AlignmentSubsystemForClients.cpp:11
_ILightVectorProperty::lp
ILight * lp
Definition: indiapi.h:428
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
MAXINDILABEL
#define MAXINDILABEL
Definition: indiapi.h:191
INDI::DefaultDevice
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
Definition: defaultdevice.h:118
INDI::WeatherInterface::ParametersN
INumber * ParametersN
Definition: indiweatherinterface.h:149
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
IUFillLightVector
void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char *dev, const char *name, const char *label, const char *group, IPState s)
Assign attributes for a light vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidriver.c:435
INDI::WeatherInterface::ParametersRangeNP
INumberVectorProperty * ParametersRangeNP
Definition: indiweatherinterface.h:153
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
INDI::WeatherInterface::updateProperties
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
Definition: indiweatherinterface.cpp:61
INDI::WeatherInterface::updateWeather
virtual IPState updateWeather()
updateWeather Update weather conditions from device or service. The function should not change the st...
Definition: indiweatherinterface.cpp:124
INDI::WeatherInterface::setParameterValue
void setParameterValue(std::string name, double value)
setParameterValue Update weather parameter value
Definition: indiweatherinterface.cpp:155