Instrument Neutral Distributed Interface INDI 2.2.5
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
34namespace INDI
35{
36
38{
39}
40
42{
45
46 // Location
47 LocationNP[LOCATION_LATITUDE].fill("LAT", "Lat (dd:mm:ss)", "%010.6m", -90, 90, 0, 0.0);
48 LocationNP[LOCATION_LONGITUDE].fill("LONG", "Lon (dd:mm:ss)", "%010.6m", 0, 360, 0, 0.0);
49 LocationNP[LOCATION_ELEVATION].fill("ELEV", "Elevation (m)", "%g", -200, 10000, 0, 0);
50 LocationNP.fill(getDeviceName(), "GEOGRAPHIC_COORD", "Location", SITE_TAB, IP_RW, 60, IPS_OK);
52
53 // Active Devices
54 ActiveDeviceTP[0].fill("ACTIVE_GPS", "GPS", "GPS Simulator");
55 ActiveDeviceTP.fill(getDeviceName(), "ACTIVE_DEVICES", "Snoop devices", OPTIONS_TAB, IP_RW, 60, IPS_IDLE);
57
58 IDSnoopDevice(ActiveDeviceTP[0].getText(), "GEOGRAPHIC_COORD");
59
60 if (weatherConnection & CONNECTION_SERIAL)
61 {
64 {
65 return callHandshake();
66 });
68 }
69
70 if (weatherConnection & CONNECTION_TCP)
71 {
74 {
75 return callHandshake();
76 });
78 }
79
81
82 return true;
83}
84
90
92{
94
95 if (isConnected())
96 {
98
100 DEBUG(Logger::DBG_SESSION, "Weather update is in progress...");
101 }
102 else
103 {
106 }
107
108 return true;
109}
110
111bool Weather::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
112{
113 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
114 {
115 if (processSwitch(dev, name, states, names, n))
116 return true;
117 }
118
119 return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
120}
121
122bool Weather::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
123{
124 // first check if it's for our device
125 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
126 {
127 if (LocationNP.isNameMatch(name))
128 {
129 int latindex = IUFindIndex("LAT", names, n);
130 int longindex = IUFindIndex("LONG", names, n);
131 int elevationindex = IUFindIndex("ELEV", names, n);
132
133 if (latindex == -1 || longindex == -1 || elevationindex == -1)
134 {
136 LocationNP.apply("Location data missing or corrupted.");
137 return true;
138 }
139
140 double targetLat = values[latindex];
141 double targetLong = values[longindex];
142 double targetElev = values[elevationindex];
143 processLocationInfo(targetLat, targetLong, targetElev);
144 return true;
145 }
146
147 // Pass to weather interface
148 if (processNumber(dev, name, values, names, n))
149 return true;
150 }
151
152 return DefaultDevice::ISNewNumber(dev, name, values, names, n);
153}
154
155bool INDI::Weather::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
156{
157 // first check if it's for our device
158 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
159 {
160 if (ActiveDeviceTP.isNameMatch(name))
161 {
162 ActiveDeviceTP.setState(IPS_OK);
163 ActiveDeviceTP.update(texts, names, n);
164 // Update client display
165 ActiveDeviceTP.apply();
166 IDSnoopDevice(ActiveDeviceTP[0].getText(), "GEOGRAPHIC_COORD");
167 saveConfig(ActiveDeviceTP);
168 return true;
169 }
170 }
171 return DefaultDevice::ISNewText(dev, name, texts, names, n);
172}
173
175{
176 XMLEle *ep = nullptr;
177 const char *propName = findXMLAttValu(root, "name");
178
179 if (isConnected())
180 {
181 if (!strcmp(propName, "GEOGRAPHIC_COORD"))
182 {
183 // Only accept IPS_OK state
184 if (strcmp(findXMLAttValu(root, "state"), "Ok"))
185 return false;
186
187 double longitude = -1, latitude = -1, elevation = -1;
188
189 for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
190 {
191 const char *elemName = findXMLAttValu(ep, "name");
192
193 if (!strcmp(elemName, "LAT"))
194 latitude = atof(pcdataXMLEle(ep));
195 else if (!strcmp(elemName, "LONG"))
196 longitude = atof(pcdataXMLEle(ep));
197 else if (!strcmp(elemName, "ELEV"))
198 elevation = atof(pcdataXMLEle(ep));
199 }
200
201 processLocationInfo(latitude, longitude, elevation);
202 return true;
203 }
204 }
205
206 return DefaultDevice::ISSnoopDevice(root);
207}
208
209bool Weather::updateLocation(double latitude, double longitude, double elevation)
210{
211 INDI_UNUSED(latitude);
212 INDI_UNUSED(longitude);
213 INDI_UNUSED(elevation);
214 return true;
215}
216
217void Weather::processLocationInfo(double latitude, double longitude, double elevation)
218{
219 // Do not update if not necessary
220 if (latitude == LocationNP[LOCATION_LATITUDE].getValue() && longitude == LocationNP[LOCATION_LONGITUDE].getValue() &&
221 elevation == LocationNP[LOCATION_ELEVATION].getValue())
222 {
225 return;
226 }
227
228 if (updateLocation(latitude, longitude, elevation))
229 {
231 LocationNP[LOCATION_LATITUDE].setValue(latitude);
232 LocationNP[LOCATION_LONGITUDE].setValue(longitude);
233 LocationNP[LOCATION_ELEVATION].setValue(elevation);
235 }
236 else
238
240}
241
242
244{
248 LocationNP.save(fp);
249 return true;
250}
251
253{
254 return false;
255}
256
257bool Weather::callHandshake()
258{
259 if (weatherConnection > 0)
260 {
265 }
266
267 return Handshake();
268}
269
271{
272 return weatherConnection;
273}
274
275void Weather::setWeatherConnection(const uint8_t &value)
276{
278
279 if (value == 0 || (mask & value) == 0)
280 {
281 DEBUGF(Logger::DBG_ERROR, "Invalid connection mode %d", value);
282 return;
283 }
284
285 weatherConnection = value;
286}
287}
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the initial connection to the devic...
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 successful connection...
int getPortFD() const
bool isConnected() const
const char * getDeviceName() const
INDI::PropertyText getText(const char *name) 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.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
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.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
Connection::Interface * getActiveConnection()
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
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, IPerm permission, double timeout, IPState state)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
Provides interface to implement weather reporting and safety monitoring 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)
Initialize focuser properties. It is recommended to call this function within initProperties() of you...
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
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 Handshake()
perform handshake with device to check communication
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
INDI::PropertyNumber LocationNP
void setWeatherConnection(const uint8_t &value)
setWeatherConnection Set Weather connection mode. Child class should call this in the constructor bef...
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
Connection::TCP * tcpConnection
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
INDI::PropertyText ActiveDeviceTP
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:148
@ IP_RW
Definition indiapi.h:184
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
int IUFindIndex(const char *needle, char **hay, unsigned int n)
Returns the index of the string in a string array.
Definition indidevapi.c:326
#define INDI_UNUSED(x)
Definition indidevapi.h:132
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
#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
#define getDeviceName
const char * findXMLAttValu(XMLEle *ep, const char *name)
Find an XML element's attribute value.
Definition lilxml.cpp:644
XMLEle * nextXMLEle(XMLEle *ep, int init)
Iterate an XML element for a list of nesetd XML elements.
Definition lilxml.cpp:555
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
Definition lilxml.cpp:606
Namespace to encapsulate INDI client, drivers, and mediator classes.