Instrument Neutral Distributed Interface INDI 2.2.5
steeldrive2.cpp
Go to the documentation of this file.
1/*
2 Baader SteelDriveII Focuser
3
4 Copyright (C) 2019 Jasem Mutlaq ([email protected])
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20*/
21
22#include "steeldrive2.h"
23#include "indicom.h"
25
26#include <cmath>
27#include <memory>
28#include <cstring>
29#include <termios.h>
30#include <unistd.h>
31#include <regex>
32
33static std::unique_ptr<SteelDriveII> steelDrive(new SteelDriveII());
34
49
51{
53
54 // Focuser Information
55 IUFillText(&InfoT[INFO_NAME], "INFO_NAME", "Name", "NA");
56 IUFillText(&InfoT[INFO_VERSION], "INFO_VERSION", "Version", "NA");
57 IUFillTextVector(&InfoTP, InfoT, 2, getDeviceName(), "INFO", "Info", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);
58
59 // Focuser Device Operation
60 IUFillSwitch(&OperationS[OPERATION_REBOOT], "OPERATION_REBOOT", "Reboot", ISS_OFF);
61 IUFillSwitch(&OperationS[OPERATION_RESET], "OPERATION_RESET", "Factory Reset", ISS_OFF);
62 IUFillSwitch(&OperationS[OPERATION_ZEROING], "OPERATION_ZEROING", "Zero Home", ISS_OFF);
63 IUFillSwitchVector(&OperationSP, OperationS, 3, getDeviceName(), "OPERATION", "Device", MAIN_CONTROL_TAB, IP_RW,
65
66 // Temperature Compensation
67 IUFillSwitch(&TemperatureCompensationS[TC_ENABLED], "TC_ENABLED", "Enabled", ISS_OFF);
68 IUFillSwitch(&TemperatureCompensationS[TC_DISABLED], "TC_DISABLED", "Disabled", ISS_ON);
69 IUFillSwitchVector(&TemperatureCompensationSP, TemperatureCompensationS, 2, getDeviceName(), "TC_COMPENSATE",
70 "Compensation", COMPENSATION_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
71
72 // TC State
73 IUFillSwitch(&TemperatureStateS[TC_ENABLED], "TC_ACTIVE", "Active", ISS_OFF);
74 IUFillSwitch(&TemperatureStateS[TC_DISABLED], "TC_PAUSED", "Paused", ISS_ON);
75 IUFillSwitchVector(&TemperatureStateSP, TemperatureStateS, 2, getDeviceName(), "TC_State", "State", COMPENSATION_TAB, IP_RW,
77
78 // Temperature Compensation Settings
79 IUFillNumber(&TemperatureSettingsN[TC_FACTOR], "TC_FACTOR", "Factor", "%.2f", 0, 1, 0.1, 0);
80 IUFillNumber(&TemperatureSettingsN[TC_PERIOD], "TC_PERIOD", "Period (ms)", "%.f", 10, 600000, 1000, 0);
81 IUFillNumber(&TemperatureSettingsN[TC_DELTA], "TC_DELTA", "Delta (C)", "%.2f", 0, 10, 0.1, 0);
82 IUFillNumberVector(&TemperatureSettingsNP, TemperatureSettingsN, 3, getDeviceName(), "TC_SETTINGS", "Settings",
83 COMPENSATION_TAB, IP_RW, 60, IPS_IDLE);
84
85 // Temperature Sensors
86 IUFillNumber(&TemperatureSensorN[TEMP_0], "TEMP_0", "Motor (C)", "%.2f", -60, 60, 0, 0);
87 IUFillNumber(&TemperatureSensorN[TEMP_1], "TEMP_1", "Controller (C)", "%.f", -60, 60, 0, 0);
88 IUFillNumber(&TemperatureSensorN[TEMP_AVG], "TEMP_AVG", "Average (C)", "%.2f", -60, 60, 0, 0);
89 IUFillNumberVector(&TemperatureSensorNP, TemperatureSensorN, 3, getDeviceName(), "TC_SENSOR", "Sensor", COMPENSATION_TAB,
90 IP_RO, 60, IPS_IDLE);
91
92 // Stepper Drive
93 IUFillNumber(&StepperDriveN[CURRENT_MOVE], "STEPPER_DRIVE_CURRENT_MOVE", "Inverse Current Move", "%.f", 0, 127, 1, 25);
94 IUFillNumber(&StepperDriveN[CURRENT_HOLD], "STEPPER_DRIVE_CURRENT_HOLD", "Inverse Current Hold", "%.f", 0, 127, 1, 100);
96 &StepperDriveNP, StepperDriveN, NARRAY(StepperDriveN),
97 getDeviceName(), "STEPPER_DRIVE", "Stepper Drive", OPTIONS_TAB, IP_RW, 60, IPS_IDLE
98 );
99
103
104 return true;
105}
106
111{
113
114 if (isConnected())
115 {
116 getStartupValues();
117
118 defineProperty(&InfoTP);
119 defineProperty(&OperationSP);
120
121 defineProperty(&TemperatureCompensationSP);
122 defineProperty(&TemperatureStateSP);
123 defineProperty(&TemperatureSettingsNP);
124 defineProperty(&TemperatureSensorNP);
125 defineProperty(&StepperDriveNP);
126 }
127 else
128 {
129 deleteProperty(InfoTP.name);
130 deleteProperty(OperationSP.name);
131
132 deleteProperty(TemperatureCompensationSP.name);
133 deleteProperty(TemperatureStateSP.name);
134 deleteProperty(TemperatureSettingsNP.name);
135 deleteProperty(TemperatureSensorNP.name);
136 deleteProperty(StepperDriveNP.name);
137 }
138
139 return true;
140}
141
146{
147 std::string version;
148
149 if (!getParameter("VERSION", version))
150 return false;
151
152 LOGF_INFO("Detected version %s", version.c_str());
153
154 return true;
155}
156
161{
162 return "Baader SteelDriveII";
163}
164
168bool SteelDriveII::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
169{
170 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
171 {
172 // Temperature Compensation
173 if (!strcmp(TemperatureCompensationSP.name, name))
174 {
175 bool enabled = !strcmp(IUFindOnSwitchName(states, names, n), TemperatureCompensationS[TC_ENABLED].name);
176 bool rc = setParameter("TCOMP", enabled ? "1" : "0");
177
178 if (rc)
179 {
180 IUUpdateSwitch(&TemperatureCompensationSP, states, names, n);
181 TemperatureCompensationSP.s = IPS_OK;
182 LOGF_INFO("Temperature compensation is %s.", enabled ? "enabled" : "disabled");
183 }
184 else
185 {
186 TemperatureCompensationSP.s = IPS_ALERT;
187 }
188
189 IDSetSwitch(&TemperatureCompensationSP, nullptr);
190 return true;
191 }
192
193 // Temperature State (Paused or Active)
194 if (!strcmp(TemperatureStateSP.name, name))
195 {
196 bool active = !strcmp(IUFindOnSwitchName(states, names, n), TemperatureStateS[TC_ACTIVE].name);
197 bool rc = setParameter("TCOMP_PAUSE", active ? "0" : "1");
198
199 if (rc)
200 {
201 IUUpdateSwitch(&TemperatureStateSP, states, names, n);
202 TemperatureStateSP.s = IPS_OK;
203 LOGF_INFO("Temperature compensation is %s.", active ? "active" : "paused");
204 }
205 else
206 {
207 TemperatureStateSP.s = IPS_ALERT;
208 }
209
210 IDSetSwitch(&TemperatureStateSP, nullptr);
211 return true;
212 }
213
214 // Operations
215 if (!strcmp(OperationSP.name, name))
216 {
217 IUUpdateSwitch(&OperationSP, states, names, n);
218 if (OperationS[OPERATION_RESET].s == ISS_ON)
219 {
220 IUResetSwitch(&OperationSP);
221 if (m_ConfirmFactoryReset == false)
222 {
223 LOG_WARN("Click button again to confirm factory reset.");
224 OperationSP.s = IPS_IDLE;
225 IDSetSwitch(&OperationSP, nullptr);
226 return true;
227 }
228 else
229 {
230 m_ConfirmFactoryReset = false;
231 if (!sendCommandOK("RESET"))
232 {
233 OperationSP.s = IPS_ALERT;
234 LOG_ERROR("Failed to reset to factory settings.");
235 IDSetSwitch(&OperationSP, nullptr);
236 return true;
237 }
238 }
239 }
240
241 if (OperationS[OPERATION_REBOOT].s == ISS_ON)
242 {
243 IUResetSwitch(&OperationSP);
244 if (!sendCommand("REBOOT"))
245 {
246 OperationSP.s = IPS_ALERT;
247 LOG_ERROR("Failed to reboot device.");
248 IDSetSwitch(&OperationSP, nullptr);
249 return true;
250 }
251
252 LOG_INFO("Device is rebooting...");
253 OperationSP.s = IPS_OK;
254 IDSetSwitch(&OperationSP, nullptr);
255 return true;
256 }
257
258 if (OperationS[OPERATION_ZEROING].s == ISS_ON)
259 {
260 if (!sendCommandOK("SET USE_ENDSTOP:1"))
261 {
262 LOG_WARN("Failed to enable homing sensor magnet!");
263 }
264
265 if (!sendCommandOK("ZEROING"))
266 {
267 IUResetSwitch(&OperationSP);
268 LOG_ERROR("Failed to zero to home position.");
269 OperationSP.s = IPS_ALERT;
270 }
271 else
272 {
273 OperationSP.s = IPS_BUSY;
274 LOG_INFO("Zeroing to home position in progress...");
275 }
276
277 IDSetSwitch(&OperationSP, nullptr);
278 return true;
279 }
280 }
281
282 }
283
284 return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
285}
286
290bool SteelDriveII::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
291{
292 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
293 {
294 if (!strcmp(TemperatureSettingsNP.name, name))
295 {
296 double factor = TemperatureSettingsN[TC_FACTOR].value;
297 double period = TemperatureSettingsN[TC_PERIOD].value;
298 double delta = TemperatureSettingsN[TC_DELTA].value;
299 bool rc1 = true, rc2 = true, rc3 = true;
300 IUUpdateNumber(&TemperatureSettingsNP, values, names, n);
301
302 if (factor != TemperatureSettingsN[TC_FACTOR].value)
303 rc1 = setParameter("TCOMP_FACTOR", to_string(factor));
304 if (period != TemperatureSettingsN[TC_PERIOD].value)
305 rc2 = setParameter("TCOMP_PERIOD", to_string(period));
306 if (delta != TemperatureSettingsN[TC_DELTA].value)
307 rc3 = setParameter("TCOMP_DELTA", to_string(delta));
308
309 TemperatureSettingsNP.s = (rc1 && rc2 && rc3) ? IPS_OK : IPS_ALERT;
310 IDSetNumber(&TemperatureSettingsNP, nullptr);
311 return true;
312 }
313
314 if (!strcmp(StepperDriveNP.name, name))
315 {
316 StepperDriveNP.s = IPS_OK;
317
318 if (StepperDriveN[CURRENT_MOVE].value != values[CURRENT_MOVE])
319 {
320 if (setParameter("CURRENT_MOVE", to_string(values[CURRENT_MOVE], 0)))
321 StepperDriveN[CURRENT_MOVE].value = values[CURRENT_MOVE];
322 else
323 StepperDriveNP.s = IPS_ALERT;
324 }
325
326 if (StepperDriveN[CURRENT_HOLD].value != values[CURRENT_HOLD])
327 {
328 if (setParameter("CURRENT_HOLD", to_string(values[CURRENT_HOLD], 0)))
329 StepperDriveN[CURRENT_HOLD].value = values[CURRENT_HOLD];
330 else
331 StepperDriveNP.s = IPS_ALERT;
332 }
333
334 IDSetNumber(&StepperDriveNP, nullptr);
335 return true;
336 }
337
338 }
339
340 return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
341}
342
346bool SteelDriveII::SyncFocuser(uint32_t ticks)
347{
348 char cmd[DRIVER_LEN] = {0};
349 snprintf(cmd, DRIVER_LEN, "SET POS:%u", ticks);
350 return sendCommandOK(cmd);
351}
352
357{
358 if (targetTicks < std::stoul(m_Summary[LIMIT]))
359 {
360 char cmd[DRIVER_LEN] = {0};
361 snprintf(cmd, DRIVER_LEN, "GO %u", targetTicks);
362 if (!sendCommandOK(cmd))
363 return IPS_ALERT;
364
365 return IPS_BUSY;
366 }
367
368 return IPS_ALERT;
369}
370
375{
376 uint32_t limit = std::stoul(m_Summary[LIMIT]);
377
378 int direction = (dir == FOCUS_INWARD) ? -1 : 1;
379 int reversed = (FocusReverseSP[INDI_ENABLED].getState() == ISS_ON) ? -1 : 1;
380 int relative = static_cast<int>(ticks);
381 int targetAbsPosition = FocusAbsPosNP[0].getValue() + (relative * direction * reversed);
382
383 targetAbsPosition = std::min(limit, static_cast<uint32_t>(std::max(static_cast<int>(FocusAbsPosNP[0].getMin()),
384 targetAbsPosition)));
385
386 return MoveAbsFocuser(targetAbsPosition);
387}
388
393{
394 if (!isConnected())
395 return;
396
397 getSummary();
398
399 uint32_t summaryPosition = std::max(0, std::stoi(m_Summary[POSITION]));
400
401 // Check if we're idle but the focuser is in motion
402 if (FocusAbsPosNP.getState() != IPS_BUSY && (m_State == GOING_UP || m_State == GOING_DOWN))
403 {
410 FocusAbsPosNP[0].setValue(summaryPosition);
411
415 }
416 else if (FocusAbsPosNP.getState() == IPS_BUSY && (m_State == STOPPED || m_State == ZEROED))
417 {
418 if (OperationSP.s == IPS_BUSY)
419 {
420 IUResetSwitch(&OperationSP);
421 LOG_INFO("Homing is complete");
422 OperationSP.s = IPS_OK;
423 IDSetSwitch(&OperationSP, nullptr);
424 }
425
427 FocusAbsPosNP[0].setValue(summaryPosition);
429 {
432 }
434 {
437 }
438
440 }
441 else if (std::fabs(FocusAbsPosNP[0].getValue() - summaryPosition) > 0)
442 {
443 FocusAbsPosNP[0].setValue(summaryPosition);
445 }
446
447 if (std::fabs(FocusMaxPosNP[0].getValue() - std::stoul(m_Summary[LIMIT])) > 0)
448 {
449 FocusMaxPosNP[0].setValue(std::stoul(m_Summary[LIMIT]));
451 }
452
453 double temp0 = std::stod(m_Summary[TEMP0]);
454 double temp1 = std::stod(m_Summary[TEMP1]);
455 double tempa = std::stod(m_Summary[TEMPAVG]);
456
457 if (temp0 != TemperatureSensorN[TEMP_0].value ||
458 temp1 != TemperatureSensorN[TEMP_1].value ||
459 tempa != TemperatureSensorN[TEMP_AVG].value)
460 {
461 TemperatureSensorN[TEMP_0].value = temp0;
462 TemperatureSensorN[TEMP_1].value = temp1;
463 TemperatureSensorN[TEMP_AVG].value = tempa;
464 TemperatureSensorNP.s = IPS_OK;
465 IDSetNumber(&TemperatureSensorNP, nullptr);
466 }
467
469}
470
475{
476 return sendCommandOK("STOP");
477}
478
483{
484 char cmd[DRIVER_LEN] = {0};
485 snprintf(cmd, DRIVER_LEN, "SET LIMIT:%u", ticks);
486 return sendCommandOK(cmd);
487}
488
493{
494 INDI_UNUSED(enabled);
495 return true;
496}
497
502{
504 return true;
505}
506
510void SteelDriveII::getStartupValues()
511{
512 std::string value;
513
514 if (getParameter("NAME", value))
515 IUSaveText(&InfoT[INFO_NAME], value.c_str());
516
517 if (getParameter("VERSION", value))
518 IUSaveText(&InfoT[INFO_VERSION], value.c_str());
519
520 if (getParameter("TCOMP", value))
521 {
522 TemperatureCompensationS[TC_ENABLED].s = (value == "1") ? ISS_ON : ISS_OFF;
523 TemperatureCompensationS[TC_DISABLED].s = (value == "1") ? ISS_OFF : ISS_ON;
524 }
525
526 if (getParameter("TCOMP_FACTOR", value))
527 {
528 TemperatureSettingsN[TC_FACTOR].value = std::stod(value);
529 }
530
531 if (getParameter("TCOMP_PERIOD", value))
532 {
533 TemperatureSettingsN[TC_PERIOD].value = std::stod(value);
534 }
535
536 if (getParameter("TCOMP_DELTA", value))
537 {
538 TemperatureSettingsN[TC_DELTA].value = std::stod(value);
539 }
540
541 if (getParameter("TCOMP_PAUSE", value))
542 {
543 TemperatureStateS[TC_ACTIVE].s = (value == "0") ? ISS_ON : ISS_OFF;
544 TemperatureStateS[TC_PAUSED].s = (value == "0") ? ISS_OFF : ISS_ON;
545 }
546
547 StepperDriveNP.s = IPS_OK;
548 if (getParameter("CURRENT_MOVE", value))
549 StepperDriveN[CURRENT_MOVE].value = std::stod(value);
550 else
551 StepperDriveNP.s = IPS_ALERT;
552
553 if (getParameter("CURRENT_HOLD", value))
554 StepperDriveN[CURRENT_HOLD].value = std::stod(value);
555 else
556 StepperDriveNP.s = IPS_ALERT;
557
558 getSummary();
559
560 FocusMaxPosNP[0].setValue(std::stoul(m_Summary[LIMIT]));
562
563 TemperatureSensorN[TEMP_0].value = std::stod(m_Summary[TEMP0]);
564 TemperatureSensorN[TEMP_1].value = std::stod(m_Summary[TEMP1]);
565 TemperatureSensorN[TEMP_AVG].value = std::stod(m_Summary[TEMPAVG]);
566
567}
568
572bool SteelDriveII::getSummary()
573{
574 char res[DRIVER_LEN] = {0};
575
576 if (!sendCommand("SUMMARY", res))
577 return false;
578
579 std::vector<std::string> params = split(res, ";");
580 if (params.size() < 10)
581 return false;
582
583 for (int i = 0; i < 10; i++)
584 {
585 std::vector<std::string> value = split(params[i], ":");
586 m_Summary[static_cast<Summary>(i)] = value[1];
587 }
588
589 if (m_Summary[STATE] == "GOING_UP")
590 m_State = GOING_UP;
591 else if (m_Summary[STATE] == "GOING_DOWN")
592 m_State = GOING_DOWN;
593 else if (m_Summary[STATE] == "STOPPED")
594 m_State = STOPPED;
595 else if (m_Summary[STATE] == "ZEROED")
596 m_State = ZEROED;
597
598 return true;
599}
600
604bool SteelDriveII::getParameter(const std::string &parameter, std::string &value)
605{
606 char res[DRIVER_LEN] = {0};
607
608 std::string cmd = "GET " + parameter;
609 if (sendCommand(cmd.c_str(), res) == false)
610 return false;
611
612 std::vector<std::string> values = split(res, ":");
613 if (values.size() != 2)
614 return false;
615
616 value = values[1];
617
618 return true;
619}
620
624bool SteelDriveII::setParameter(const std::string &parameter, const std::string &value)
625{
626 std::string cmd = "SET " + parameter + ":" + value;
627 return sendCommandOK(cmd.c_str());
628}
629
633bool SteelDriveII::sendCommandOK(const char * cmd)
634{
635 char res[DRIVER_LEN] = {0};
636
637 if (!sendCommand(cmd, res))
638 return false;
639
640 return strstr(res, "OK");
641}
642
646bool SteelDriveII::sendCommand(const char * cmd, char * res, int cmd_len, int res_len)
647{
648 int nbytes_written = 0, nbytes_read = 0, rc = -1;
649
650 tcflush(PortFD, TCIOFLUSH);
651
652 if (cmd_len > 0)
653 {
654 char hex_cmd[DRIVER_LEN * 3] = {0};
655 hexDump(hex_cmd, cmd, cmd_len);
656 LOGF_DEBUG("CMD <%s>", hex_cmd);
657 rc = tty_write(PortFD, cmd, cmd_len, &nbytes_written);
658 }
659 else
660 {
661 LOGF_DEBUG("CMD <%s>", cmd);
662
663 char formatted_command[DRIVER_LEN] = {0};
664 snprintf(formatted_command, DRIVER_LEN, "$BS %s\r\n", cmd);
665 rc = tty_write_string(PortFD, formatted_command, &nbytes_written);
666 }
667
668 if (rc != TTY_OK)
669 {
670 char errstr[MAXRBUF] = {0};
671 tty_error_msg(rc, errstr, MAXRBUF);
672 LOGF_ERROR("Serial write error: %s.", errstr);
673 return false;
674 }
675
676 if (res == nullptr)
677 return true;
678
679 char rawResponse[DRIVER_LEN * 2] = {0};
680
681 if (res_len > 0)
682 rc = tty_read(PortFD, res, res_len, DRIVER_TIMEOUT, &nbytes_read);
683 else
684 {
685 // Read echo
686 tty_nread_section(PortFD, rawResponse, DRIVER_LEN, DRIVER_STOP_CHAR, DRIVER_TIMEOUT, &nbytes_read);
687 // Read actual respose
688 rc = tty_nread_section(PortFD, rawResponse, DRIVER_LEN, DRIVER_STOP_CHAR, DRIVER_TIMEOUT, &nbytes_read);
689 }
690
691 if (rc != TTY_OK)
692 {
693 char errstr[MAXRBUF] = {0};
694 tty_error_msg(rc, errstr, MAXRBUF);
695 LOGF_ERROR("Serial read error: %s.", errstr);
696 return false;
697 }
698
699 if (res_len > 0)
700 {
701 char hex_res[DRIVER_LEN * 3] = {0};
702 hexDump(hex_res, res, res_len);
703 LOGF_DEBUG("RES <%s>", hex_res);
704 }
705 else
706 {
707 // Remove extra \r\n
708 rawResponse[nbytes_read - 2] = 0;
709 // Remove the $BS
710 snprintf(res, DRIVER_LEN, "%s", rawResponse + 4);
711 LOGF_DEBUG("RES <%s>", res);
712 }
713
714 tcflush(PortFD, TCIOFLUSH);
715
716 return true;
717}
718
722void SteelDriveII::hexDump(char * buf, const char * data, int size)
723{
724 for (int i = 0; i < size; i++)
725 sprintf(buf + 3 * i, "%02X ", static_cast<uint8_t>(data[i]));
726
727 if (size > 0)
728 buf[3 * size - 1] = '\0';
729}
730
734std::vector<std::string> SteelDriveII::split(const std::string &input, const std::string &regex)
735{
736 // passing -1 as the submatch index parameter performs splitting
737 std::regex re(regex);
738 std::sregex_token_iterator
739 first{input.begin(), input.end(), re, -1},
740 last;
741 return {first, last};
742}
743
747template <typename T>
748std::string SteelDriveII::to_string(const T a_value, const int n)
749{
750 std::ostringstream out;
751 out.precision(n);
752 out << std::fixed << a_value;
753 return out.str();
754}
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
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)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INDI::PropertyNumber FocusRelPosNP
INDI::PropertySwitch FocusReverseSP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertySwitch FocusMotionSP
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertyNumber FocusAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool saveConfigItems(FILE *fp) override
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
Connection::Serial * serialConnection
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
Reverse Focuser Motion.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual IPState MoveRelFocuser(FocusDirection dir, unsigned int ticks) override
virtual bool ReverseFocuser(bool enabled) override
Reverse Focuser Motion.
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
const char * getDefaultName() override
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool saveConfigItems(FILE *fp) override
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
virtual bool SyncFocuser(uint32_t ticks) override
Sync focuser.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
#define NARRAY(a)
Handy macro to find the number of elements in array a[]. Must be used with actual array,...
Definition indiapi.h:498
@ IP_RW
Definition indiapi.h:184
@ IP_RO
Definition indiapi.h:182
IPState
Property state.
Definition indiapi.h:158
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
@ ISR_ATMOST1
Definition indiapi.h:172
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition indicom.c:418
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition indicom.c:548
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
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
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 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
const char * IUFindOnSwitchName(ISState *states, char *names[], int n)
Returns the name of the first ON switch it finds in the supplied arguments.
Definition indidevapi.c:355
#define INDI_UNUSED(x)
Definition indidevapi.h:132
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
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
#define LOGF_INFO(fmt,...)
Definition indilogger.h:82
#define LOG_WARN(txt)
Definition indilogger.h:73
#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
std::unique_ptr< SteelDrive > steelDrive(new SteelDrive())
char name[MAXINDINAME]
Definition indiapi.h:321
char name[MAXINDINAME]
Definition indiapi.h:369
char name[MAXINDINAME]
Definition indiapi.h:248