Instrument Neutral Distributed Interface INDI  2.0.2
snapcap.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2017-2023 Jarno Paananen. All right reserved.
3 
4  Based on Flip Flat driver by:
5 
6  Copyright(c) 2015 Jasem Mutlaq. All rights reserved.
7 
8  This program is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by the Free
10  Software Foundation; either version 2 of the License, or (at your option)
11  any later version.
12 
13  This program is distributed in the hope that it will be useful, but WITHOUT
14  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16  more details.
17 
18  You should have received a copy of the GNU Library General Public License
19  along with this library; see the file COPYING.LIB. If not, write to
20  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  Boston, MA 02110-1301, USA.
22 
23  The full GNU General Public License is included in this distribution in the
24  file called LICENSE.
25 *******************************************************************************/
26 
27 #include "snapcap.h"
28 
29 #include "indicom.h"
31 
32 #include <cerrno>
33 #include <cstring>
34 #include <memory>
35 #include <termios.h>
36 #include <sys/ioctl.h>
37 
38 // We declare an auto pointer to SnapCap.
39 std::unique_ptr<SnapCap> snapcap(new SnapCap());
40 
41 #define SNAP_CMD 7
42 #define SNAP_RES 8 // Includes terminating null
43 #define SNAP_TIMEOUT 3
44 
46 {
47  setVersion(1, 2);
48 }
49 
51 {
53 
54  // Status
55  StatusTP[0].fill("COVER", "Cover", nullptr);
56  StatusTP[1].fill("LIGHT", "Light", nullptr);
57  StatusTP[2].fill("MOTOR", "Motor", nullptr);
58  StatusTP.fill(getDeviceName(), "STATUS", "Status", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);
59 
60  // Firmware version
61  FirmwareTP[0].fill("VERSION", "Version", nullptr);
62  FirmwareTP.fill(getDeviceName(), "FIRMWARE", "Firmware", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);
63 
64  // Abort and force open/close buttons
65  AbortSP[0].fill("ABORT", "Abort", ISS_OFF);
66  AbortSP.fill(getDeviceName(), "ABORT", "Abort", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
67 
68  ForceSP[0].fill("OFF", "Off", ISS_ON);
69  ForceSP[1].fill("ON", "On", ISS_OFF);
70  ForceSP.fill(getDeviceName(), "FORCE", "Force movement", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
71 
74 
75  LightIntensityN[0].min = 0;
76  LightIntensityN[0].max = 255;
77  LightIntensityN[0].step = 10;
78 
79  hasLight = true;
80 
82 
84 
85  serialConnection = new Connection::Serial(this);
86  serialConnection->registerHandshake([&]()
87  {
88  return Handshake();
89  });
90  registerConnection(serialConnection);
92  return true;
93 }
94 
95 void SnapCap::ISGetProperties(const char *dev)
96 {
98 
99  // Get Light box properties
101 }
102 
104 {
106 
107  if (isConnected())
108  {
110  if (hasLight)
111  {
115  }
116  defineProperty(StatusTP);
117  defineProperty(FirmwareTP);
118  defineProperty(AbortSP);
119  defineProperty(ForceSP);
120  getStartupData();
121  }
122  else
123  {
125  if (hasLight)
126  {
130  }
131  deleteProperty(StatusTP);
132  deleteProperty(FirmwareTP);
133  deleteProperty(AbortSP);
134  deleteProperty(ForceSP);
135  }
136 
137  return true;
138 }
139 
141 {
142  return (const char *)"SnapCap";
143 }
144 
145 bool SnapCap::Handshake()
146 {
147  if (isSimulation())
148  {
149  LOGF_INFO("Connected successfully to simulated %s. Retrieving startup data...", getDeviceName());
150 
152  return true;
153  }
154 
155  PortFD = serialConnection->getPortFD();
156 
157  if (!ping())
158  {
159  LOG_ERROR("Device ping failed.");
160  return false;
161  }
162 
163  return true;
164 }
165 
166 bool SnapCap::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
167 {
168  if (!dev || strcmp(dev, getDeviceName()))
169  return false;
170 
171  if (processLightBoxNumber(dev, name, values, names, n))
172  return true;
173 
174  return INDI::DefaultDevice::ISNewNumber(dev, name, values, names, n);
175 }
176 
177 bool SnapCap::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
178 {
179  if (!dev || strcmp(dev, getDeviceName()))
180  return false;
181 
182  if (processLightBoxText(dev, name, texts, names, n))
183  return true;
184 
185  return INDI::DefaultDevice::ISNewText(dev, name, texts, names, n);
186 }
187 
188 bool SnapCap::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
189 {
190  if (!dev || strcmp(dev, getDeviceName()))
191  return false;
192 
193  if (AbortSP.isNameMatch(name))
194  {
195  AbortSP.reset();
196  AbortSP.setState(Abort());
197  AbortSP.apply();
198  return true;
199  }
200  if (ForceSP.isNameMatch(name))
201  {
202  AbortSP.update(states, names, n);
203  AbortSP.apply();
204  return true;
205  }
206 
207  if (processDustCapSwitch(dev, name, states, names, n))
208  return true;
209 
210  if (processLightBoxSwitch(dev, name, states, names, n))
211  return true;
212 
213  return INDI::DefaultDevice::ISNewSwitch(dev, name, states, names, n);
214 }
215 
217 {
218  snoopLightBox(root);
219 
221 }
222 
224 {
226 
227  return saveLightBoxConfigItems(fp);
228 }
229 
230 bool SnapCap::ping()
231 {
232  bool found = getFirmwareVersion();
233  // Sometimes the controller does a corrupt reply at first connect
234  // so retry once just in case
235  if (!found)
236  found = getFirmwareVersion();
237  return found;
238 }
239 
240 bool SnapCap::sendCommand(const char *command, char *response)
241 {
242  int nbytes_written = 0, nbytes_read = 0, rc = -1;
243  char errstr[MAXRBUF];
244 
245  tcflush(PortFD, TCIOFLUSH);
246 
247  LOGF_DEBUG("CMD (%s)", command);
248 
249  char buffer[SNAP_CMD + 1]; // space for terminating null
250  snprintf(buffer, SNAP_CMD + 1, "%s\r\n", command);
251 
252  if ((rc = tty_write(PortFD, buffer, SNAP_CMD, &nbytes_written)) != TTY_OK)
253  {
254  tty_error_msg(rc, errstr, MAXRBUF);
255  LOGF_ERROR("%s error: %s.", command, errstr);
256  return false;
257  }
258 
259  if ((rc = tty_nread_section(PortFD, response, SNAP_RES, '\n', SNAP_TIMEOUT, &nbytes_read)) != TTY_OK)
260  {
261  tty_error_msg(rc, errstr, MAXRBUF);
262  LOGF_ERROR("%s: %s.", command, errstr);
263  return false;
264  }
265 
266  response[nbytes_read - 2] = 0; // strip \r\n
267 
268  LOGF_DEBUG("RES (%s)", response);
269  return true;
270 }
271 
272 bool SnapCap::getStartupData()
273 {
274  bool rc1 = getFirmwareVersion();
275  bool rc2 = getStatus();
276  bool rc3 = getBrightness();
277 
278  return (rc1 && rc2 && rc3);
279 }
280 
282 {
283  if (isSimulation())
284  {
285  simulationWorkCounter = 3;
286  return IPS_BUSY;
287  }
288 
289  char command[SNAP_CMD];
290  char response[SNAP_RES];
291 
292  if (ForceSP[1].getState() == ISS_ON)
293  strncpy(command, ">c000", SNAP_CMD); // Force close command
294  else
295  strncpy(command, ">C000", SNAP_CMD);
296 
297  if (!sendCommand(command, response))
298  return IPS_ALERT;
299 
300  if (strcmp(response, "*C000") == 0 || strcmp(response, "*c000") == 0)
301  {
302  // Set cover status to random value outside of range to force it to refresh
303  prevCoverStatus = 10;
304  targetCoverStatus = 2;
305  return IPS_BUSY;
306  }
307  else
308  return IPS_ALERT;
309 }
310 
312 {
313  if (isSimulation())
314  {
315  simulationWorkCounter = 3;
316  return IPS_BUSY;
317  }
318 
319  char command[SNAP_CMD];
320  char response[SNAP_RES];
321 
322  if (ForceSP[1].getState() == ISS_ON)
323  strncpy(command, ">o000", SNAP_CMD); // Force open command
324  else
325  strncpy(command, ">O000", SNAP_CMD);
326 
327  if (!sendCommand(command, response))
328  return IPS_ALERT;
329 
330  if (strcmp(response, "*O000") == 0 || strcmp(response, "*o000") == 0)
331  {
332  // Set cover status to random value outside of range to force it to refresh
333  prevCoverStatus = 10;
334  targetCoverStatus = 1;
335  return IPS_BUSY;
336  }
337  else
338  return IPS_ALERT;
339 }
340 
341 IPState SnapCap::Abort()
342 {
343  if (isSimulation())
344  {
345  simulationWorkCounter = 0;
346  return IPS_OK;
347  }
348 
349  char response[SNAP_RES];
350 
351  if (!sendCommand(">A000", response))
352  return IPS_ALERT;
353 
354  if (strcmp(response, "*A000") == 0)
355  {
356  // Set cover status to random value outside of range to force it to refresh
357  prevCoverStatus = 10;
358  return IPS_OK;
359  }
360  else
361  return IPS_ALERT;
362 }
363 
364 bool SnapCap::EnableLightBox(bool enable)
365 {
366  char command[SNAP_CMD];
367  char response[SNAP_RES];
368 
369  if (isSimulation())
370  return true;
371 
372  if (enable)
373  strncpy(command, ">L000", SNAP_CMD);
374  else
375  strncpy(command, ">D000", SNAP_CMD);
376 
377  if (!sendCommand(command, response))
378  return false;
379 
380  char expectedResponse[SNAP_RES];
381  if (enable)
382  snprintf(expectedResponse, SNAP_RES, "*L000");
383  else
384  snprintf(expectedResponse, SNAP_RES, "*D000");
385 
386  if (strcmp(response, expectedResponse) == 0)
387  return true;
388 
389  return false;
390 }
391 
392 bool SnapCap::getStatus()
393 {
394  char response[SNAP_RES];
395 
396  if (isSimulation())
397  {
398  if (ParkCapSP.s == IPS_BUSY && --simulationWorkCounter <= 0)
399  {
400  ParkCapSP.s = IPS_IDLE;
401  IDSetSwitch(&ParkCapSP, nullptr);
402  simulationWorkCounter = 0;
403  }
404 
405  if (ParkCapSP.s == IPS_BUSY)
406  {
407  response[2] = '1';
408  response[4] = '0';
409  }
410  else
411  {
412  response[2] = '0';
413  // Parked/Closed
414  if (ParkCapS[CAP_PARK].s == ISS_ON)
415  response[4] = '2';
416  else
417  response[4] = '1';
418  }
419 
420  response[3] = (LightS[FLAT_LIGHT_ON].s == ISS_ON) ? '1' : '0';
421  }
422  else
423  {
424  if (!sendCommand(">S000", response))
425  return false;
426  }
427 
428  char motorStatus = response[2] - '0';
429  char lightStatus = response[3] - '0';
430  char coverStatus = response[4] - '0';
431 
432  // Force cover status as it doesn't reflect moving state otherwise...
433  if (motorStatus)
434  {
435  coverStatus = 0;
436  }
437  bool statusUpdated = false;
438 
439  if (coverStatus != prevCoverStatus)
440  {
441  prevCoverStatus = coverStatus;
442 
443  statusUpdated = true;
444 
445  switch (coverStatus)
446  {
447  case 0:
448  StatusTP[0].setText("Opening/closing");
449  break;
450 
451  case 1:
452  if ((targetCoverStatus == 1 && ParkCapSP.s == IPS_BUSY) || ParkCapSP.s == IPS_IDLE)
453  {
454  StatusTP[0].setText("Open");
457  ParkCapSP.s = IPS_OK;
458  LOG_INFO("Cover open.");
459  IDSetSwitch(&ParkCapSP, nullptr);
460  }
461  break;
462 
463  case 2:
464  if ((targetCoverStatus == 2 && ParkCapSP.s == IPS_BUSY) || ParkCapSP.s == IPS_IDLE)
465  {
466  StatusTP[0].setText("Closed");
468  ParkCapS[CAP_PARK].s = ISS_ON;
469  ParkCapSP.s = IPS_OK;
470  LOG_INFO("Cover closed.");
471  IDSetSwitch(&ParkCapSP, nullptr);
472  }
473  break;
474 
475  case 3:
476  StatusTP[0].setText("Timed out");
477  break;
478 
479  case 4:
480  StatusTP[0].setText("Open circuit");
481  break;
482 
483  case 5:
484  StatusTP[0].setText("Overcurrent");
485  break;
486 
487  case 6:
488  StatusTP[0].setText("User abort");
489  break;
490  }
491  }
492 
493  if (lightStatus != prevLightStatus)
494  {
495  prevLightStatus = lightStatus;
496 
497  statusUpdated = true;
498 
499  switch (lightStatus)
500  {
501  case 0:
502  StatusTP[1].setText("Off");
503  if (LightS[0].s == ISS_ON)
504  {
505  LightS[0].s = ISS_OFF;
506  LightS[1].s = ISS_ON;
507  IDSetSwitch(&LightSP, nullptr);
508  }
509  break;
510 
511  case 1:
512  StatusTP[1].setText("On");
513  if (LightS[1].s == ISS_ON)
514  {
515  LightS[0].s = ISS_ON;
516  LightS[1].s = ISS_OFF;
517  IDSetSwitch(&LightSP, nullptr);
518  }
519  break;
520  }
521  }
522 
523  if (motorStatus != prevMotorStatus)
524  {
525  prevMotorStatus = motorStatus;
526 
527  statusUpdated = true;
528 
529  switch (motorStatus)
530  {
531  case 0:
532  StatusTP[2].setText("Stopped");
533  break;
534 
535  case 1:
536  StatusTP[2].setText("Running");
537  break;
538  }
539  }
540 
541  if (statusUpdated)
542  StatusTP.apply();
543 
544  return true;
545 }
546 
547 bool SnapCap::getFirmwareVersion()
548 {
549  if (isSimulation())
550  {
551  FirmwareTP[0].setText("Ssimulation");
552  FirmwareTP.apply();
553  return true;
554  }
555 
556  char response[SNAP_RES];
557 
558  if (!sendCommand(">V000", response))
559  return false;
560 
561  char versionString[4] = { 0 };
562  snprintf(versionString, 4, "%s", response + 2);
563  FirmwareTP[0].setText(versionString);
564  FirmwareTP.apply();
565 
566  return true;
567 }
568 
570 {
571  if (!isConnected())
572  return;
573 
574  getStatus();
575 
577 }
578 
579 bool SnapCap::getBrightness()
580 {
581  if (isSimulation())
582  {
583  return true;
584  }
585 
586  char response[SNAP_RES];
587 
588  if (!sendCommand(">J000", response))
589  return false;
590 
591  int brightnessValue = 0;
592  int rc = sscanf(response, "*J%d", &brightnessValue);
593 
594  if (rc <= 0)
595  {
596  LOGF_ERROR("Unable to parse brightness value (%s)", response);
597  return false;
598  }
599 
600  if (brightnessValue != prevBrightness)
601  {
602  prevBrightness = brightnessValue;
603  LightIntensityN[0].value = brightnessValue;
604  IDSetNumber(&LightIntensityNP, nullptr);
605  }
606 
607  return true;
608 }
609 
610 bool SnapCap::SetLightBoxBrightness(uint16_t value)
611 {
612  if (isSimulation())
613  {
614  LightIntensityN[0].value = value;
615  IDSetNumber(&LightIntensityNP, nullptr);
616  return true;
617  }
618 
619  char command[SNAP_CMD];
620  char response[SNAP_RES];
621 
622  snprintf(command, SNAP_CMD, ">B%03d", value);
623 
624  if (!sendCommand(command, response))
625  return false;
626 
627  int brightnessValue = 0;
628  int rc = sscanf(response, "*B%d", &brightnessValue);
629 
630  if (rc <= 0)
631  {
632  LOGF_ERROR("Unable to parse brightness value (%s)", response);
633  return false;
634  }
635 
636  if (brightnessValue != prevBrightness)
637  {
638  prevBrightness = brightnessValue;
639  LightIntensityN[0].value = brightnessValue;
640  IDSetNumber(&LightIntensityNP, nullptr);
641  }
642 
643  return true;
644 }
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the intial connection to the device...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
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 saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function.
bool isSimulation() const
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
void initDustCapProperties(const char *deviceName, const char *groupName)
Initilize dust cap properties. It is recommended to call this function within initProperties() of you...
bool processDustCapSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process dust cap switch properties.
ISwitchVectorProperty ParkCapSP
INumberVectorProperty LightIntensityNP
bool processLightBoxNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process light box number properties.
ISwitchVectorProperty LightSP
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...
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
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool isNameMatch(const char *otherName) const
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)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
Provides interface to implement controllable light box/switch device.
virtual IPState UnParkCap() override
unPark dust cap (open cover). Must be implemented by child.
Definition: snapcap.cpp:311
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: snapcap.cpp:50
virtual bool ISSnoopDevice(XMLEle *root) override
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
Definition: snapcap.cpp:216
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...
Definition: snapcap.cpp:95
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: snapcap.cpp:166
virtual bool SetLightBoxBrightness(uint16_t value) override
setBrightness Set light level. Must be impelemented in the child class, if supported.
Definition: snapcap.cpp:610
virtual IPState ParkCap() override
Park dust cap (close cover). Must be implemented by child.
Definition: snapcap.cpp:281
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: snapcap.cpp:569
virtual bool EnableLightBox(bool enable) override
EnableLightBox Turn on/off on a light box. Must be impelemented in the child class.
Definition: snapcap.cpp:364
SnapCap()
Definition: snapcap.cpp:45
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: snapcap.cpp:188
const char * getDefaultName() override
Definition: snapcap.cpp:140
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: snapcap.cpp:103
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
Definition: snapcap.cpp:177
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: snapcap.cpp:223
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
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
@ IP_RO
Definition: indiapi.h:184
IPState
Property state.
Definition: indiapi.h:160
@ 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
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition: indicom.c:424
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1167
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:666
Implementations for common driver routines.
@ TTY_OK
Definition: indicom.h:150
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indidevapi.c:148
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
#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 LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
#define LOG_INFO(txt)
Definition: indilogger.h:74
#define MAXRBUF
Definition: indiserver.cpp:102
std::vector< uint8_t > buffer
#define SNAP_TIMEOUT
Definition: snapcap.cpp:43
std::unique_ptr< SnapCap > snapcap(new SnapCap())
#define SNAP_CMD
Definition: snapcap.cpp:41
#define SNAP_RES
Definition: snapcap.cpp:42
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371