Instrument Neutral Distributed Interface INDI 2.2.5
indilightboxinterface.cpp
Go to the documentation of this file.
1/*
2 Dust Cap Interface
3 Copyright (C) 2015 Jasem Mutlaq ([email protected])
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
22
23#include "indilogger.h"
24
25#include <cstring>
26
27namespace INDI
28{
29
36
43
47void LightBoxInterface::initProperties(const char *group, uint32_t capabilities)
48{
49 m_Capabilities = capabilities;
50 // Turn on/off light
51 // @INDI_STANDARD_PROPERTY@
52 LightSP[FLAT_LIGHT_ON].fill("FLAT_LIGHT_ON", "On", ISS_OFF);
53 LightSP[FLAT_LIGHT_OFF].fill("FLAT_LIGHT_OFF", "Off", ISS_ON);
54 LightSP.fill(m_DefaultDevice->getDeviceName(), "FLAT_LIGHT_CONTROL", "Flat Light", group, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
55
56 // Light Intensity
57 // @INDI_STANDARD_PROPERTY@
58 LightIntensityNP[0].fill("FLAT_LIGHT_INTENSITY_VALUE", "Value", "%.f", 0, 255, 10, 0);
59 LightIntensityNP.fill(m_DefaultDevice->getDeviceName(), "FLAT_LIGHT_INTENSITY", "Brightness", group, IP_RW, 0, IPS_IDLE);
60
61 // Active Devices
62 ActiveDeviceTP[0].fill("ACTIVE_FILTER", "Filter", "Filter Simulator");
63 ActiveDeviceTP.fill(m_DefaultDevice->getDeviceName(), "ACTIVE_DEVICES", "Snoop devices", OPTIONS_TAB, IP_RW, 60, IPS_IDLE);
65
66 // Filter Intensities
67 // @INDI_STANDARD_PROPERTY@
68 FilterIntensityNP.fill(m_DefaultDevice->getDeviceName(), "FLAT_LIGHT_FILTER_INTENSITY", "Filter Intensity", "Preset", IP_RW,
69 60, IPS_IDLE);
70
71 IDSnoopDevice(ActiveDeviceTP[0].getText(), "FILTER_SLOT");
72 IDSnoopDevice(ActiveDeviceTP[0].getText(), "FILTER_NAME");
73}
74
78void LightBoxInterface::ISGetProperties(const char *deviceName)
79{
80 INDI_UNUSED(deviceName);
81 m_DefaultDevice->defineProperty(ActiveDeviceTP);
82}
83
88{
89 if (m_DefaultDevice->isConnected())
90 {
91 m_DefaultDevice->defineProperty(LightSP);
92 if (m_Capabilities & CAN_DIM)
93 m_DefaultDevice->defineProperty(LightIntensityNP);
95 m_DefaultDevice->defineProperty(FilterIntensityNP);
96 }
97 else
98 {
99 m_DefaultDevice->deleteProperty(LightSP);
100 if (m_Capabilities & CAN_DIM)
101 m_DefaultDevice->deleteProperty(LightIntensityNP);
102
104 m_DefaultDevice->deleteProperty(FilterIntensityNP);
105 }
106
107 return true;
108}
109
113bool LightBoxInterface::processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
114{
115 if (strcmp(dev, m_DefaultDevice->getDeviceName()))
116 return false;
117
118 // Light
119 if (LightSP.isNameMatch(name))
120 {
121 auto prevIndex = LightSP.findOnSwitchIndex();
122 LightSP.update(states, names, n);
123 auto rc = EnableLightBox(LightSP[FLAT_LIGHT_ON].getState() == ISS_ON ? true : false);
125
126 if (!rc)
127 {
128 LightSP.reset();
129 LightSP[prevIndex].setState(ISS_ON);
130 }
131
132 LightSP.apply();
133 return true;
134 }
135
136 return false;
137}
138
142bool LightBoxInterface::processNumber(const char *dev, const char *name, double values[], char *names[], int n)
143{
144 if (strcmp(dev, m_DefaultDevice->getDeviceName()))
145 return false;
146
147 // Light Intensity
149 {
150 auto prevValue = LightIntensityNP[0].getValue();
151 LightIntensityNP.update(values, names, n);
152
153 bool rc = SetLightBoxBrightness(LightIntensityNP[0].getValue());
154 if (rc)
156 else
157 {
158 LightIntensityNP[0].setValue(prevValue);
160 }
161
163 // If we have no filters, then save config
165 m_DefaultDevice->saveConfig(LightIntensityNP);
166 return true;
167 }
168
170 {
171 // If this is first time, we add the filters
173 {
174 for (int i = 0; i < n; i++)
175 addFilterDuration(names[i], values[i]);
176
177 m_DefaultDevice->defineProperty(FilterIntensityNP);
178 return true;
179 }
180
181 FilterIntensityNP.update(values, names, n);
184 m_DefaultDevice->saveConfig(FilterIntensityNP);
185 return true;
186 }
187
188 return false;
189}
190
194bool LightBoxInterface::processText(const char *dev, const char *name, char *texts[], char *names[], int n)
195{
196 if (strcmp(dev, m_DefaultDevice->getDeviceName()))
197 return false;
198
199 if (ActiveDeviceTP.isNameMatch(name))
200 {
202 ActiveDeviceTP.update(texts, names, n);
203 // Update client display
205 m_DefaultDevice->saveConfig(ActiveDeviceTP);
206
207 if (!ActiveDeviceTP[0].isEmpty())
208 {
209 IDSnoopDevice(ActiveDeviceTP[0].getText(), "FILTER_SLOT");
210 IDSnoopDevice(ActiveDeviceTP[0].getText(), "FILTER_NAME");
211 }
212 // If filter removed, remove presets
213 else
214 {
215 m_DefaultDevice->deleteProperty(FilterIntensityNP);
216 }
217 return true;
218 }
219
220
221 return false;
222}
223
228{
229 INDI_UNUSED(enable);
230 // Must be implemented by child class
231 return false;
232}
233
238{
239 INDI_UNUSED(value);
240 // Must be implemented by child class
241 return false;
242}
243
248{
249 auto deviceName = findXMLAttValu(root, "device");
250
251 // If dimming not supported or not our device, we return
252 if (!(m_Capabilities & CAN_DIM) || strcmp(ActiveDeviceTP[0].getText(), deviceName))
253 return false;
254
255 XMLEle *ep = nullptr;
256 auto propTag = tagXMLEle(root);
257 auto propName = findXMLAttValu(root, "name");
258
259 if (!strcmp(propTag, "delProperty"))
260 return false;
261
262 if (!strcmp(propName, "FILTER_NAME"))
263 {
265 {
266 uint32_t snoopCounter = 0;
267 bool isDifferent = false;
268 for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
269 {
270 // If either count or labels are different, then mark it as such
271 if (snoopCounter >= FilterIntensityNP.count() || !FilterIntensityNP[snoopCounter].isLabelMatch(pcdataXMLEle(ep)))
272 {
273 isDifferent = true;
274 break;
275 }
276
277 snoopCounter++;
278 }
279
280 if (isDifferent == false && snoopCounter != FilterIntensityNP.count())
281 isDifferent = true;
282
283 // Check if we have different FILTER_NAME
284 // If identical, no need to recreate it.
285 if (isDifferent)
286 {
287 m_DefaultDevice->deleteProperty(FilterIntensityNP);
289 }
290 else
291 return false;
292 }
293
294 for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
295 addFilterDuration(pcdataXMLEle(ep), 0);
296
298 m_DefaultDevice->defineProperty(FilterIntensityNP);
299
300 if (m_DefaultDevice->isConnected())
301 {
302 if (currentFilterSlot < FilterIntensityNP.count())
303 {
304 auto duration = FilterIntensityNP[currentFilterSlot].getValue();
305 if (duration > 0)
306 SetLightBoxBrightness(duration);
307 }
308 }
309 }
310 else if (!strcmp(propName, "FILTER_SLOT"))
311 {
312 // Only accept IPS_OK/IPS_IDLE state
313 if (strcmp(findXMLAttValu(root, "state"), "Ok") && strcmp(findXMLAttValu(root, "state"), "Idle"))
314 return false;
315
316 for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
317 {
318 const char *elemName = findXMLAttValu(ep, "name");
319
320 if (!strcmp(elemName, "FILTER_SLOT_VALUE"))
321 {
322 currentFilterSlot = atoi(pcdataXMLEle(ep)) - 1;
323 break;
324 }
325 }
326
327 if (!FilterIntensityNP.isEmpty() && m_DefaultDevice->isConnected())
328 {
329 if (currentFilterSlot < FilterIntensityNP.count())
330 {
331 auto value = FilterIntensityNP[currentFilterSlot].getValue();
332 if (value > 0)
333 {
334 if (SetLightBoxBrightness(value))
335 {
336 LightIntensityNP[0].setValue(value);
339 }
340 }
341 }
342 }
343 }
344
345 return false;
346}
347
351void LightBoxInterface::addFilterDuration(const char *filterName, uint16_t filterDuration)
352{
353 // Ensure no duplicates
354 for (uint32_t i = 0; i < FilterIntensityNP.count(); i++)
355 {
356 if (FilterIntensityNP[i].isNameMatch(filterName))
357 return;
358 }
359
360 INDI::WidgetNumber element;
361 element.fill(filterName, filterName, "%0.f", 0, LightIntensityNP[0].getMax(), LightIntensityNP[0].getStep(),
362 filterDuration);
363 FilterIntensityNP.push(std::move(element));
364}
365
370{
372 // N.B. In case we do not have any filters defined, the light intensity is saved directly.
373 // Otherwise, we rely on filter settings to set the appropiate intensity for each filter.
376 else
378
379 return true;
380}
381}
hid_device * device
bool isConnected() const
const char * getDeviceName() const
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
void initProperties(const char *group, uint32_t capabilities)
Initialize light box properties. It is recommended to call this function within initProperties() of y...
void ISGetProperties(const char *deviceName)
isGetLightBoxProperties Get light box properties
INDI::PropertyText ActiveDeviceTP
INDI::PropertyNumber LightIntensityNP
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process light box switch properties.
virtual bool EnableLightBox(bool enable)
EnableLightBox Turn on/off on a light box. Must be implemented in the child class.
bool processText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process light box text properties.
virtual bool SetLightBoxBrightness(uint16_t value)
setBrightness Set light level. Must be implemented in the child class, if supported.
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process light box number properties.
LightBoxInterface(DefaultDevice *device)
INDI::PropertyNumber FilterIntensityNP
void push(WidgetView< T > &&item)
void setState(IPState state)
bool isLabelMatch(const char *otherLabel) const
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.
void resize(size_t size)
bool isNameMatch(const char *otherName) const
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
bool update(const char *const texts[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
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
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
@ IP_RW
Definition indiapi.h:184
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
#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
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 * tagXMLEle(XMLEle *ep)
Return the tag of an XML element.
Definition lilxml.cpp:600
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
Definition lilxml.cpp:606
Namespace to encapsulate INDI client, drivers, and mediator classes.
void fill(const char *name, const char *label, const char *format, double min, double max, double step, double value)