Instrument Neutral Distributed Interface INDI  2.0.2
xagyl_wheel.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2020 Jasem Mutlaq. All rights reserved.
3  Copyright(c) 2020 Justin Husted.
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 "xagyl_wheel.h"
21 #include "indicom.h"
22 
23 #include <cstring>
24 #include <cassert>
25 #include <memory>
26 #include <regex>
27 #include <termios.h>
28 
29 static std::unique_ptr<XAGYLWheel> xagylWheel(new XAGYLWheel());
30 
35 {
36  setVersion(0, 3);
37 
39 
41 }
42 
47 {
48  delete[] OffsetN;
49 }
50 
55 {
56  return "XAGYL Wheel";
57 }
58 
63 {
65 
66  // Firmware info
67  IUFillText(&FirmwareInfoT[FIRMWARE_PRODUCT], "FIRMWARE_PRODUCT", "Product",
68  nullptr);
69  IUFillText(&FirmwareInfoT[FIRMWARE_VERSION], "FIRMWARE_VERSION", "Version",
70  nullptr);
71  IUFillText(&FirmwareInfoT[FIRMWARE_SERIAL], "FIRMWARE_SERIAL", "Serial #",
72  nullptr);
73  IUFillTextVector(&FirmwareInfoTP, FirmwareInfoT, 3, getDeviceName(),
74  "Info", "Info", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);
75 
76  // Settings
77  IUFillNumber(&SettingsN[SETTING_SPEED], "SETTING_SPEED", "Speed", "%.f",
78  0, 100, 10., 0.);
79  IUFillNumber(&SettingsN[SETTING_JITTER], "SETTING_JITTER", "Jitter", "%.f",
80  1, 10, 1., 0.);
81  IUFillNumber(&SettingsN[SETTING_THRESHOLD], "SETTING_THRESHOLD",
82  "Threshold", "%.f", 10, 30, 1., 0.);
83  IUFillNumber(&SettingsN[SETTING_PW], "SETTING_PW", "Pulse", "%.f",
84  100, 10000, 100., 0.);
85  IUFillNumberVector(&SettingsNP, SettingsN, 4, getDeviceName(), "Settings",
86  "Settings", SETTINGS_TAB, IP_RW, 0, IPS_IDLE);
87 
88  // Reset
89  IUFillSwitch(&ResetS[COMMAND_REBOOT], "COMMAND_REBOOT", "Reboot", ISS_OFF);
90  IUFillSwitch(&ResetS[COMMAND_INIT], "COMMAND_INIT", "Initialize", ISS_OFF);
91  IUFillSwitch(&ResetS[COMMAND_CLEAR_CALIBRATION],
92  "COMMAND_CLEAR_CALIBRATION Calibration", "Clear Calibration",
93  ISS_OFF);
94  IUFillSwitch(&ResetS[COMMAND_PERFORM_CALIBRAITON],
95  "COMMAND_PERFORM_CALIBRAITON", "Perform Calibration", ISS_OFF);
96  IUFillSwitchVector(&ResetSP, ResetS, 4, getDeviceName(),
97  "Commands", "Commands", MAIN_CONTROL_TAB, IP_RW,
98  ISR_ATMOST1, 0, IPS_IDLE);
99 
100  addAuxControls();
101 
102  return true;
103 }
104 
109 {
111 
112  if (isConnected())
113  {
114  getStartupData();
115 
116  defineProperty(&ResetSP);
117  defineProperty(&OffsetNP);
118  defineProperty(&FirmwareInfoTP);
119  defineProperty(&SettingsNP);
120  }
121  else
122  {
123  deleteProperty(ResetSP.name);
124  deleteProperty(OffsetNP.name);
125  deleteProperty(FirmwareInfoTP.name);
126  deleteProperty(SettingsNP.name);
127  }
128 
129  return true;
130 }
131 
136 {
137  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
138 
139  tcflush(PortFD, TCIOFLUSH);
140 
141  snprintf(cmd, DRIVER_LEN, "I%d", INFO_FIRMWARE_VERSION);
142  if (!sendCommand(cmd, res))
143  return false;
144 
145  int firmware_version = 0;
146  int fw_rc = sscanf(res, "%d", &firmware_version);
147 
148  if (fw_rc != 1)
149  fw_rc = sscanf(res, "FW %d", &firmware_version);
150 
151  if (fw_rc <= 0)
152  {
153  LOGF_ERROR("Unable to parse response <%s>", res);
154  return false;
155  }
156 
157  m_FirmwareVersion = firmware_version;
158 
159  // We don't have pulse width for version < 3
160  SettingsNP.nnp = 4;
161  if (m_FirmwareVersion < 3)
162  SettingsNP.nnp = 3;
163 
164  bool rc = getMaxFilterSlots();
165  if (!rc)
166  {
167  LOG_ERROR("Unable to parse max filter slots.");
168  return false;
169  }
170 
171  initOffset();
172 
173  rc = getFilterPosition();
174  if (!rc)
175  {
176  LOG_ERROR("Unable to initialize filter position.");
177  return false;
178  }
179 
180  LOG_INFO("XAGYL is online. Getting filter parameters...");
181 
182  return true;
183 }
184 
188 bool XAGYLWheel::ISNewSwitch(const char *dev, const char *name, ISState *states,
189  char *names[], int n)
190 {
191  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
192  {
193  if (strcmp(ResetSP.name, name) == 0)
194  {
195  IUUpdateSwitch(&ResetSP, states, names, n);
196  int command = IUFindOnSwitchIndex(&ResetSP);
197  IUResetSwitch(&ResetSP);
198 
199  switch (command)
200  {
201  case COMMAND_REBOOT:
202  LOG_INFO("Executing hard reboot...");
203  break;
204 
205  case COMMAND_INIT:
206  LOG_INFO("Restarting and moving to filter position #1...");
207  break;
208 
209  case COMMAND_CLEAR_CALIBRATION:
210  LOG_INFO("Calibration removed.");
211  break;
212 
213  case COMMAND_PERFORM_CALIBRAITON:
214  LOG_INFO("Calibrating...");
215  break;
216  }
217 
218  bool rc = reset(command);
219  if (rc)
220  LOG_INFO("Done.");
221  else
222  LOG_ERROR("Error. Please reset device.");
223 
224  ResetSP.s = rc ? IPS_OK : IPS_ALERT;
225  IDSetSwitch(&ResetSP, nullptr);
226 
227  return true;
228  }
229  }
230 
231  return INDI::FilterWheel::ISNewSwitch(dev, name, states, names, n);
232 }
233 
237 bool XAGYLWheel::ISNewNumber(const char *dev, const char *name, double values[],
238  char *names[], int n)
239 {
240  if (!(dev != nullptr && strcmp(dev, getDeviceName()) == 0))
241  return INDI::FilterWheel::ISNewNumber(dev, name, values, names, n);
242 
243  // Handle Offsets
244  if (strcmp(OffsetNP.name, name) == 0)
245  {
246  // Setting offsets changes the current filter.
247  int origFiler = CurrentFilter;
248  bool rc_offset = true;
249 
250  for (int i = 0; i < n; i++)
251  {
252  if (0 != strcmp(names[i], OffsetN[i].name))
253  continue;
254 
255  int newOffset = values[i];
256  int curOffset = OffsetN[i].value;
257 
258  if (newOffset != curOffset)
259  rc_offset &= setOffset(i + 1, newOffset - curOffset);
260  }
261 
262  OffsetNP.s = rc_offset ? IPS_OK : IPS_ALERT;
263  IDSetNumber(&OffsetNP, nullptr);
264 
265  // Return filter to original position.
266  if (!SelectFilter(origFiler))
267  return false;
268 
269  return true;
270  }
271 
272  // Handle Speed, Jitter, Threshold, Pulse width
273  if (strcmp(SettingsNP.name, name) == 0)
274  {
275  int newSpeed = -1, newJitter = -1, newThreshold = -1,
276  newPulseWidth = -1;
277 
278  for (int i = 0; i < n; i++)
279  {
280  if (!strcmp(names[i], SettingsN[SET_SPEED].name))
281  newSpeed = values[i];
282  if (!strcmp(names[i], SettingsN[SET_JITTER].name))
283  newJitter = values[i];
284  if (!strcmp(names[i], SettingsN[SET_THRESHOLD].name))
285  newThreshold = values[i];
286  if (!strcmp(names[i], SettingsN[SET_PULSE_WITDH].name))
287  newPulseWidth = values[i];
288  }
289 
290  bool rc_speed = true, rc_jitter = true, rc_threshold = true,
291  rc_pulsewidth = true;
292 
293  // Speed
294  if (newSpeed >= 0)
295  {
296  rc_speed = setMaximumSpeed(newSpeed);
297  getMaximumSpeed();
298  }
299 
300  // Jitter
301  if (newJitter >= 0)
302  {
303  int curJitter = SettingsN[SET_JITTER].value;
304  rc_jitter &= setRelativeCommand(SET_JITTER, newJitter - curJitter);
305  getJitter();
306  }
307 
308  // Threshold
309  if (newThreshold >= 0)
310  {
311  int curThreshold = SettingsN[SET_THRESHOLD].value;
312  rc_threshold &= setRelativeCommand(SET_THRESHOLD,
313  newThreshold - curThreshold);
314  getThreshold();
315  }
316 
317  // Pulse width
318  if (m_FirmwareVersion >= 3 && newPulseWidth >= 0)
319  {
320  int curPulseWidth = SettingsN[SET_PULSE_WITDH].value;
321  rc_pulsewidth &= setRelativeCommand(SET_PULSE_WITDH, (newPulseWidth - curPulseWidth) / 100.0);
322  getPulseWidth();
323  }
324 
325  if (rc_speed && rc_jitter && rc_threshold && rc_pulsewidth)
326  SettingsNP.s = IPS_OK;
327  else
328  SettingsNP.s = IPS_ALERT;
329 
330  IDSetNumber(&SettingsNP, nullptr);
331 
332  return true;
333  }
334 
335  return INDI::FilterWheel::ISNewNumber(dev, name, values, names, n);
336 }
337 
341 void XAGYLWheel::initOffset()
342 {
343  delete [] OffsetN;
344  OffsetN = new INumber[static_cast<uint8_t>(FilterSlotN[0].max)];
345  char offsetName[MAXINDINAME], offsetLabel[MAXINDILABEL];
346  for (int i = 0; i < FilterSlotN[0].max; i++)
347  {
348  snprintf(offsetName, MAXINDINAME, "OFFSET_%d", i + 1);
349  snprintf(offsetLabel, MAXINDINAME, "#%d Offset", i + 1);
350  IUFillNumber(OffsetN + i, offsetName, offsetLabel, "%.f", -9, 9, 1, 0);
351  }
352 
353  IUFillNumberVector(&OffsetNP, OffsetN, FilterSlotN[0].max, getDeviceName(),
354  "Offsets", "", FILTER_TAB, IP_RW, 0, IPS_IDLE);
355 }
356 
361 bool XAGYLWheel::setMaximumSpeed(int value)
362 {
363  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
364  snprintf(cmd, DRIVER_LEN, "S%X", value / 10);
365  return sendCommand(cmd, res);
366 }
367 
374 bool XAGYLWheel::setRelativeCommand(SET_COMMAND command, int shift)
375 {
376  if (shift == 0)
377  return true;
378 
379  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
380  switch (command)
381  {
382  case SET_JITTER:
383  snprintf(cmd, DRIVER_LEN, "%s0", shift > 0 ? "]" : "[");
384  break;
385 
386  case SET_THRESHOLD:
387  snprintf(cmd, DRIVER_LEN, "%s0", shift > 0 ? "}" : "{");
388  break;
389 
390  case SET_PULSE_WITDH:
391  snprintf(cmd, DRIVER_LEN, "%s0", shift > 0 ? "M" : "N");
392  break;
393 
394  default:
395  assert(false);
396  }
397 
398  for (int i = 0; i < std::abs(shift); ++i)
399  {
400  if (!sendCommand(cmd, res))
401  return false;
402  }
403 
404  return true;
405 }
406 
411 {
412  // The wheel does not return a response when setting the value to the
413  // current number.
414  if (CurrentFilter == f)
415  {
417  return true;
418  }
419 
420  // The wheel moves to a new position, and responds with one line or two.
421  // On success, the first line will be P#. On failure, it is an ERROR.
422  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
423  snprintf(cmd, DRIVER_LEN, "G%X", f);
424  if (!sendCommand(cmd, res))
425  return false;
426 
427  // On success, the wheel may also return an ERROR on a second line.
428  char opt[DRIVER_LEN] = {0};
429  if (!receiveResponse(opt, true))
430  return false;
431 
432  if (!getFilterPosition())
433  return false;
434 
436 
437  return true;
438 
439 }
440 
444 bool XAGYLWheel::getStartupData()
445 {
446  bool rc1 = getFirmwareInfo();
447 
448  bool rc2 = getSettingInfo();
449 
450  for (int i = 0; i < OffsetNP.nnp; i++)
451  getOffset(i);
452 
453  return (rc1 && rc2);
454 }
455 
459 bool XAGYLWheel::getFirmwareInfo()
460 {
461  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
462 
463  // Product
464  snprintf(cmd, DRIVER_LEN, "I%d", INFO_PRODUCT_NAME);
465  if (!sendCommand(cmd, res))
466  return false;
467  IUSaveText(&FirmwareInfoT[FIRMWARE_PRODUCT], res);
468 
469  // Version
470  snprintf(cmd, DRIVER_LEN, "I%d", INFO_FIRMWARE_VERSION);
471  if (!sendCommand(cmd, res))
472  return false;
473  IUSaveText(&FirmwareInfoT[FIRMWARE_VERSION], res);
474 
475  // Serial Number
476  snprintf(cmd, DRIVER_LEN, "I%d", INFO_SERIAL_NUMBER);
477  if (!sendCommand(cmd, res))
478  return false;
479  IUSaveText(&FirmwareInfoT[FIRMWARE_SERIAL], res);
480 
481  return true;
482 }
483 
487 bool XAGYLWheel::getSettingInfo()
488 {
489  bool rc1 = getMaximumSpeed();
490  bool rc2 = getJitter();
491  bool rc3 = getThreshold();
492  bool rc4 = true;
493 
494  if (m_FirmwareVersion >= 3)
495  rc4 = getPulseWidth();
496 
497  return (rc1 && rc2 && rc3 && rc4);
498 }
499 
503 bool XAGYLWheel::getFilterPosition()
504 {
505  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
506  snprintf(cmd, DRIVER_LEN, "I%d", INFO_FILTER_POSITION);
507  if (!sendCommand(cmd, res))
508  return false;
509 
510  int rc = sscanf(res, "P%d", &CurrentFilter);
511 
512  if (rc > 0)
513  {
514  FilterSlotN[0].value = CurrentFilter;
515  return true;
516  }
517  else
518  return false;
519 }
520 
524 bool XAGYLWheel::getMaximumSpeed()
525 {
526  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
527  snprintf(cmd, DRIVER_LEN, "I%d", INFO_MAX_SPEED);
528  if (!sendCommand(cmd, res))
529  return false;
530 
531  int maxSpeed = 0;
532  int rc = sscanf(res, "MaxSpeed %d%%", &maxSpeed);
533  if (rc > 0)
534  {
535  SettingsN[SET_SPEED].value = maxSpeed;
536  return true;
537  }
538  return false;
539 }
540 
544 bool XAGYLWheel::getJitter()
545 {
546  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
547  snprintf(cmd, DRIVER_LEN, "I%d", INFO_JITTER);
548  if (!sendCommand(cmd, res))
549  return false;
550 
551  int jitter = 0;
552  int rc = sscanf(res, "Jitter %d", &jitter);
553 
554  if (rc > 0)
555  {
556  SettingsN[SET_JITTER].value = jitter;
557  return true;
558  }
559  return false;
560 }
561 
565 bool XAGYLWheel::getThreshold()
566 {
567  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
568  snprintf(cmd, DRIVER_LEN, "I%d", INFO_THRESHOLD);
569  if (!sendCommand(cmd, res))
570  return false;
571 
572  int threshold = 0;
573  int rc = sscanf(res, "Threshold %d", &threshold);
574 
575  if (rc > 0)
576  {
577  SettingsN[SET_THRESHOLD].value = threshold;
578  return true;
579  }
580  return false;
581 }
582 
586 bool XAGYLWheel::getPulseWidth()
587 {
588  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
589  snprintf(cmd, DRIVER_LEN, "I%d", INFO_PULSE_WIDTH);
590  if (!sendCommand(cmd, res))
591  return false;
592 
593  int pulseWidth = 0;
594  int rc = sscanf(res, "PulseWidth %duS", &pulseWidth);
595 
596  if (rc > 0)
597  {
598  SettingsN[SET_PULSE_WITDH].value = pulseWidth;
599  return true;
600  }
601  return false;
602 }
603 
607 bool XAGYLWheel::getMaxFilterSlots()
608 {
609  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
610  snprintf(cmd, DRIVER_LEN, "I%d", INFO_MAX_SLOTS);
611  if (!sendCommand(cmd, res))
612  return false;
613 
614  int maxFilterSlots = 0;
615  int rc = sscanf(res, "FilterSlots %d", &maxFilterSlots);
616 
617  if (rc > 0)
618  {
619  FilterSlotN[0].max = maxFilterSlots;
620  return true;
621  }
622  return false;
623 }
624 
642 bool XAGYLWheel::reset(int command)
643 {
644  char cmd[DRIVER_LEN] = {0}, resbuf[DRIVER_LEN] = {0};
645  char *res = resbuf;
646 
647  int value = command;
648  if (command == COMMAND_PERFORM_CALIBRAITON)
649  {
650  value = 6;
651  res = nullptr;
652  }
653 
654  snprintf(cmd, DRIVER_LEN, "R%d", value);
655  if (!sendCommand(cmd, res))
656  return false;
657 
658  // Wait for P1 on relevant commands.
659  if (command == COMMAND_REBOOT || command == COMMAND_INIT)
660  {
661  do
662  {
663  if (!receiveResponse(res))
664  return false;
665  }
666  while (0 != strcmp(res, "P1"));
667  }
668 
669  getFilterPosition();
670  getStartupData();
671 
672  return true;
673 }
674 
683 bool XAGYLWheel::setOffset(int filter, int shift)
684 {
685  if (!SelectFilter(filter))
686  return false;
687 
688  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
689  snprintf(cmd, DRIVER_LEN, "%s0", shift > 0 ? "(" : ")");
690 
691  // Set filter offset.
692  for (int i = 0; i < std::abs(shift); ++i)
693  {
694  res[0] = 0;
695  if (!sendCommand(cmd, res))
696  return false;
697  }
698 
699  // Update filter offset based on result.
700  int filter_num = 0, offset = 0;
701  int rc = sscanf(res, "P%d Offset %d", &filter_num, &offset);
702 
703  if (rc > 0)
704  {
705  OffsetN[filter_num - 1].value = offset;
706  return true;
707  }
708  else
709  return false;
710 }
711 
715 bool XAGYLWheel::getOffset(int filter)
716 {
717  char cmd[DRIVER_LEN] = {0}, res[DRIVER_LEN] = {0};
718  snprintf(cmd, DRIVER_LEN, "O%d", filter + 1);
719  if (!sendCommand(cmd, res))
720  return false;
721 
722  int filter_num = 0, offset = 0;
723  int rc = sscanf(res, "P%d Offset %d", &filter_num, &offset);
724 
725  if (rc > 0)
726  {
727  OffsetN[filter_num - 1].value = offset;
728  return true;
729  }
730  else
731  return false;
732 }
733 
738 {
740 
741  IUSaveConfigNumber(fp, &SettingsNP);
742  if (OffsetN != nullptr)
743  IUSaveConfigNumber(fp, &OffsetNP);
744 
745  return true;
746 }
747 
751 bool XAGYLWheel::receiveResponse(char * res, bool optional)
752 {
753  int nbytes_read = 0, rc = -1;
754 
755  int timeout = optional ? OPTIONAL_TIMEOUT : DRIVER_TIMEOUT;
756  rc = tty_nread_section(PortFD, res, DRIVER_LEN, DRIVER_STOP_CHAR,
757  timeout, &nbytes_read);
758  if (optional && rc == TTY_TIME_OUT)
759  {
760  res[0] = '\0';
761  LOG_DEBUG("RES (optional): not found.");
762  return true;
763  }
764  else if (rc != TTY_OK)
765  {
766  char errstr[MAXRBUF] = {0};
767  tty_error_msg(rc, errstr, MAXRBUF);
768  LOGF_ERROR("Serial read error: %s.", errstr);
769  return false;
770  }
771 
772  // Remove extra \r
773  assert(nbytes_read > 1);
774  res[nbytes_read - 2] = 0;
775 
776  // If the response starts with "ERROR" the command failed.
777  if (0 == strncmp(res, "ERROR", 5))
778  {
779  LOGF_WARN("Device error: %s", res);
780  if (!optional)
781  return false;
782  }
783  else
784  LOGF_DEBUG("RES <%s>", res);
785 
786  return true;
787 }
788 
792 bool XAGYLWheel::sendCommand(const char * cmd, char * res)
793 {
794  int nbytes_written = 0, rc = -1;
795 
796  tcflush(PortFD, TCIOFLUSH);
797 
798  // Send
799  LOGF_DEBUG("CMD <%s>", cmd);
800  rc = tty_write_string(PortFD, cmd, &nbytes_written);
801 
802  if (rc != TTY_OK)
803  {
804  char errstr[MAXRBUF] = {0};
805  tty_error_msg(rc, errstr, MAXRBUF);
806  LOGF_ERROR("Serial write error: %s.", errstr);
807  return false;
808  }
809 
810  // Receive
811  if (!res)
812  return true;
813 
814  return receiveResponse(res);
815 }
816 
820 void XAGYLWheel::hexDump(char * buf, const char * data, int size)
821 {
822  for (int i = 0; i < size; i++)
823  sprintf(buf + 3 * i, "%02X ", static_cast<uint8_t>(data[i]));
824 
825  if (size > 0)
826  buf[3 * size - 1] = '\0';
827 }
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
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)
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
void SelectFilterDone(int newpos)
The child class calls this function when the hardware successfully finished selecting a new filter wh...
virtual bool updateProperties() override
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) override
Process the client newSwitch command.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
void setFilterConnection(const uint8_t &value)
setFilterConnection Set Filter connection mode. Child class should call this in the constructor befor...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
int PortFD
For Serial & TCP connections.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
bool Handshake() override
perform handshake with device to check communication
virtual ~XAGYLWheel() override
Definition: xagyl_wheel.cpp:46
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: xagyl_wheel.cpp:62
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
@ SET_PULSE_WITDH
Definition: xagyl_wheel.h:42
@ INFO_MAX_SPEED
Definition: xagyl_wheel.h:33
@ INFO_FILTER_POSITION
Definition: xagyl_wheel.h:31
@ INFO_MAX_SLOTS
Definition: xagyl_wheel.h:37
@ INFO_THRESHOLD
Definition: xagyl_wheel.h:36
@ INFO_PULSE_WIDTH
Definition: xagyl_wheel.h:38
@ INFO_PRODUCT_NAME
Definition: xagyl_wheel.h:29
@ INFO_FIRMWARE_VERSION
Definition: xagyl_wheel.h:30
@ INFO_SERIAL_NUMBER
Definition: xagyl_wheel.h:32
bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
bool SelectFilter(int) override
Select a new filter position.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
const char * getDefaultName() override
Definition: xagyl_wheel.cpp:54
const char * FILTER_TAB
FILTER_TAB Where all the properties for filter wheels are located.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
double max(void)
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ IP_RW
Definition: indiapi.h:186
@ IP_RO
Definition: indiapi.h:184
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
#define MAXINDILABEL
Definition: indiapi.h:192
@ ISR_ATMOST1
Definition: indiapi.h:174
#define MAXINDINAME
Definition: indiapi.h:191
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:474
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
@ TTY_TIME_OUT
Definition: indicom.h:154
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
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indidevapi.c:128
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indidevapi.c:148
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 IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indidevapi.c:15
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
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
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 LOG_DEBUG(txt)
Definition: indilogger.h:75
#define LOGF_WARN(fmt,...)
Definition: indilogger.h:81
#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
@ value
the parser finished reading a JSON value
__u8 cmd[4]
Definition: pwc-ioctl.h:2
One number descriptor.
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371
char name[MAXINDINAME]
Definition: indiapi.h:250