Instrument Neutral Distributed Interface INDI  2.0.2
indiweather.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2015 Jasem Mutlaq. All rights reserved.
3 
4  INDI Weather Device Class
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 "indiweather.h"
26 
29 
30 #include <cstring>
31 
32 #define PARAMETERS_TAB "Parameters"
33 
34 namespace INDI
35 {
36 
38 {
39 }
40 
42 {
45 
46  // Location
47  IUFillNumber(&LocationN[LOCATION_LATITUDE], "LAT", "Lat (dd:mm:ss)", "%010.6m", -90, 90, 0, 0.0);
48  IUFillNumber(&LocationN[LOCATION_LONGITUDE], "LONG", "Lon (dd:mm:ss)", "%010.6m", 0, 360, 0, 0.0);
49  IUFillNumber(&LocationN[LOCATION_ELEVATION], "ELEV", "Elevation (m)", "%g", -200, 10000, 0, 0);
50  IUFillNumberVector(&LocationNP, LocationN, 3, getDeviceName(), "GEOGRAPHIC_COORD", "Location", SITE_TAB, IP_RW, 60,
51  IPS_OK);
52 
53  // Active Devices
54  IUFillText(&ActiveDeviceT[0], "ACTIVE_GPS", "GPS", "GPS Simulator");
55  IUFillTextVector(&ActiveDeviceTP, ActiveDeviceT, 1, getDeviceName(), "ACTIVE_DEVICES", "Snoop devices", OPTIONS_TAB,
56  IP_RW, 60, IPS_IDLE);
57 
58  IDSnoopDevice(ActiveDeviceT[0].text, "GEOGRAPHIC_COORD");
59 
60  if (weatherConnection & CONNECTION_SERIAL)
61  {
64  {
65  return callHandshake();
66  });
68  }
69 
70  if (weatherConnection & CONNECTION_TCP)
71  {
72  tcpConnection = new Connection::TCP(this);
74  {
75  return callHandshake();
76  });
78  }
79 
81 
82  return true;
83 }
84 
86 {
88 
89  if (isConnected())
90  {
92 
95 
96  DEBUG(Logger::DBG_SESSION, "Weather update is in progress...");
97  }
98  else
99  {
101 
104  }
105 
106  return true;
107 }
108 
109 bool Weather::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
110 {
111  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
112  {
113  if (processSwitch(dev, name, states, names, n))
114  return true;
115  }
116 
117  return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
118 }
119 
120 bool Weather::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
121 {
122  // first check if it's for our device
123  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
124  {
125  if (strcmp(name, "GEOGRAPHIC_COORD") == 0)
126  {
127  int latindex = IUFindIndex("LAT", names, n);
128  int longindex = IUFindIndex("LONG", names, n);
129  int elevationindex = IUFindIndex("ELEV", names, n);
130 
131  if (latindex == -1 || longindex == -1 || elevationindex == -1)
132  {
134  IDSetNumber(&LocationNP, "Location data missing or corrupted.");
135  }
136 
137  double targetLat = values[latindex];
138  double targetLong = values[longindex];
139  double targetElev = values[elevationindex];
140 
141  return processLocationInfo(targetLat, targetLong, targetElev);
142  }
143 
144  // Pass to weather interface
145  if (processNumber(dev, name, values, names, n))
146  return true;
147  }
148 
149  return DefaultDevice::ISNewNumber(dev, name, values, names, n);
150 }
151 
152 bool INDI::Weather::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
153 {
154  // first check if it's for our device
155  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
156  {
157  if (!strcmp(name, ActiveDeviceTP.name))
158  {
159  ActiveDeviceTP.s = IPS_OK;
160  IUUpdateText(&ActiveDeviceTP, texts, names, n);
161  // Update client display
162  IDSetText(&ActiveDeviceTP, nullptr);
163 
164  IDSnoopDevice(ActiveDeviceT[0].text, "GEOGRAPHIC_COORD");
165  return true;
166  }
167  }
168  return DefaultDevice::ISNewText(dev, name, texts, names, n);
169 }
170 
172 {
173  XMLEle *ep = nullptr;
174  const char *propName = findXMLAttValu(root, "name");
175 
176  if (isConnected())
177  {
178  if (!strcmp(propName, "GEOGRAPHIC_COORD"))
179  {
180  // Only accept IPS_OK state
181  if (strcmp(findXMLAttValu(root, "state"), "Ok"))
182  return false;
183 
184  double longitude = -1, latitude = -1, elevation = -1;
185 
186  for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
187  {
188  const char *elemName = findXMLAttValu(ep, "name");
189 
190  if (!strcmp(elemName, "LAT"))
191  latitude = atof(pcdataXMLEle(ep));
192  else if (!strcmp(elemName, "LONG"))
193  longitude = atof(pcdataXMLEle(ep));
194  else if (!strcmp(elemName, "ELEV"))
195  elevation = atof(pcdataXMLEle(ep));
196  }
197 
198  return processLocationInfo(latitude, longitude, elevation);
199  }
200  }
201 
202  return DefaultDevice::ISSnoopDevice(root);
203 }
204 
205 bool Weather::updateLocation(double latitude, double longitude, double elevation)
206 {
207  INDI_UNUSED(latitude);
208  INDI_UNUSED(longitude);
209  INDI_UNUSED(elevation);
210 
211  return true;
212 }
213 
214 bool Weather::processLocationInfo(double latitude, double longitude, double elevation)
215 {
216  // Do not update if not necessary
217  if (latitude == LocationN[LOCATION_LATITUDE].value && longitude == LocationN[LOCATION_LONGITUDE].value &&
218  elevation == LocationN[LOCATION_ELEVATION].value)
219  {
220  LocationNP.s = IPS_OK;
221  IDSetNumber(&LocationNP, nullptr);
222  }
223 
224  if (updateLocation(latitude, longitude, elevation))
225  {
226  LocationNP.s = IPS_OK;
227  LocationN[LOCATION_LATITUDE].value = latitude;
228  LocationN[LOCATION_LONGITUDE].value = longitude;
229  LocationN[LOCATION_ELEVATION].value = elevation;
230  // Update client display
231  IDSetNumber(&LocationNP, nullptr);
232 
233  return true;
234  }
235  else
236  {
238  // Update client display
239  IDSetNumber(&LocationNP, nullptr);
240  return false;
241  }
242 }
243 
244 
246 {
251  return true;
252 }
253 
255 {
256  return false;
257 }
258 
259 bool Weather::callHandshake()
260 {
261  if (weatherConnection > 0)
262  {
265  else if (getActiveConnection() == tcpConnection)
267  }
268 
269  return Handshake();
270 }
271 
273 {
274  return weatherConnection;
275 }
276 
277 void Weather::setWeatherConnection(const uint8_t &value)
278 {
280 
281  if (value == 0 || (mask & value) == 0)
282  {
283  DEBUGF(Logger::DBG_ERROR, "Invalid connection mode %d", value);
284  return;
285  }
286 
287  weatherConnection = value;
288 }
289 }
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the intial connection to the device...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
The TCP class manages connection with devices over the network via TCP/IP. Upon successfull connectio...
Definition: connectiontcp.h:38
int getPortFD() const
Definition: connectiontcp.h:84
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
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()
Initilize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
Connection::Interface * getActiveConnection()
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
Provides interface to implement weather reporting functionality.
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process weather switch properties.
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process weather number properties.
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save parameters ranges in the config file.
void initProperties(const char *statusGroup, const char *paramsGroup)
Initilize focuser properties. It is recommended to call this function within initProperties() of your...
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
ITextVectorProperty ActiveDeviceTP
Definition: indiweather.h:130
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: indiweather.cpp:85
IText ActiveDeviceT[1]
Definition: indiweather.h:131
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
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 Handshake()
perform handshake with device to check communication
INumberVectorProperty LocationNP
Definition: indiweather.h:126
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...
INumber LocationN[3]
Definition: indiweather.h:127
virtual bool updateLocation(double latitude, double longitude, double elevation)
Update weather station location.
uint8_t getWeatherConnection() const
virtual bool ISSnoopDevice(XMLEle *root) override
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
Connection::Serial * serialConnection
Definition: indiweather.h:133
Connection::TCP * tcpConnection
Definition: indiweather.h:134
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indiweather.cpp:41
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * SITE_TAB
SITE_TAB Where all site information setting are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
ISState
Switch state.
Definition: indiapi.h:150
@ IP_RW
Definition: indiapi.h:186
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
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: indidevapi.c:272
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: indidevapi.c:291
int IUFindIndex(const char *needle, char **hay, unsigned int n)
Returns the index of the string in a string array.
Definition: indidevapi.c:117
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indidevapi.c:15
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: indidevapi.c:198
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: indidevapi.c:180
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition: indidevapi.c:20
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:1396
void IDSnoopDevice(const char *snooped_device, const char *snooped_property)
Function a Driver calls to snoop on another Device. Snooped messages will then arrive via ISSnoopDevi...
Definition: indidriver.c:143
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1191
#define DEBUG(priority, msg)
Macro to print log messages. Example of usage of the Logger: DEBUG(DBG_DEBUG, "hello " << "world");.
Definition: indilogger.h:56
#define DEBUGF(priority, msg,...)
Definition: indilogger.h:57
#define PARAMETERS_TAB
Definition: indiweather.cpp:32
const char * findXMLAttValu(XMLEle *ep, const char *name)
Find an XML element's attribute value.
Definition: lilxml.cpp:644
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
Definition: lilxml.cpp:606
XMLEle * nextXMLEle(XMLEle *ep, int init)
Iterate an XML element for a list of nesetd XML elements.
Definition: lilxml.cpp:555
Namespace to encapsulate INDI client, drivers, and mediator classes.
const char * getDeviceName()
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:250