Instrument Neutral Distributed Interface INDI  2.0.2
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 <marco.gulino@gmai.com>
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"
21 #include "indistandardproperty.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 
38 const std::string Imager::DEVICE_NAME = "Imager Agent";
39 std::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 
51 bool Imager::isRunning()
52 {
53  return ProgressNP.s == IPS_BUSY;
54 }
55 
56 bool Imager::isCCDConnected()
57 {
58  return StatusL[0].s == IPS_OK;
59 }
60 
61 bool Imager::isFilterConnected()
62 {
63  return StatusL[1].s == IPS_OK;
64 }
65 
66 std::shared_ptr<Group> Imager::getGroup(int index) const
67 {
68  if(index > -1 && index <= maxGroup)
69  return groups[index];
70  return {};
71 }
72 
73 std::shared_ptr<Group> Imager::currentGroup() const
74 {
75  return getGroup(group - 1);
76 }
77 
78 
79 
80 std::shared_ptr<Group> Imager::nextGroup() const
81 {
82  return getGroup(group);
83 }
84 
85 void 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.s = IPS_ALERT;
99  IDSetNumber(&ProgressNP, "Filter wheel is not connected");
100  return;
101  }
102  else
103  {
104  initiateNextCapture();
105  }
106  }
107  else if (filterSlot != 0 && FilterSlotN[0].value != filterSlot)
108  {
109  FilterSlotN[0].value = filterSlot;
110  sendNewNumber(&FilterSlotNP);
111  LOGF_DEBUG("Group %d of %d, image %d of %d, filer %d, filter set initiated on %s",
112  group, maxGroup, image, maxImage, (int)FilterSlotN[0].value, FilterSlotNP.device);
113  }
114  else
115  {
116  initiateNextCapture();
117  }
118  }
119 }
120 
121 void Imager::initiateNextCapture()
122 {
123  if (isRunning())
124  {
125  if (group > 0 && image > 0 && group <= maxGroup && image <= maxImage)
126  {
127  if (!isCCDConnected())
128  {
129  ProgressNP.s = IPS_ALERT;
130  IDSetNumber(&ProgressNP, "CCD is not connected");
131  return;
132  }
133  CCDImageBinN[0].value = currentGroup()->binning();
134  CCDImageBinN[1].value = currentGroup()->binning();
135  sendNewNumber(&CCDImageBinNP);
136  CCDImageExposureN[0].value = currentGroup()->exposure();
137  sendNewNumber(&CCDImageExposureNP);
138  IUSaveText(&CCDUploadSettingsT[0], ImageNameT[0].text);
139  IUSaveText(&CCDUploadSettingsT[1], "_TMP_");
140  sendNewSwitch(&CCDUploadSP);
141  sendNewText(&CCDUploadSettingsTP);
142  LOGF_DEBUG("Group %d of %d, image %d of %d, duration %.1fs, binning %d, capture initiated on %s", group,
143  maxGroup, image, maxImage, CCDImageExposureN[0].value, (int)CCDImageBinN[0].value,
144  CCDImageExposureNP.device);
145  }
146  }
147 }
148 
149 void Imager::startBatch()
150 {
151  LOG_DEBUG("Batch started");
152  ProgressN[0].value = group = 1;
153  ProgressN[1].value = image = 1;
154  maxImage = currentGroup()->count();
155  ProgressNP.s = IPS_BUSY;
156  IDSetNumber(&ProgressNP, nullptr);
157  initiateNextFilter();
158 }
159 
160 void Imager::abortBatch()
161 {
162  ProgressNP.s = IPS_ALERT;
163  IDSetNumber(&ProgressNP, "Batch aborted");
164 }
165 
166 void Imager::batchDone()
167 {
168  ProgressNP.s = IPS_OK;
169  IDSetNumber(&ProgressNP, "Batch done");
170 }
171 
172 void Imager::initiateDownload()
173 {
174  int group = (int)DownloadN[0].value;
175  int image = (int)DownloadN[1].value;
176  char name[128] = {0};
177  std::ifstream file;
178 
179  if (group == 0 || image == 0)
180  return;
181 
182  sprintf(name, IMAGE_NAME, ImageNameT[0].text, ImageNameT[1].text, group, image, format);
183  file.open(name, std::ios::in | std::ios::binary | std::ios::ate);
184  DownloadN[0].value = 0;
185  DownloadN[1].value = 0;
186  if (file.is_open())
187  {
188  long size = file.tellg();
189  char *data = new char[size];
190 
191  file.seekg(0, std::ios::beg);
192  file.read(data, size);
193  file.close();
194  remove(name);
195  LOGF_DEBUG("Group %d, image %d, download initiated", group, image);
196  DownloadNP.s = IPS_BUSY;
197  IDSetNumber(&DownloadNP, "Download initiated");
198  strncpy(FitsB[0].format, format, MAXINDIBLOBFMT);
199  FitsB[0].blob = data;
200  FitsB[0].bloblen = FitsB[0].size = size;
201  FitsBP.s = IPS_OK;
202  IDSetBLOB(&FitsBP, nullptr);
203  DownloadNP.s = IPS_OK;
204  IDSetNumber(&DownloadNP, "Download finished");
205  }
206  else
207  {
208  DownloadNP.s = IPS_ALERT;
209  IDSetNumber(&DownloadNP, "Download failed");
210  LOGF_DEBUG("Group %d, image %d, upload failed", group, image);
211  }
212 }
213 
214 // DefaultDevice ----------------------------------------------------------------------------
215 
217 {
218  return Imager::DEVICE_NAME.c_str();
219 }
220 
222 {
224 
225  addDebugControl();
226 
227  IUFillNumber(&GroupCountN[0], "GROUP_COUNT", "Image group count", "%3.0f", 1, MAX_GROUP_COUNT, 1, maxGroup = 1);
228  IUFillNumberVector(&GroupCountNP, GroupCountN, 1, getDefaultName(), "GROUPS", "Image groups", MAIN_CONTROL_TAB, IP_RW,
229  60, IPS_IDLE);
230 
231  IUFillText(&ControlledDeviceT[0], "CCD", "CCD", "CCD Simulator");
232  IUFillText(&ControlledDeviceT[1], "FILTER", "Filter wheel", "Filter Simulator");
233  IUFillTextVector(&ControlledDeviceTP, ControlledDeviceT, 2, getDefaultName(), "DEVICES", "Controlled devices",
235  controlledCCD = ControlledDeviceT[0].text;
236  controlledFilterWheel = ControlledDeviceT[1].text;
237 
238  IUFillLight(&StatusL[0], "CCD", controlledCCD, IPS_IDLE);
239  IUFillLight(&StatusL[1], "FILTER", controlledFilterWheel, IPS_IDLE);
240  IUFillLightVector(&StatusLP, StatusL, 2, getDefaultName(), "STATUS", "Controlled devices", MAIN_CONTROL_TAB, IPS_IDLE);
241 
242  IUFillNumber(&ProgressN[0], "GROUP", "Current group", "%3.0f", 1, MAX_GROUP_COUNT, 1, 0);
243  IUFillNumber(&ProgressN[1], "IMAGE", "Current image", "%3.0f", 1, 100, 1, 0);
244  IUFillNumber(&ProgressN[2], "REMAINING_TIME", "Remaining time", "%5.2f", 0, 36000, 0, 0.0);
245  IUFillNumberVector(&ProgressNP, ProgressN, 3, getDefaultName(), "PROGRESS", "Batch execution progress", MAIN_CONTROL_TAB,
246  IP_RO, 60, IPS_IDLE);
247 
248  IUFillSwitch(&BatchS[0], "START", "Start batch", ISS_OFF);
249  IUFillSwitch(&BatchS[1], "ABORT", "Abort batch", ISS_OFF);
250  IUFillSwitchVector(&BatchSP, BatchS, 2, getDefaultName(), "BATCH", "Batch control", MAIN_CONTROL_TAB, IP_RW, ISR_NOFMANY,
251  60, IPS_IDLE);
252 
253  IUFillText(&ImageNameT[0], "IMAGE_FOLDER", "Image folder", "/tmp");
254  IUFillText(&ImageNameT[1], "IMAGE_PREFIX", "Image prefix", "IMG");
255  IUFillTextVector(&ImageNameTP, ImageNameT, 2, getDefaultName(), "IMAGE_NAME", "Image name", OPTIONS_TAB, IP_RW, 60,
256  IPS_IDLE);
257 
258  IUFillNumber(&DownloadN[0], "GROUP", "Group", "%3.0f", 1, MAX_GROUP_COUNT, 1, 1);
259  IUFillNumber(&DownloadN[1], "IMAGE", "Image", "%3.0f", 1, 100, 1, 1);
260  IUFillNumberVector(&DownloadNP, DownloadN, 2, getDefaultName(), "DOWNLOAD", "Download image", DOWNLOAD_TAB, IP_RW, 60,
261  IPS_IDLE);
262 
263  IUFillBLOB(&FitsB[0], "IMAGE", "Image", "");
264  IUFillBLOBVector(&FitsBP, FitsB, 1, getDefaultName(), "IMAGE", "Image Data", DOWNLOAD_TAB, IP_RO, 60, IPS_IDLE);
265 
266  defineProperty(&GroupCountNP);
267  defineProperty(&ControlledDeviceTP);
268  defineProperty(&ImageNameTP);
269 
270  for (int i = 0; i < GroupCountN[0].value; i++)
271  {
272  groups[i]->defineProperties();
273  }
274 
275  IUFillNumber(&CCDImageExposureN[0], "CCD_EXPOSURE_VALUE", "Duration (s)", "%5.2f", 0, 36000, 0, 1.0);
276  IUFillNumberVector(&CCDImageExposureNP, CCDImageExposureN, 1, ControlledDeviceT[0].text, "CCD_EXPOSURE", "Expose",
278 
279  IUFillNumber(&CCDImageBinN[0], "HOR_BIN", "X", "%2.0f", 1, 4, 1, 1);
280  IUFillNumber(&CCDImageBinN[1], "VER_BIN", "Y", "%2.0f", 1, 4, 1, 1);
281  IUFillNumberVector(&CCDImageBinNP, CCDImageBinN, 2, ControlledDeviceT[0].text, "CCD_BINNING", "Binning",
283 
284  IUFillSwitch(&CCDUploadS[0], "UPLOAD_CLIENT", "Client", ISS_OFF);
285  IUFillSwitch(&CCDUploadS[1], "UPLOAD_LOCAL", "Local", ISS_ON);
286  IUFillSwitch(&CCDUploadS[2], "UPLOAD_BOTH", "Both", ISS_OFF);
287  IUFillSwitchVector(&CCDUploadSP, CCDUploadS, 3, ControlledDeviceT[0].text, "UPLOAD_MODE", "Upload", OPTIONS_TAB,
288  IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
289 
290  IUFillText(&CCDUploadSettingsT[0], "UPLOAD_DIR", "Dir", "");
291  IUFillText(&CCDUploadSettingsT[1], "UPLOAD_PREFIX", "Prefix", IMAGE_PREFIX);
292  IUFillTextVector(&CCDUploadSettingsTP, CCDUploadSettingsT, 2, ControlledDeviceT[0].text, "UPLOAD_SETTINGS",
293  "Upload Settings", OPTIONS_TAB, IP_RW, 60, IPS_IDLE);
294 
295  IUFillNumber(&FilterSlotN[0], "FILTER_SLOT_VALUE", "Filter", "%3.0f", 1.0, 12.0, 1.0, 1.0);
296  IUFillNumberVector(&FilterSlotNP, FilterSlotN, 1, ControlledDeviceT[1].text, "FILTER_SLOT", "Filter Slot",
298 
299  return true;
300 }
301 
303 {
304  if (isConnected())
305  {
306  defineProperty(&StatusLP);
307  ProgressN[0].value = group = 0;
308  ProgressN[1].value = image = 0;
309  ProgressNP.s = IPS_IDLE;
310  defineProperty(&ProgressNP);
311  BatchSP.s = IPS_IDLE;
312  defineProperty(&BatchSP);
313  DownloadN[0].value = 0;
314  DownloadN[1].value = 0;
315  DownloadNP.s = IPS_IDLE;
316  defineProperty(&DownloadNP);
317  FitsBP.s = IPS_IDLE;
318  defineProperty(&FitsBP);
319  }
320  else
321  {
322  deleteProperty(StatusLP.name);
323  deleteProperty(ProgressNP.name);
324  deleteProperty(BatchSP.name);
325  deleteProperty(DownloadNP.name);
326  deleteProperty(FitsBP.name);
327  }
328  return true;
329 }
330 
331 void Imager::ISGetProperties(const char *dev)
332 {
334 }
335 
336 bool Imager::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
337 {
338  if (Imager::DEVICE_NAME == dev)
339  {
340  if (std::string{name} == std::string{GroupCountNP.name})
341  {
342  for (int i = 0; i < maxGroup; i++)
343  groups[i]->deleteProperties();
344  IUUpdateNumber(&GroupCountNP, values, names, n);
345  maxGroup = (int)GroupCountN[0].value;
346  if (maxGroup > MAX_GROUP_COUNT)
347  GroupCountN[0].value = maxGroup = MAX_GROUP_COUNT;
348  for (int i = 0; i < maxGroup; i++)
349  groups[i]->defineProperties();
350  GroupCountNP.s = IPS_OK;
351  IDSetNumber(&GroupCountNP, nullptr);
352  return true;
353  }
354  if (std::string{name} == std::string{DownloadNP.name})
355  {
356  IUUpdateNumber(&DownloadNP, values, names, n);
357  initiateDownload();
358  return true;
359  }
360  if (strncmp(name, GROUP_PREFIX, GROUP_PREFIX_LEN) == 0)
361  {
362  for (int i = 0; i < GroupCountN[0].value; i++)
363  if (groups[i]->ISNewNumber(dev, name, values, names, n))
364  {
365  return true;
366  }
367  return false;
368  }
369  }
370  return DefaultDevice::ISNewNumber(dev, name, values, names, n);
371 }
372 
373 bool Imager::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
374 {
375  if (Imager::DEVICE_NAME == dev)
376  {
377  if (std::string{name} == std::string{BatchSP.name})
378  {
379  for (int i = 0; i < n; i++)
380  {
381  if (strcmp(names[i], BatchS[0].name) == 0 && states[i] == ISS_ON)
382  {
383  if (!isRunning())
384  startBatch();
385  }
386  if (strcmp(names[i], BatchS[1].name) == 0 && states[i] == ISS_ON)
387  {
388  if (isRunning())
389  abortBatch();
390  }
391  }
392  BatchSP.s = IPS_OK;
393  IDSetSwitch(&BatchSP, nullptr);
394  return true;
395  }
396  }
397  return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
398 }
399 
400 bool Imager::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
401 {
402  if (Imager::DEVICE_NAME == dev)
403  {
404  if (std::string{name} == std::string{ControlledDeviceTP.name})
405  {
406  IUUpdateText(&ControlledDeviceTP, texts, names, n);
407  IDSetText(&ControlledDeviceTP, nullptr);
408  strncpy(StatusL[0].label, ControlledDeviceT[0].text, sizeof(StatusL[0].label));
409  strncpy(CCDImageExposureNP.device, ControlledDeviceT[0].text, sizeof(CCDImageExposureNP.device));
410  strncpy(CCDImageBinNP.device, ControlledDeviceT[0].text, sizeof(CCDImageBinNP.device));
411  strncpy(StatusL[1].label, ControlledDeviceT[1].text, sizeof(StatusL[1].label));
412  strncpy(FilterSlotNP.device, ControlledDeviceT[1].text, sizeof(FilterSlotNP.device));
413  return true;
414  }
415  if (std::string{name} == std::string{ImageNameTP.name})
416  {
417  IUUpdateText(&ImageNameTP, texts, names, n);
418  IDSetText(&ImageNameTP, nullptr);
419  return true;
420  }
421  }
422  return INDI::DefaultDevice::ISNewText(dev, name, texts, names, n);
423 }
424 
425 bool Imager::ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[],
426  char *names[], int n)
427 {
428  return INDI::DefaultDevice::ISNewBLOB(dev, name, sizes, blobsizes, blobs, formats, names, n);
429 }
430 
432 {
434 }
435 
437 {
438  setServer("localhost", 7624); // TODO configuration options
439  BaseClient::watchDevice(controlledCCD);
440  BaseClient::watchDevice(controlledFilterWheel);
441  connectServer();
442  setBLOBMode(B_ALSO, controlledCCD, nullptr);
443 
444  return true;
445 }
446 
448 {
449  if (isRunning())
450  abortBatch();
452  return true;
453 }
454 
455 // BaseClient ----------------------------------------------------------------------------
456 
458 {
459  LOG_DEBUG("Server connected");
460  StatusL[0].s = IPS_ALERT;
461  StatusL[1].s = IPS_ALERT;
462  IDSetLight(&StatusLP, nullptr);
463 }
464 
466 {
467  std::string deviceName{baseDevice.getDeviceName()};
468 
469  LOGF_DEBUG("Device %s detected", deviceName.c_str());
470  if (deviceName == controlledCCD)
471  StatusL[0].s = IPS_BUSY;
472  if (deviceName == controlledFilterWheel)
473  StatusL[1].s = IPS_BUSY;
474 
475  IDSetLight(&StatusLP, nullptr);
476 }
477 
479 {
480  std::string deviceName{property.getDeviceName()};
481 
482  if (property.isNameMatch(INDI::SP::CONNECTION))
483  {
484  bool state = INDI::PropertySwitch(property)[0].getState() != ISS_OFF;
485  if (deviceName == controlledCCD)
486  {
487  if (state)
488  {
489  StatusL[0].s = IPS_OK;
490  }
491  else
492  {
493  connectDevice(controlledCCD);
494  LOGF_DEBUG("Connecting %s", controlledCCD);
495  }
496  }
497  if (deviceName == controlledFilterWheel)
498  {
499  if (state)
500  {
501  StatusL[1].s = IPS_OK;
502  }
503  else
504  {
505  connectDevice(controlledFilterWheel);
506  LOGF_DEBUG("Connecting %s", controlledFilterWheel);
507  }
508  }
509  IDSetLight(&StatusLP, nullptr);
510  }
511 }
512 
514 {
515  std::string deviceName{property.getDeviceName()};
516 
517  if (property.getType() == INDI_BLOB)
518  {
519  for (auto &bp: INDI::PropertyBlob(property))
520  {
521  if (ProgressNP.s == IPS_BUSY)
522  {
523  char name[128] = {0};
524  std::ofstream file;
525 
526  strncpy(format, bp.getFormat(), 16);
527  sprintf(name, IMAGE_NAME, ImageNameT[0].text, ImageNameT[1].text, group, image, format);
528  file.open(name, std::ios::out | std::ios::binary | std::ios::trunc);
529  file.write(static_cast<char *>(bp.getBlob()), bp.getBlobLen());
530  file.close();
531  LOGF_DEBUG("Group %d of %d, image %d of %d, saved to %s", group, maxGroup, image, maxImage,
532  name);
533  if (image == maxImage)
534  {
535  if (group == maxGroup)
536  {
537  batchDone();
538  }
539  else
540  {
541  maxImage = nextGroup()->count();
542  ProgressN[0].value = group = group + 1;
543  ProgressN[1].value = image = 1;
544  IDSetNumber(&ProgressNP, nullptr);
545  initiateNextFilter();
546  }
547  }
548  else
549  {
550  ProgressN[1].value = image = image + 1;
551  IDSetNumber(&ProgressNP, nullptr);
552  initiateNextFilter();
553  }
554  }
555  }
556  return;
557  }
558 
559  if (property.isNameMatch(INDI::SP::CONNECTION))
560  {
561  INDI::PropertySwitch propertySwitch{property};
562 
563  bool state = propertySwitch[0].getState() != ISS_OFF;
564  if (deviceName == controlledCCD)
565  {
566  StatusL[0].s = state ? IPS_OK : IPS_BUSY;
567  }
568 
569  if (deviceName == controlledFilterWheel)
570  {
571  StatusL[1].s = state ? IPS_OK : IPS_BUSY;
572  }
573  IDSetLight(&StatusLP, nullptr);
574  return;
575  }
576 
577  if (deviceName == controlledCCD && property.isNameMatch("CCD_EXPOSURE"))
578  {
579  INDI::PropertyNumber propertyNumber{property};
580  ProgressN[2].value = propertyNumber[0].getValue();
581  IDSetNumber(&ProgressNP, nullptr);
582  return;
583  }
584 
585  if (deviceName == controlledFilterWheel && property.isNameMatch("FILTER_SLOT"))
586  {
587  INDI::PropertyNumber propertyNumber{property};
588  FilterSlotN[0].value = propertyNumber[0].getValue();
589  if (property.getState() == IPS_OK)
590  initiateNextCapture();
591  return;
592  }
593 
594  if (deviceName == controlledCCD && property.isNameMatch("CCD_FILE_PATH"))
595  {
596  INDI::PropertyText propertyText(property);
597  char name[128] = {0};
598 
599  strncpy(format, strrchr(propertyText[0].getText(), '.'), sizeof(format));
600  sprintf(name, IMAGE_NAME, ImageNameT[0].text, ImageNameT[1].text, group, image, format);
601  rename(propertyText[0].getText(), name);
602  LOGF_DEBUG("Group %d of %d, image %d of %d, saved to %s", group, maxGroup, image,
603  maxImage, name);
604  if (image == maxImage)
605  {
606  if (group == maxGroup)
607  {
608  batchDone();
609  }
610  else
611  {
612  maxImage = nextGroup()->count();
613  ProgressN[0].value = group = group + 1;
614  ProgressN[1].value = image = 1;
615  IDSetNumber(&ProgressNP, nullptr);
616  initiateNextFilter();
617  }
618  }
619  else
620  {
621  ProgressN[1].value = image = image + 1;
622  IDSetNumber(&ProgressNP, nullptr);
623  initiateNextFilter();
624  }
625  return;
626  }
627 }
628 
629 void Imager::serverDisconnected(int exit_code)
630 {
631  INDI_UNUSED(exit_code);
632  LOG_DEBUG("Server disconnected");
633  StatusL[0].s = IPS_ALERT;
634  StatusL[1].s = IPS_ALERT;
635 }
636 
637 
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
Definition: agent_imager.h:24
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.
Definition: baseclient.cpp:343
bool connectServer() override
Connect to INDI server.
Definition: baseclient.cpp:308
Class to provide basic INDI device functionality.
Definition: basedevice.h:52
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
INDI::PropertyText getText(const char *name) const
Definition: basedevice.cpp:94
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()
Initilize 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.
IPState getState() const
Provides generic container for INDI properties.
Definition: indiproperty.h:48
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
Definition: agent_imager.h:30
virtual bool initProperties() override
Initilize 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.
void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Update the value of an existing switch vector property.
void ISGetProperties(const char *dev)
Get Device Properties.
void ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
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
#define MAXINDIBLOBFMT
Definition: indiapi.h:196
@ IP_RW
Definition: indiapi.h:186
@ IP_RO
Definition: indiapi.h:184
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_1OFMANY
Definition: indiapi.h:173
@ ISR_NOFMANY
Definition: indiapi.h:175
void IUFillLight(ILight *lp, const char *name, const char *label, IPState s)
Assign attributes for a light property. The light's auxiliary elements will be set to NULL.
Definition: indidevapi.c:169
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
void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char *dev, const char *name, const char *label, const char *group, IPState s)
Assign attributes for a light vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidevapi.c:255
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 IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indidevapi.c:36
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 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
void IUFillBLOBVector(IBLOBVectorProperty *bvp, IBLOB *bp, int nbp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a BLOB vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidevapi.c:310
void IUFillBLOB(IBLOB *bp, const char *name, const char *label, const char *format)
Assign attributes for a BLOB property. The BLOB's data and auxiliary elements will be set to NULL.
Definition: indidevapi.c:216
@ B_ALSO
Definition: indidevapi.h:268
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
void IDSetLight(const ILightVectorProperty *lvp, const char *fmt,...)
Definition: indidriver.c:1251
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
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:1362
@ INDI_BLOB
Definition: indidriver.c:61
void IDSetBLOB(const IBLOBVectorProperty *bvp, const char *fmt,...)
Definition: indidriver.c:1287
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1191
#define LOG_DEBUG(txt)
Definition: indilogger.h:75
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
const char * CONNECTION
Connect to and disconnect from device.
char name[MAXINDINAME]
Definition: indiapi.h:475
char name[MAXINDINAME]
Definition: indiapi.h:421
char device[MAXINDIDEVICE]
Definition: indiapi.h:321
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371
char name[MAXINDINAME]
Definition: indiapi.h:250