Instrument Neutral Distributed Interface INDI  2.0.2
indilightboxinterface.cpp
Go to the documentation of this file.
1 /*
2  Dust Cap Interface
3  Copyright (C) 2015 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 "indilightboxinterface.h"
22 
23 #include "indilogger.h"
24 
25 #include <cstring>
26 
27 namespace INDI
28 {
29 
31 {
32  this->device = device;
33  this->isDimmable = isDimmable;
34  FilterIntensityN = nullptr;
35  currentFilterSlot = 0;
36 }
37 
39 {
40 }
41 
42 void LightBoxInterface::initLightBoxProperties(const char *deviceName, const char *groupName)
43 {
44  // Turn on/off light
45  IUFillSwitch(&LightS[FLAT_LIGHT_ON], "FLAT_LIGHT_ON", "On", ISS_OFF);
46  IUFillSwitch(&LightS[FLAT_LIGHT_OFF], "FLAT_LIGHT_OFF", "Off", ISS_ON);
47  IUFillSwitchVector(&LightSP, LightS, 2, deviceName, "FLAT_LIGHT_CONTROL", "Flat Light", groupName, IP_RW,
48  ISR_1OFMANY, 0, IPS_IDLE);
49 
50  // Light Intensity
51  IUFillNumber(&LightIntensityN[0], "FLAT_LIGHT_INTENSITY_VALUE", "Value", "%.f", 0, 255, 10, 0);
52  IUFillNumberVector(&LightIntensityNP, LightIntensityN, 1, deviceName, "FLAT_LIGHT_INTENSITY", "Brightness",
53  groupName, IP_RW, 0, IPS_IDLE);
54 
55  // Active Devices
56  IUFillText(&ActiveDeviceT[0], "ACTIVE_FILTER", "Filter", "Filter Simulator");
57  IUFillTextVector(&ActiveDeviceTP, ActiveDeviceT, 1, deviceName, "ACTIVE_DEVICES", "Snoop devices", OPTIONS_TAB,
58  IP_RW, 60, IPS_IDLE);
59 
60  // Filter duration
61  IUFillNumberVector(&FilterIntensityNP, nullptr, 0, deviceName, "FLAT_LIGHT_FILTER_INTENSITY", "Filter Intensity",
62  "Preset", IP_RW, 60, IPS_OK);
63 
64  IDSnoopDevice(ActiveDeviceT[0].text, "FILTER_SLOT");
65  IDSnoopDevice(ActiveDeviceT[0].text, "FILTER_NAME");
66 }
67 
68 void LightBoxInterface::isGetLightBoxProperties(const char *deviceName)
69 {
70  INDI_UNUSED(deviceName);
71 
73  char errmsg[MAXRBUF];
74  IUReadConfig(nullptr, device->getDeviceName(), "ACTIVE_DEVICES", 1, errmsg);
75 }
76 
78 {
79  if (device->isConnected() == false)
80  {
81  if (FilterIntensityN)
82  {
85  free (FilterIntensityN);
86  FilterIntensityN = nullptr;
87  }
88  }
89 
90  return true;
91 }
92 
93 bool LightBoxInterface::processLightBoxSwitch(const char *dev, const char *name, ISState *states, char *names[],
94  int n)
95 {
96  if (strcmp(dev, device->getDeviceName()) == 0)
97  {
98  // Light
99  if (!strcmp(LightSP.name, name))
100  {
101  int prevIndex = IUFindOnSwitchIndex(&LightSP);
102  IUUpdateSwitch(&LightSP, states, names, n);
103  bool rc = EnableLightBox(LightS[FLAT_LIGHT_ON].s == ISS_ON ? true : false);
104 
105  LightSP.s = rc ? IPS_OK : IPS_ALERT;
106 
107  if (!rc)
108  {
110  LightS[prevIndex].s = ISS_ON;
111  }
112 
113  IDSetSwitch(&LightSP, nullptr);
114 
115  return true;
116  }
117  }
118 
119  return false;
120 }
121 
122 bool LightBoxInterface::processLightBoxNumber(const char *dev, const char *name, double values[], char *names[],
123  int n)
124 {
125  if (strcmp(dev, device->getDeviceName()) == 0)
126  {
127  // Light Intensity
128  if (!strcmp(LightIntensityNP.name, name))
129  {
130  double prevValue = LightIntensityN[0].value;
131  IUUpdateNumber(&LightIntensityNP, values, names, n);
132 
133  bool rc = SetLightBoxBrightness(LightIntensityN[0].value);
134  if (rc)
136  else
137  {
138  LightIntensityN[0].value = prevValue;
140  }
141 
142  IDSetNumber(&LightIntensityNP, nullptr);
143 
144  return true;
145  }
146 
147  if (!strcmp(FilterIntensityNP.name, name))
148  {
149  if (FilterIntensityN == nullptr)
150  {
151  for (int i = 0; i < n; i++)
152  addFilterDuration(names[i], values[i]);
153 
155 
156  return true;
157  }
158 
159  IUUpdateNumber(&FilterIntensityNP, values, names, n);
161  IDSetNumber(&FilterIntensityNP, nullptr);
162  return true;
163  }
164  }
165 
166  return false;
167 }
168 
169 bool LightBoxInterface::processLightBoxText(const char *dev, const char *name, char *texts[], char *names[],
170  int n)
171 {
172  if (strcmp(dev, device->getDeviceName()) == 0)
173  {
174  if (!strcmp(name, ActiveDeviceTP.name))
175  {
177  IUUpdateText(&ActiveDeviceTP, texts, names, n);
178  // Update client display
179  IDSetText(&ActiveDeviceTP, nullptr);
180 
181  if (strlen(ActiveDeviceT[0].text) > 0)
182  {
183  IDSnoopDevice(ActiveDeviceT[0].text, "FILTER_SLOT");
184  IDSnoopDevice(ActiveDeviceT[0].text, "FILTER_NAME");
185  }
186  // If filter removed, remove presets
187  else
188  {
191  free(FilterIntensityN);
192  FilterIntensityN = nullptr;
193  }
194  return true;
195  }
196  }
197 
198  return false;
199 }
200 
202 {
203  INDI_UNUSED(enable);
204  // Must be implemented by child class
205  return false;
206 }
207 
209 {
210  INDI_UNUSED(value);
211  // Must be implemented by child class
212  return false;
213 }
214 
216 {
217  if (isDimmable == false)
218  return false;
219 
220  XMLEle *ep = nullptr;
221  const char *propTag = tagXMLEle(root);
222  const char *propName = findXMLAttValu(root, "name");
223 
224  if (!strcmp(propTag, "delProperty"))
225  return false;
226 
227  if (!strcmp(propName, "FILTER_NAME"))
228  {
229  if (FilterIntensityN != nullptr)
230  {
231  int snoopCounter = 0;
232  bool isDifferent = false;
233  for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
234  {
235  if (snoopCounter >= FilterIntensityNP.nnp || (strcmp(FilterIntensityN[snoopCounter].label, pcdataXMLEle(ep))))
236  {
237  isDifferent = true;
238  break;
239  }
240 
241  snoopCounter++;
242  }
243 
244  if (isDifferent == false && snoopCounter != FilterIntensityNP.nnp)
245  isDifferent = true;
246 
247  // Check if we have different FILTER_NAME
248  // If identical, no need to recreate it.
249  if (isDifferent)
250  {
253  free(FilterIntensityN);
254  FilterIntensityN = nullptr;
255  }
256  else
257  return false;
258  }
259 
260  for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
261  addFilterDuration(pcdataXMLEle(ep), 0);
262 
264  char errmsg[MAXRBUF];
265  IUReadConfig(nullptr, device->getDeviceName(), "FLAT_LIGHT_FILTER_INTENSITY", 1, errmsg);
266 
267  if (device->isConnected())
268  {
269  if (currentFilterSlot < FilterIntensityNP.nnp)
270  {
271  double duration = FilterIntensityN[currentFilterSlot].value;
272  if (duration > 0)
273  SetLightBoxBrightness(duration);
274  }
275  }
276  }
277  else if (!strcmp(propName, "FILTER_SLOT"))
278  {
279  // Only accept IPS_OK/IPS_IDLE state
280  if (strcmp(findXMLAttValu(root, "state"), "Ok") && strcmp(findXMLAttValu(root, "state"), "Idle"))
281  return false;
282 
283  for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
284  {
285  const char *elemName = findXMLAttValu(ep, "name");
286 
287  if (!strcmp(elemName, "FILTER_SLOT_VALUE"))
288  {
289  currentFilterSlot = atoi(pcdataXMLEle(ep)) - 1;
290  break;
291  }
292  }
293 
294  if (FilterIntensityN && device->isConnected())
295  {
296  if (currentFilterSlot < FilterIntensityNP.nnp)
297  {
298  auto value = FilterIntensityN[currentFilterSlot].value;
299  if (value > 0)
300  {
301  if (SetLightBoxBrightness(value))
302  {
303  LightIntensityN[0].value = value;
305  IDSetNumber(&LightIntensityNP, nullptr);
306  }
307 
308  }
309  }
310  }
311  }
312 
313  return false;
314 }
315 
316 void LightBoxInterface::addFilterDuration(const char *filterName, uint16_t filterDuration)
317 {
318  if (FilterIntensityN == nullptr)
319  {
320  FilterIntensityN = (INumber *)malloc(sizeof(INumber));
321  DEBUGDEVICE(device->getDeviceName(), Logger::DBG_DEBUG, "Filter intensity preset created.");
322  }
323  else
324  {
325  // Ensure no duplicates
326  for (int i = 0; i < FilterIntensityNP.nnp; i++)
327  {
328  if (!strcmp(filterName, FilterIntensityN[i].name))
329  return;
330  }
331 
332  FilterIntensityN = (INumber *)realloc(FilterIntensityN, (FilterIntensityNP.nnp + 1) * sizeof(INumber));
333  }
334 
335  IUFillNumber(&FilterIntensityN[FilterIntensityNP.nnp], filterName, filterName, "%0.f", 0, LightIntensityN[0].max,
336  LightIntensityN[0].step, filterDuration);
337 
340 }
341 
343 {
345  if (FilterIntensityN != nullptr)
347 
348  return true;
349 }
350 }
hid_device * device
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
INumberVectorProperty LightIntensityNP
bool processLightBoxNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process light box number properties.
ISwitchVectorProperty LightSP
ITextVectorProperty ActiveDeviceTP
virtual bool EnableLightBox(bool enable)
EnableLightBox Turn on/off on a light box. Must be impelemented in the child class.
virtual bool SetLightBoxBrightness(uint16_t value)
setBrightness Set light level. Must be impelemented in the child class, if supported.
bool processLightBoxSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process light box switch properties.
void initLightBoxProperties(const char *deviceName, const char *groupNam)
Initilize light box properties. It is recommended to call this function within initProperties() of yo...
INumberVectorProperty FilterIntensityNP
bool processLightBoxText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process light box text properties.
void isGetLightBoxProperties(const char *deviceName)
isGetLightBoxProperties Get light box properties
LightBoxInterface(DefaultDevice *device, bool isDimmable)
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
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
@ IP_RW
Definition: indiapi.h:186
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
struct _INumber INumber
@ ISR_1OFMANY
Definition: indiapi.h:173
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
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indidevapi.c:128
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indidevapi.c:148
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
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indidevapi.c:15
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: indidevapi.c:158
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
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: indidevapi.c:235
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
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
int IUReadConfig(const char *filename, const char *dev, const char *property, int silent, char errmsg[])
Loads and processes a configuration file. Once a configuration file is successful loaded,...
Definition: indidriver.c:485
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:1362
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1191
#define DEBUGDEVICE(device, priority, msg)
Definition: indilogger.h:60
#define MAXRBUF
Definition: indiserver.cpp:102
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
char * tagXMLEle(XMLEle *ep)
Return the tag of an XML element.
Definition: lilxml.cpp:600
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.
One number descriptor.
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371
char name[MAXINDINAME]
Definition: indiapi.h:250