Instrument Neutral Distributed Interface INDI 2.2.5
agent_imager.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright(c) 2013-2016 CloudMakers, s. r. o. All rights reserved.
3 Copyright(c) 2017 Marco Gulino <[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 "agent_imager.h"
22
23#include <cstring>
24#include <algorithm>
25#include <memory>
26
27#include "group.h"
28
29#define DOWNLOAD_TAB "Download images"
30#define IMAGE_NAME "%s/%s_%d_%03d%s"
31#define IMAGE_PREFIX "_TMP_"
32
33
34#define GROUP_PREFIX "GROUP_"
35#define GROUP_PREFIX_LEN 6
36
37
38const std::string Imager::DEVICE_NAME = "Imager Agent";
39std::shared_ptr<Imager> imager(new Imager());
40
41// Imager ----------------------------------------------------------------------------
42
44{
45 setVersion(1, 2);
46 groups.resize(MAX_GROUP_COUNT);
47 int i = 0;
48 std::generate(groups.begin(), groups.end(), [this, &i] { return std::make_shared<Group>(i++, this); });
49}
50
51bool Imager::isRunning()
52{
53 return ProgressNP.getState() == IPS_BUSY;
54}
55
56bool Imager::isCCDConnected()
57{
58 return StatusLP[CCD].getState() == IPS_OK;
59}
60
61bool Imager::isFilterConnected()
62{
63 return StatusLP[FILTER].getState() == IPS_OK;
64}
65
66std::shared_ptr<Group> Imager::getGroup(int index) const
67{
68 if(index > -1 && index <= maxGroup)
69 return groups[index];
70 return {};
71}
72
73std::shared_ptr<Group> Imager::currentGroup() const
74{
75 return getGroup(group - 1);
76}
77
78
79
80std::shared_ptr<Group> Imager::nextGroup() const
81{
82 return getGroup(group);
83}
84
85void Imager::initiateNextFilter()
86{
87 if (!isRunning())
88 return;
89
90 if (group > 0 && image > 0 && group <= maxGroup && image <= maxImage)
91 {
92 int filterSlot = currentGroup()->filterSlot();
93
94 if (!isFilterConnected())
95 {
96 if (filterSlot != 0)
97 {
98 ProgressNP.setState(IPS_ALERT);
99 LOG_INFO("Filter wheel is not connected");
100 ProgressNP.apply();
101 return;
102 }
103 else
104 {
105 initiateNextCapture();
106 }
107 }
108 else if (filterSlot != 0 && FilterSlotNP[0].getValue() != filterSlot)
109 {
110 FilterSlotNP[0].setValue(filterSlot);
111 sendNewNumber(FilterSlotNP);
112 LOGF_DEBUG("Group %d of %d, image %d of %d, filer %d, filter set initiated on %s",
113 group, maxGroup, image, maxImage, (int)FilterSlotNP[0].getValue(), FilterSlotNP.getDeviceName());
114 }
115 else
116 {
117 initiateNextCapture();
118 }
119 }
120}
121
122void Imager::initiateNextCapture()
123{
124 if (isRunning())
125 {
126 if (group > 0 && image > 0 && group <= maxGroup && image <= maxImage)
127 {
128 if (!isCCDConnected())
129 {
130 ProgressNP.setState(IPS_ALERT);
131 LOG_INFO("CCD is not connected");
132 ProgressNP.apply();
133 return;
134 }
135 CCDImageBinNP[HOR_BIN].setValue(currentGroup()->binning());
136 CCDImageBinNP[VER_BIN].setValue(currentGroup()->binning());
137 sendNewNumber(CCDImageBinNP);
138 CCDImageExposureNP[0].setValue(currentGroup()->exposure());
139 sendNewNumber(CCDImageExposureNP);
140 CCDUploadSettingsTP[UPLOAD_DIR].setText(ImageNameTP[IMAGE_FOLDER].getText());
141 CCDUploadSettingsTP[UPLOAD_PREFIX].setText("_TMP_");
142 sendNewSwitch(CCDUploadSP);
143 sendNewText(CCDUploadSettingsTP);
144 LOGF_DEBUG("Group %d of %d, image %d of %d, duration %.1fs, binning %d, capture initiated on %s", group,
145 maxGroup, image, maxImage, CCDImageExposureNP[0].getValue(), (int)CCDImageBinNP[HOR_BIN].getValue(),
146 CCDImageExposureNP.getDeviceName());
147 }
148 }
149}
150
151void Imager::startBatch()
152{
153 LOG_DEBUG("Batch started");
154 ProgressNP[GROUP].setValue(group = 1);
155 ProgressNP[IMAGE].setValue(image = 1);
156 maxImage = currentGroup()->count();
157 ProgressNP.setState(IPS_BUSY);
158 ProgressNP.apply();
159 initiateNextFilter();
160}
161
162void Imager::abortBatch()
163{
164 ProgressNP.setState(IPS_ALERT);
165 LOG_ERROR("Batch aborted");
166 ProgressNP.apply();
167}
168
169void Imager::batchDone()
170{
171 ProgressNP.setState(IPS_OK);
172 LOG_INFO("Batch done");
173 ProgressNP.apply();
174}
175
176void Imager::initiateDownload()
177{
178 int group = (int)DownloadNP[GROUP].getValue();
179 int image = (int)DownloadNP[IMAGE].getValue();
180 char name[128] = {0};
181 std::ifstream file;
182
183 if (group == 0 || image == 0)
184 return;
185
186 snprintf(name, sizeof(name), IMAGE_NAME, ImageNameTP[IMAGE_FOLDER].getText(), ImageNameTP[IMAGE_NAME_PREFIX].getText(), group, image,
187 format);
188 file.open(name, std::ios::in | std::ios::binary | std::ios::ate);
189 DownloadNP[GROUP].setValue(0);
190 DownloadNP[IMAGE].setValue(0);
191 if (file.is_open())
192 {
193 long size = file.tellg();
194 char *data = new char[size];
195
196 file.seekg(0, std::ios::beg);
197 file.read(data, size);
198 file.close();
199 remove(name);
200 LOGF_DEBUG("Group %d, image %d, download initiated", group, image);
201 DownloadNP.setState(IPS_BUSY);
202 LOG_INFO("Download initiated");
203 DownloadNP.apply();
204 // strncpy(FitsBP[0].format, format, MAXINDIBLOBFMT);
205 FitsBP[0].setFormat(format);
206 FitsBP[0].setBlob(data);
207 FitsBP[0].setBlobLen(FitsBP[0].getSize() == size);
208 FitsBP.setState(IPS_OK);
209 FitsBP.apply();
210 DownloadNP.setState(IPS_OK);
211 LOG_INFO("Download finished");
212 DownloadNP.apply();
213 }
214 else
215 {
216 DownloadNP.setState(IPS_ALERT);
217 LOG_ERROR("Download failed");
218 DownloadNP.apply();
219 LOGF_DEBUG("Group %d, image %d, upload failed", group, image);
220 }
221}
222
223// DefaultDevice ----------------------------------------------------------------------------
224
226{
227 return Imager::DEVICE_NAME.c_str();
228}
229
231{
233
235
236 GroupCountNP[0].fill("GROUP_COUNT", "Image group count", "%3.0f", 1, MAX_GROUP_COUNT, 1, maxGroup = 1);
237 GroupCountNP.fill(getDefaultName(), "GROUPS", "Image groups", MAIN_CONTROL_TAB, IP_RW,
238 60, IPS_IDLE);
239
240 ControlledDeviceTP[CCD].fill("CCD", "CCD", "CCD Simulator");
241 ControlledDeviceTP[FILTER].fill("FILTER", "Filter wheel", "Filter Simulator");
242 ControlledDeviceTP.fill(getDefaultName(), "DEVICES", "Controlled devices",
244 controlledCCD = ControlledDeviceTP[CCD].getText();
245 controlledFilterWheel = ControlledDeviceTP[FILTER].getText();
246
247 StatusLP[CCD].fill("CCD", controlledCCD, IPS_IDLE);
248 StatusLP[FILTER].fill("FILTER", controlledFilterWheel, IPS_IDLE);
249 StatusLP.fill(getDefaultName(), "STATUS", "Controlled devices", MAIN_CONTROL_TAB, IPS_IDLE);
250
251 ProgressNP[GROUP].fill("GROUP", "Current group", "%3.0f", 1, MAX_GROUP_COUNT, 1, 0);
252 ProgressNP[IMAGE].fill("IMAGE", "Current image", "%3.0f", 1, 100, 1, 0);
253 ProgressNP[REMAINING_TIME].fill("REMAINING_TIME", "Remaining time", "%5.2f", 0, 36000, 0, 0.0);
254 ProgressNP.fill(getDefaultName(), "PROGRESS", "Batch execution progress", MAIN_CONTROL_TAB,
255 IP_RO, 60, IPS_IDLE);
256
257 BatchSP[START].fill("START", "Start batch", ISS_OFF);
258 BatchSP[ABORT].fill("ABORT", "Abort batch", ISS_OFF);
259 BatchSP.fill(getDefaultName(), "BATCH", "Batch control", MAIN_CONTROL_TAB, IP_RW, ISR_NOFMANY,
260 60, IPS_IDLE);
261
262 ImageNameTP[IMAGE_FOLDER].fill("IMAGE_FOLDER", "Image folder", "/tmp");
263 ImageNameTP[IMAGE_NAME_PREFIX].fill("IMAGE_NAME_PREFIX", "Image prefix", "IMG");
264 ImageNameTP.fill(getDefaultName(), "IMAGE_NAME", "Image name", OPTIONS_TAB, IP_RW, 60,
265 IPS_IDLE);
266
267 DownloadNP[GROUP].fill("GROUP", "Group", "%3.0f", 1, MAX_GROUP_COUNT, 1, 1);
268 DownloadNP[IMAGE].fill("IMAGE", "Image", "%3.0f", 1, 100, 1, 1);
269 DownloadNP.fill(getDefaultName(), "DOWNLOAD", "Download image", DOWNLOAD_TAB, IP_RW, 60,
270 IPS_IDLE);
271
272 FitsBP[0].fill("IMAGE", "Image", "");
273 FitsBP.fill(getDefaultName(), "IMAGE", "Image Data", DOWNLOAD_TAB, IP_RO, 60, IPS_IDLE);
274
275 defineProperty(GroupCountNP);
276 defineProperty(ControlledDeviceTP);
277 defineProperty(ImageNameTP);
278
279 for (int i = 0; i < GroupCountNP[0].getValue(); i++)
280 {
281 groups[i]->defineProperties();
282 }
283
284 CCDImageExposureNP[0].fill("CCD_EXPOSURE_VALUE", "Duration (s)", "%5.2f", 0, 36000, 0, 1.0);
285 CCDImageExposureNP.fill(ControlledDeviceTP[CCD].getText(), "CCD_EXPOSURE", "Expose",
287
288 CCDImageBinNP[HOR_BIN].fill("HOR_BIN", "X", "%2.0f", 1, 4, 1, 1);
289 CCDImageBinNP[VER_BIN].fill("VER_BIN", "Y", "%2.0f", 1, 4, 1, 1);
290 CCDImageBinNP.fill(ControlledDeviceTP[CCD].getText(), "CCD_BINNING", "Binning",
292
293 CCDUploadSP[UPLOAD_CLIENT].fill("UPLOAD_CLIENT", "Client", ISS_OFF);
294 CCDUploadSP[UPLOAD_LOCAL].fill("UPLOAD_LOCAL", "Local", ISS_ON);
295 CCDUploadSP[UPLOAD_BOTH].fill("UPLOAD_BOTH", "Both", ISS_OFF);
296 CCDUploadSP.fill(ControlledDeviceTP[CCD].getText(), "UPLOAD_MODE", "Upload", OPTIONS_TAB,
298
299 CCDUploadSettingsTP[UPLOAD_DIR].fill("UPLOAD_DIR", "Dir", "");
300 CCDUploadSettingsTP[UPLOAD_PREFIX].fill("UPLOAD_PREFIX", "Prefix", IMAGE_PREFIX);
301 CCDUploadSettingsTP.fill(ControlledDeviceTP[CCD].getText(), "UPLOAD_SETTINGS",
302 "Upload Settings", OPTIONS_TAB, IP_RW, 60, IPS_IDLE);
303
304 FilterSlotNP[0].fill("FILTER_SLOT_VALUE", "Filter", "%3.0f", 1.0, 12.0, 1.0, 1.0);
305 FilterSlotNP.fill(ControlledDeviceTP[FILTER].getText(), "FILTER_SLOT", "Filter Slot",
307
308 return true;
309}
310
312{
313 if (isConnected())
314 {
315 defineProperty(StatusLP);
316 ProgressNP[GROUP].setValue(group = 0);
317 ProgressNP[IMAGE].setValue(image = 0);
318 ProgressNP.setState(IPS_IDLE);
319 defineProperty(ProgressNP);
320 BatchSP.setState(IPS_IDLE);
321 defineProperty(BatchSP);
322 DownloadNP[GROUP].setValue(0);
323 DownloadNP[IMAGE].setValue(0);
324 DownloadNP.setState(IPS_IDLE);
325 defineProperty(DownloadNP);
326 FitsBP.setState(IPS_IDLE);
327 defineProperty(FitsBP);
328 }
329 else
330 {
331 deleteProperty(StatusLP);
332 deleteProperty(ProgressNP);
333 deleteProperty(BatchSP);
334 deleteProperty(DownloadNP);
335 deleteProperty(FitsBP);
336 }
337 return true;
338}
339
340void Imager::ISGetProperties(const char *dev)
341{
342 DefaultDevice::ISGetProperties(dev);
343}
344
345bool Imager::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
346{
347 if (Imager::DEVICE_NAME == dev)
348 {
349 if (GroupCountNP[0].isNameMatch(name))
350 {
351 for (int i = 0; i < maxGroup; i++)
352 groups[i]->deleteProperties();
353 GroupCountNP.update(values, names, n);
354 maxGroup = (int)GroupCountNP[0].getValue();
355 if (maxGroup > MAX_GROUP_COUNT)
356 GroupCountNP[0].setValue(maxGroup = MAX_GROUP_COUNT);
357 for (int i = 0; i < maxGroup; i++)
358 groups[i]->defineProperties();
359 GroupCountNP.setState(IPS_OK);
360 GroupCountNP.apply();
361 return true;
362 }
363 if (DownloadNP.isNameMatch(name))
364 {
365 DownloadNP.update(values, names, n);
366 initiateDownload();
367 return true;
368 }
369 if (strncmp(name, GROUP_PREFIX, GROUP_PREFIX_LEN) == 0)
370 {
371 for (int i = 0; i < GroupCountNP[0].getValue(); i++)
372 if (groups[i]->ISNewNumber(dev, name, values, names, n))
373 {
374 return true;
375 }
376 return false;
377 }
378 }
379 return DefaultDevice::ISNewNumber(dev, name, values, names, n);
380}
381
382bool Imager::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
383{
384 if (Imager::DEVICE_NAME == dev)
385 {
386 if (BatchSP.isNameMatch(name))
387 {
388 for (int i = 0; i < n; i++)
389 {
390 if (strcmp(names[i], BatchSP[START].getName()) == 0 && states[i] == ISS_ON)
391 {
392 if (!isRunning())
393 startBatch();
394 }
395 if (strcmp(names[i], BatchSP[ABORT].getName()) == 0 && states[i] == ISS_ON)
396 {
397 if (isRunning())
398 abortBatch();
399 }
400 }
401 BatchSP.setState(IPS_OK);
402 BatchSP.apply();
403 return true;
404 }
405 }
406 return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
407}
408
409bool Imager::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
410{
411 if (Imager::DEVICE_NAME == dev)
412 {
413 if (ControlledDeviceTP.isNameMatch(name))
414 {
415 ControlledDeviceTP.update(texts, names, n);
416 ControlledDeviceTP.apply();
417
418 StatusLP[CCD].setLabel(ControlledDeviceTP[CCD].getText());
419 CCDImageExposureNP.setDeviceName(ControlledDeviceTP[CCD].getText());
420 CCDImageBinNP.setDeviceName(ControlledDeviceTP[CCD].getText());
421 StatusLP[FILTER].setLabel(ControlledDeviceTP[FILTER].getText());
422 FilterSlotNP.setDeviceName(ControlledDeviceTP[FILTER].getText());
423
424 return true;
425 }
426 if (ImageNameTP.isNameMatch(name))
427 {
428 ImageNameTP.update(texts, names, n);
429 ImageNameTP.apply();
430 return true;
431 }
432 }
433 return INDI::DefaultDevice::ISNewText(dev, name, texts, names, n);
434}
435
436bool Imager::ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[],
437 char *names[], int n)
438{
439 return INDI::DefaultDevice::ISNewBLOB(dev, name, sizes, blobsizes, blobs, formats, names, n);
440}
441
446
448{
449 setServer("localhost", 7624); // TODO configuration options
450 BaseClient::watchDevice(controlledCCD);
451 BaseClient::watchDevice(controlledFilterWheel);
453 setBLOBMode(B_ALSO, controlledCCD, nullptr);
454
455 return true;
456}
457
459{
460 if (isRunning())
461 abortBatch();
463 return true;
464}
465
466// BaseClient ----------------------------------------------------------------------------
467
469{
470 LOG_DEBUG("Server connected");
471 StatusLP[CCD].setState(IPS_ALERT);
472 StatusLP[FILTER].setState(IPS_ALERT);
473 StatusLP.apply();
474}
475
477{
478 std::string deviceName{baseDevice.getDeviceName()};
479
480 LOGF_DEBUG("Device %s detected", deviceName.c_str());
481 if (deviceName == controlledCCD)
482 StatusLP[CCD].setState(IPS_BUSY);
483 if (deviceName == controlledFilterWheel)
484 StatusLP[FILTER].setState(IPS_BUSY);
485
486 StatusLP.apply();
487}
488
490{
491 std::string deviceName{property.getDeviceName()};
492
493 if (property.isNameMatch(INDI::SP::CONNECTION))
494 {
495 bool state = INDI::PropertySwitch(property)[0].getState() != ISS_OFF;
496 if (deviceName == controlledCCD)
497 {
498 if (state)
499 {
500 StatusLP[CCD].setState(IPS_OK);
501 }
502 else
503 {
504 connectDevice(controlledCCD);
505 LOGF_DEBUG("Connecting %s", controlledCCD);
506 }
507 }
508 if (deviceName == controlledFilterWheel)
509 {
510 if (state)
511 {
512 StatusLP[FILTER].setState(IPS_OK);
513 }
514 else
515 {
516 connectDevice(controlledFilterWheel);
517 LOGF_DEBUG("Connecting %s", controlledFilterWheel);
518 }
519 }
520 StatusLP.apply();
521 }
522}
523
525{
526 std::string deviceName{property.getDeviceName()};
527
528 if (property.getType() == INDI_BLOB)
529 {
530 for (auto &bp : INDI::PropertyBlob(property))
531 {
532 if (ProgressNP.getState() == IPS_BUSY)
533 {
534 char name[128] = {0};
535 std::ofstream file;
536
537 snprintf(format, sizeof(format), "%s", bp.getFormat());
538 snprintf(name, sizeof(name), IMAGE_NAME, ImageNameTP[IMAGE_FOLDER].getText(), ImageNameTP[IMAGE_NAME_PREFIX].getText(), group, image,
539 format);
540 file.open(name, std::ios::out | std::ios::binary | std::ios::trunc);
541 file.write(static_cast<char *>(bp.getBlob()), bp.getBlobLen());
542 file.close();
543 LOGF_DEBUG("Group %d of %d, image %d of %d, saved to %s", group, maxGroup, image, maxImage,
544 name);
545 if (image == maxImage)
546 {
547 if (group == maxGroup)
548 {
549 batchDone();
550 }
551 else
552 {
553 maxImage = nextGroup()->count();
554 ProgressNP[GROUP].setValue(group = group + 1);
555 ProgressNP[IMAGE].setValue(image = 1);
556 ProgressNP.apply();
557 initiateNextFilter();
558 }
559 }
560 else
561 {
562 ProgressNP[IMAGE].setValue(image = image + 1);
563 ProgressNP.apply();
564 initiateNextFilter();
565 }
566 }
567 }
568 return;
569 }
570
571 if (property.isNameMatch(INDI::SP::CONNECTION))
572 {
573 INDI::PropertySwitch propertySwitch{property};
574
575 bool state = propertySwitch[0].getState() != ISS_OFF;
576 if (deviceName == controlledCCD)
577 {
578 StatusLP[CCD].setState(state ? IPS_OK : IPS_BUSY);
579 }
580
581 if (deviceName == controlledFilterWheel)
582 {
583 StatusLP[FILTER].setState(state ? IPS_OK : IPS_BUSY);
584 }
585 StatusLP.apply();
586 return;
587 }
588
589 if (deviceName == controlledCCD && property.isNameMatch("CCD_EXPOSURE"))
590 {
591 INDI::PropertyNumber propertyNumber{property};
592 ProgressNP[REMAINING_TIME].setValue(propertyNumber[0].getValue());
593 ProgressNP.apply();
594 return;
595 }
596
597 if (deviceName == controlledFilterWheel && property.isNameMatch("FILTER_SLOT"))
598 {
599 INDI::PropertyNumber propertyNumber{property};
600 FilterSlotNP[0].setValue(propertyNumber[0].getValue());
601 if (property.getState() == IPS_OK)
602 initiateNextCapture();
603 return;
604 }
605
606 if (deviceName == controlledCCD && property.isNameMatch("CCD_FILE_PATH"))
607 {
608 INDI::PropertyText propertyText(property);
609 char name[128] = {0};
610
611 snprintf(format, sizeof(format), "%s", strrchr(propertyText[0].getText(), '.'));
612 snprintf(name, sizeof(name), IMAGE_NAME, ImageNameTP[IMAGE_FOLDER].getText(), ImageNameTP[IMAGE_NAME_PREFIX].getText(), group, image,
613 format);
614 rename(propertyText[0].getText(), name);
615 LOGF_DEBUG("Group %d of %d, image %d of %d, saved to %s", group, maxGroup, image,
616 maxImage, name);
617 if (image == maxImage)
618 {
619 if (group == maxGroup)
620 {
621 batchDone();
622 }
623 else
624 {
625 maxImage = nextGroup()->count();
626 ProgressNP[GROUP].setValue(group = group + 1);
627 ProgressNP[IMAGE].setValue(image = 1);
628 ProgressNP.apply();
629 initiateNextFilter();
630 }
631 }
632 else
633 {
634 ProgressNP[IMAGE].setValue(image = image + 1);
635 ProgressNP.apply();
636 initiateNextFilter();
637 }
638 return;
639 }
640}
641
642void Imager::serverDisconnected(int exit_code)
643{
644 INDI_UNUSED(exit_code);
645 LOG_DEBUG("Server disconnected");
646 StatusLP[CCD].setState(IPS_ALERT);
647 StatusLP[FILTER].setState(IPS_ALERT);
648}
649
650
std::shared_ptr< Imager > imager(new Imager())
#define GROUP_PREFIX
#define DOWNLOAD_TAB
#define IMAGE_NAME
#define GROUP_PREFIX_LEN
#define IMAGE_PREFIX
#define MAX_GROUP_COUNT
void setServer(const char *hostname, unsigned int port)
Set the server host name and port.
void sendNewSwitch(INDI::Property pp)
Send new Switch command to server.
void setBLOBMode(BLOBHandling blobH, const char *dev, const char *prop=nullptr)
Set Binary Large Object policy mode.
void connectDevice(const char *deviceName)
Disconnect INDI driver.
void sendNewNumber(INDI::Property pp)
Send new Number command to server.
void sendNewText(INDI::Property pp)
Send new Text command to server.
bool disconnectServer(int exit_code=0) override
Disconnect from INDI server. Any devices previously created will be deleted and memory cleared.
bool connectServer() override
Connect to INDI server.
Class to provide basic INDI device functionality.
Definition basedevice.h:52
bool isConnected() const
const char * getDeviceName() const
INDI::PropertyText getText(const char *name) const
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
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 initProperties()
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
Process the client newBLOB command.
void addDebugControl()
Add Debug control to the driver.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
void setDeviceName(const char *name)
void setState(IPState state)
const char * getDeviceName() const
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void setLabel(const char *label)
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, IPState state)
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)
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)
Provides generic container for INDI properties.
INDI::PropertyViewText * getText() const
bool isNameMatch(const char *otherName) const
IPState getState() const
INDI_PROPERTY_TYPE getType() const
virtual void updateProperty(INDI::Property property) override
Emmited when a new property value arrives from INDI server.
static const std::string DEVICE_NAME
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual const char * getDefaultName() override
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 void serverConnected() override
Emmited when the server is connected.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual void newDevice(INDI::BaseDevice baseDevice) override
Emmited when a new device is created from INDI server.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool Disconnect() override
Disconnect from device.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual void serverDisconnected(int exit_code) override
Emmited when the server gets disconnected.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISSnoopDevice(XMLEle *root) override
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
virtual void newProperty(INDI::Property property) override
Emmited when a new property is created for an INDI driver.
virtual bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) override
Process the client newBLOB command.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device 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
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
@ IP_RW
Definition indiapi.h:184
@ IP_RO
Definition indiapi.h:182
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
@ ISR_NOFMANY
Definition indiapi.h:173
@ B_ALSO
Definition indidevapi.h:269
#define INDI_UNUSED(x)
Definition indidevapi.h:132
@ INDI_BLOB
Definition indidriver.c:61
#define LOG_DEBUG(txt)
Definition indilogger.h:75
#define LOGF_DEBUG(fmt,...)
Definition indilogger.h:83
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition indilogger.h:72
#define LOG_INFO(txt)
Definition indilogger.h:74
const char * CONNECTION
Connect to and disconnect from device.