Instrument Neutral Distributed Interface INDI 2.2.5
indiproperty.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright(c) 2011 Jasem Mutlaq. All rights reserved.
3 2022 Pawel Soja <[email protected]>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*******************************************************************************/
19
20#include "indiproperty.h"
21#include "indiproperty_p.h"
22
23#include "basedevice.h"
24
25#include "indipropertytext.h"
26#include "indipropertyswitch.h"
27#include "indipropertynumber.h"
28#include "indipropertylight.h"
29#include "indipropertyblob.h"
30
31#include "indipropertytext_p.h"
34#include "indipropertylight_p.h"
35#include "indipropertyblob_p.h"
36
37#include <cstdlib>
38#include <cstring>
39
40namespace INDI
41{
42
44 : property(property)
45 , type(property ? type : INDI_UNKNOWN)
46 , registered(property != nullptr)
47{ }
48
50 : property(property)
51 , type(property ? INDI_TEXT : INDI_UNKNOWN)
52 , registered(property != nullptr)
53{ }
54
56 : property(property)
57 , type(property ? INDI_NUMBER : INDI_UNKNOWN)
58 , registered(property != nullptr)
59{ }
60
62 : property(property)
63 , type(property ? INDI_SWITCH : INDI_UNKNOWN)
64 , registered(property != nullptr)
65{ }
66
68 : property(property)
69 , type(property ? INDI_LIGHT : INDI_UNKNOWN)
70 , registered(property != nullptr)
71{ }
72
74 : property(property)
75 , type(property ? INDI_BLOB : INDI_UNKNOWN)
76 , registered(property != nullptr)
77{ }
78
79#ifdef INDI_PROPERTY_BACKWARD_COMPATIBILE
81{
82 return this;
83}
84
86{
87 return this;
88}
89
90Property::operator INDI::Property *()
91{
92 D_PTR(Property);
93 return isValid() ? &d->self : nullptr;
94}
95
96Property::operator const INDI::Property *() const
97{
98 D_PTR(const Property);
99 return isValid() ? &d->self : nullptr;
100}
101#endif
102
104{
105 D_PTR(Property);
106 return isValid() ? &d->self : nullptr;
107}
108
109#define PROPERTY_CASE(CODE) \
110 switch (d->property != nullptr ? d->type : INDI_UNKNOWN) \
111 { \
112 case INDI_NUMBER: { auto property = static_cast<PropertyViewNumber *>(d->property); CODE } break; \
113 case INDI_TEXT: { auto property = static_cast<PropertyViewText *>(d->property); CODE } break; \
114 case INDI_SWITCH: { auto property = static_cast<PropertyViewSwitch *>(d->property); CODE } break; \
115 case INDI_LIGHT: { auto property = static_cast<PropertyViewLight *>(d->property); CODE } break; \
116 case INDI_BLOB: { auto property = static_cast<PropertyViewBlob *>(d->property); CODE } break; \
117 default:; \
118 }
119
121{
122 // Only delete properties if they were created dynamically via the buildSkeleton
123 // function. Other drivers are responsible for their own memory allocation.
124 if (property == nullptr || !dynamic)
125 return;
126
127 auto d = this;
128 PROPERTY_CASE( delete property; )
129}
130
132 : d_ptr(new PropertyPrivate(nullptr, INDI_UNKNOWN))
133{ }
134
136 : d_ptr(property.d_ptr)
137{ }
138
140 : d_ptr(property.d_ptr)
141{ }
142
144 : d_ptr(property.d_ptr)
145{ }
146
148 : d_ptr(property.d_ptr)
149{ }
150
152 : d_ptr(property.d_ptr)
153{ }
154
155#ifdef INDI_PROPERTY_BACKWARD_COMPATIBILE
156
158 : d_ptr(new PropertyNumberPrivate(property))
159{ }
160
162 : d_ptr(new PropertyTextPrivate(property))
163{ }
164
166 : d_ptr(new PropertySwitchPrivate(property))
167{ }
168
170 : d_ptr(new PropertyLightPrivate(property))
171{ }
172
174 : d_ptr(new PropertyBlobPrivate(property))
175{ }
176
178 : d_ptr(new PropertyNumberPrivate(property))
179{ }
180
182 : d_ptr(new PropertyTextPrivate(property))
183{ }
184
186 : d_ptr(new PropertySwitchPrivate(property))
187{ }
188
190 : d_ptr(new PropertyLightPrivate(property))
191{ }
192
194 : d_ptr(new PropertyBlobPrivate(property))
195{ }
196#endif
197
200
202 : d_ptr(&dd)
203{ }
204
205Property::Property(const std::shared_ptr<PropertyPrivate> &dd)
206 : d_ptr(dd)
207{ }
208
210{
211 D_PTR(Property);
212 d->type = p ? d->type : INDI_UNKNOWN;
213 d->registered = p != nullptr;
214 d->property = p;
215}
216
218{
219 D_PTR(Property);
220 d->type = t;
221}
222
224{
225 D_PTR(Property);
226 d->registered = r;
227}
228
230{
231 D_PTR(Property);
232 d->dynamic = dyn;
233}
234
236{
237 D_PTR(Property);
238 d->baseDevice = (idp == nullptr ? BaseDevice() : *idp);
239}
240
242{
243 D_PTR(Property);
244 d->baseDevice = baseDevice;
245}
246
248{
249 D_PTR(const Property);
250 return d->property;
251}
252
254{
255 D_PTR(const Property);
256 return d->property != nullptr ? d->type : INDI_UNKNOWN;
257}
258
259const char *Property::getTypeAsString() const
260{
261 switch (getType())
262 {
263 case INDI_NUMBER:
264 return "INDI_NUMBER";
265 case INDI_SWITCH:
266 return "INDI_SWITCH";
267 case INDI_TEXT:
268 return "INDI_TEXT";
269 case INDI_LIGHT:
270 return "INDI_LIGHT";
271 case INDI_BLOB:
272 return "INDI_BLOB";
273 case INDI_UNKNOWN:
274 return "INDI_UNKNOWN";
275 }
276 return "INDI_UNKNOWN";
277}
278
280{
281 D_PTR(const Property);
282 return d->registered;
283}
284
286{
287 D_PTR(const Property);
288 return d->dynamic;
289}
290
292{
293 D_PTR(const Property);
294 return d->baseDevice;
295}
296
297void Property::setName(const char *name)
298{
299 D_PTR(Property);
300 PROPERTY_CASE( property->setName(name); )
301}
302
303void Property::setLabel(const char *label)
304{
305 D_PTR(Property);
306 PROPERTY_CASE( property->setLabel(label); )
307}
308
309void Property::setGroupName(const char *group)
310{
311 D_PTR(Property);
312 PROPERTY_CASE( property->setGroupName(group); )
313}
314
316{
317 D_PTR(Property);
318 PROPERTY_CASE( property->setDeviceName(device); )
319}
320
321void Property::setTimestamp(const char *timestamp)
322{
323 D_PTR(Property);
324 PROPERTY_CASE( property->setTimestamp(timestamp); )
325}
326
328{
329 D_PTR(Property);
330 PROPERTY_CASE( property->setState(state); )
331}
332
334{
335 D_PTR(Property);
336 PROPERTY_CASE( property->setPermission(permission); )
337}
338
339void Property::setTimeout(double timeout)
340{
341 D_PTR(Property);
342 PROPERTY_CASE( property->setTimeout(timeout); )
343}
344
345const char *Property::getName() const
346{
347 D_PTR(const Property);
348 PROPERTY_CASE( return property->getName(); )
349 return nullptr;
350}
351
352const char *Property::getLabel() const
353{
354 D_PTR(const Property);
355 PROPERTY_CASE( return property->getLabel(); )
356 return nullptr;
357}
358
359const char *Property::getGroupName() const
360{
361 D_PTR(const Property);
362 PROPERTY_CASE( return property->getGroupName(); )
363 return nullptr;
364}
365
366const char *Property::getDeviceName() const
367{
368 D_PTR(const Property);
369 PROPERTY_CASE( return property->getDeviceName(); )
370 return nullptr;
371}
372
373const char *Property::getTimestamp() const
374{
375 D_PTR(const Property);
376 PROPERTY_CASE( return property->getTimestamp(); )
377 return nullptr;
378}
379
381{
382 D_PTR(const Property);
383 PROPERTY_CASE( return property->getState(); )
384 return IPS_ALERT;
385}
386
387const char *Property::getStateAsString() const
388{
389 return pstateStr(getState());
390}
391
393{
394 D_PTR(const Property);
395 PROPERTY_CASE( return property->getPermission(); )
396 return IP_RO;
397}
398
400{
401 D_PTR(const Property);
402 PROPERTY_CASE( return property->isEmpty(); )
403 return true;
404}
405
407{
408 D_PTR(const Property);
409 return d->type != INDI_UNKNOWN;
410}
411
412bool Property::isNameMatch(const char *otherName) const
413{
414 D_PTR(const Property);
415 PROPERTY_CASE( return property->isNameMatch(otherName); )
416 return false;
417}
418
419bool Property::isNameMatch(const std::string &otherName) const
420{
421 D_PTR(const Property);
422 PROPERTY_CASE( return property->isNameMatch(otherName); )
423 return false;
424}
425
426bool Property::isLabelMatch(const char *otherLabel) const
427{
428 D_PTR(const Property);
429 PROPERTY_CASE( return property->isLabelMatch(otherLabel); )
430 return false;
431}
432
433bool Property::isLabelMatch(const std::string &otherLabel) const
434{
435 D_PTR(const Property);
436 PROPERTY_CASE( return property->isLabelMatch(otherLabel); )
437 return false;
438}
439
440bool Property::isDeviceNameMatch(const char *otherDeviceName) const
441{
442 return isDeviceNameMatch(std::string(otherDeviceName));
443}
444
445bool Property::isDeviceNameMatch(const std::string &otherDeviceName) const
446{
447 return getDeviceName() == otherDeviceName;
448}
449
451{
452 return getType() == otherType;
453}
454
456{
457 D_PTR(const Property);
458 if (d->type == INDI_NUMBER)
459 return static_cast<PropertyViewNumber*>(d->property);
460
461 return nullptr;
462}
463
465{
466 D_PTR(const Property);
467 if (d->type == INDI_TEXT)
468 return static_cast<PropertyViewText*>(d->property);
469
470 return nullptr;
471}
472
474{
475 D_PTR(const Property);
476 if (d->type == INDI_LIGHT)
477 return static_cast<PropertyViewLight*>(d->property);
478
479 return nullptr;
480}
481
483{
484 D_PTR(const Property);
485 if (d->type == INDI_SWITCH)
486 return static_cast<PropertyViewSwitch*>(d->property);
487
488 return nullptr;
489}
490
492{
493 D_PTR(const Property);
494 if (d->type == INDI_BLOB)
495 return static_cast<PropertyViewBlob*>(d->property);
496
497 return nullptr;
498}
499
501{
502 D_PTR(const Property);
503 PROPERTY_CASE( return property->load(); )
504 return false;
505}
506
507void Property::save(FILE *fp) const
508{
509 D_PTR(const Property);
510 PROPERTY_CASE( property->save(fp); )
511}
512
513void Property::apply(const char *format, ...) const
514{
515 D_PTR(const Property);
516 va_list ap;
517 va_start(ap, format);
518 PROPERTY_CASE( property->vapply(format, ap); )
519 va_end(ap);
520}
521
522void Property::define(const char *format, ...) const
523{
524 D_PTR(const Property);
525 va_list ap;
526 va_start(ap, format);
527 PROPERTY_CASE( property->vdefine(format, ap); )
528 va_end(ap);
529}
530
531void Property::onUpdate(const std::function<void()> &callback)
532{
533 D_PTR(Property);
534 d->onUpdateCallback = callback;
535}
536
538{
539 D_PTR(Property);
540 if (d->onUpdateCallback)
541 d->onUpdateCallback();
542}
543
545{
546 D_PTR(const Property);
547 return d->onUpdateCallback != nullptr;
548}
549
550}
hid_device * device
Class to provide basic INDI device functionality.
Definition basedevice.h:52
PropertyPrivate(void *property, INDI_PROPERTY_TYPE type)
Provides generic container for INDI properties.
bool isDeviceNameMatch(const char *otherDeviceName) const
void onUpdate(const std::function< void()> &callback)
INDI::PropertyViewSwitch * getSwitch() const
const char * getGroupName() const
INDI::PropertyViewBlob * getBLOB() const
INDI::PropertyViewText * getText() const
void void void apply() const
const char * getDeviceName() const
void setTimestamp(const char *timestamp)
bool isValid() const
INDI::Property * operator->()
void setLabel(const char *label)
INDI::Property * self()
void save(FILE *fp) const
void setDynamic(bool d)
bool isEmpty() const
const char * getStateAsString() const
INDI::PropertyViewNumber * getNumber() const
const char * getName() const
INDI::PropertyViewLight * getLight() const
IPerm getPermission() const
void setType(INDI_PROPERTY_TYPE t)
void setGroupName(const char *groupName)
void * getProperty() const
bool hasUpdateCallback() const
bool isDynamic() const
void setTimeout(double timeout)
void setDeviceName(const char *deviceName)
bool isNameMatch(const char *otherName) const
const char * getTypeAsString() const
BaseDevice getBaseDevice() const
const char * getLabel() const
void define() const
IPState getState() const
void setBaseDevice(BaseDevice *idp)
bool getRegistered() const
void setName(const char *name)
INDI_PROPERTY_TYPE getType() const
bool isLabelMatch(const char *otherLabel) const
void setRegistered(bool r)
void setProperty(void *)
const char * getTimestamp() const
bool isTypeMatch(INDI_PROPERTY_TYPE otherType) const
void setState(IPState state)
void setPermission(IPerm permission)
IPerm
Permission hint, with respect to client.
Definition indiapi.h:181
@ IP_RO
Definition indiapi.h:182
IPState
Property state.
Definition indiapi.h:158
@ IPS_ALERT
Definition indiapi.h:162
INDI_PROPERTY_TYPE
const char * pstateStr(IPState s)
Definition indidevapi.c:845
@ INDI_LIGHT
Definition indidriver.c:60
@ INDI_TEXT
Definition indidriver.c:59
@ INDI_UNKNOWN
Definition indidriver.c:62
@ INDI_NUMBER
Definition indidriver.c:57
@ INDI_SWITCH
Definition indidriver.c:58
@ INDI_BLOB
Definition indidriver.c:61
#define PROPERTY_CASE(CODE)
Namespace to encapsulate INDI client, drivers, and mediator classes.
uint16_t type
Definition pwc-ioctl.h:0
BLOB (Binary Large Object) vector property descriptor.
Definition indiapi.h:469
Light vector property descriptor.
Definition indiapi.h:415
Number vector property descriptor.
Definition indiapi.h:317
Switch vector property descriptor.
Definition indiapi.h:365
Text vector property descriptor.
Definition indiapi.h:244