Instrument Neutral Distributed Interface INDI 2.2.5
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
29static std::unique_ptr<XAGYLWheel> xagylWheel(new XAGYLWheel());
30
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,
99
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
188bool 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
237bool 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
341void XAGYLWheel::initOffset()
342{
343 delete [] OffsetN;
344 OffsetN = new INumber[static_cast<uint8_t>(FilterSlotNP[0].getMax())];
345 char offsetName[MAXINDINAME], offsetLabel[MAXINDILABEL];
346 for (int i = 0; i < FilterSlotNP[0].getMax(); 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, FilterSlotNP[0].getMax(), getDeviceName(),
354 "Offsets", "", FILTER_TAB, IP_RW, 0, IPS_IDLE);
355}
356
361bool 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
374bool 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
444bool 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
459bool 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
487bool 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
503bool 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 FilterSlotNP[0].setValue(CurrentFilter);
515 return true;
516 }
517 else
518 return false;
519}
520
524bool 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
544bool 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
565bool 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
586bool 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
607bool 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 FilterSlotNP[0].setMax(maxFilterSlots);
620 return true;
621 }
622 return false;
623}
624
642bool 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
683bool 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
715bool 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
751bool 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
792bool 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
820void 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
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.
INDI::PropertyNumber FilterSlotNP
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
Initialize 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
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
@ INFO_FILTER_POSITION
Definition xagyl_wheel.h:31
@ 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
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.
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ IP_RW
Definition indiapi.h:184
@ IP_RO
Definition indiapi.h:182
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
#define MAXINDILABEL
Definition indiapi.h:190
@ ISR_ATMOST1
Definition indiapi.h:172
#define MAXINDINAME
Definition indiapi.h:189
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition indicom.c:473
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition indicom.c:1243
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:759
Implementations for common driver routines.
@ TTY_OK
Definition indicom.h:54
@ TTY_TIME_OUT
Definition indicom.h:58
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:490
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition indidevapi.c:337
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition indidevapi.c:366
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:509
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition indidevapi.c:44
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition indidevapi.c:23
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:376
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:416
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:398
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:453
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
#define MAXRBUF
Definition indidriver.c:52
#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 getDeviceName
uint8_t cmd[4]
Definition pwc-ioctl.h:2
One number descriptor.
char name[MAXINDINAME]
Definition indiapi.h:321
char name[MAXINDINAME]
Definition indiapi.h:369
char name[MAXINDINAME]
Definition indiapi.h:248