Instrument Neutral Distributed Interface INDI 2.2.5
dmfc.cpp
Go to the documentation of this file.
1/*
2 Pegasus DMFC Focuser
3 Copyright (C) 2017 Jasem Mutlaq ([email protected])
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19*/
20
21#include "dmfc.h"
22
23#include "indicom.h"
25
26#include <cmath>
27#include <cstring>
28#include <memory>
29
30#include <termios.h>
31#include <unistd.h>
32
33#define DMFC_TIMEOUT 3
34#define FOCUS_SETTINGS_TAB "Settings"
35#define TEMPERATURE_THRESHOLD 0.1
36
37static std::unique_ptr<DMFC> dmfc(new DMFC());
38
40{
41 setVersion(1, 1);
42
43 // Can move in Absolute & Relative motions, can AbortFocuser motion.
50}
51
53{
55
56 // Focuser temperature
57 TemperatureNP[0].fill("TEMPERATURE", "Celsius", "%6.2f", -50, 70., 0., 0.);
58 TemperatureNP.fill(getDeviceName(), "FOCUS_TEMPERATURE", "Temperature",
60
61 // Max Speed
62 MaxSpeedNP[0].fill("Value", "", "%6.2f", 100, 1000., 100., 400.);
63 MaxSpeedNP.fill(getDeviceName(), "MaxSpeed", "", FOCUS_SETTINGS_TAB, IP_RW, 0, IPS_IDLE);
64
65 // Encoders
66 EncoderSP[ENCODERS_ON].fill("On", "", ISS_ON);
67 EncoderSP[ENCODERS_OFF].fill("Off", "", ISS_OFF);
68 EncoderSP.fill(getDeviceName(), "Encoders", "", FOCUS_SETTINGS_TAB, IP_RW, ISR_1OFMANY, 0,
69 IPS_IDLE);
70
71 // Motor Modes
72 MotorTypeSP[MOTOR_DC].fill("DC", "DC", ISS_OFF);
73 MotorTypeSP[MOTOR_STEPPER].fill("Stepper", "Stepper", ISS_ON);
74 MotorTypeSP.fill(getDeviceName(), "Motor Type", "", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY,
75 0, IPS_IDLE);
76
77 // LED
78 LEDSP[LED_OFF].fill("Off", "", ISS_ON);
79 LEDSP[LED_ON].fill("On", "", ISS_OFF);
81
82 // Firmware Version
83 FirmwareVersionTP[0].fill("Version", "Version", "");
84 FirmwareVersionTP.fill(getDeviceName(), "Firmware", "Firmware", MAIN_CONTROL_TAB, IP_RO,
85 0, IPS_IDLE);
86
87 // Relative and absolute movement
88 FocusRelPosNP[0].setMin(0.);
89 FocusRelPosNP[0].setMax(50000.);
90 FocusRelPosNP[0].setValue(0);
91 FocusRelPosNP[0].setStep(1000);
92
93 FocusAbsPosNP[0].setMin(0.);
94 FocusAbsPosNP[0].setMax(100000);
95 FocusAbsPosNP[0].setValue(0);
96 FocusAbsPosNP[0].setStep(1000);
97
98 // Backlash compensation
99 FocusBacklashNP[0].setMin(1); // 0 is off.
100 FocusBacklashNP[0].setMax(1000);
101 FocusBacklashNP[0].setValue(1);
102 FocusBacklashNP[0].setStep(1);
103
104 //LED Default ON
105 LEDSP[LED_ON].setState(ISS_ON);
106 LEDSP[LED_OFF].setState(ISS_OFF);
107
111
112 return true;
113}
114
115void DMFC::ISGetProperties(const char *dev)
116{
118 int configSwitch = MOTOR_STEPPER;
119
120 // Try to read config value for motor type
121 // If relative, then update the capability of the focuser as such.
122 if (IUGetConfigOnSwitchIndex(getDeviceName(), MotorTypeSP.getName(), &configSwitch) == 0)
123 {
124 // We are only relative focuser now.
125 if (configSwitch == MOTOR_DC)
127 else
129
130 MotorTypeSP.setState(IPS_OK);
131 }
132
133 MotorTypeSP.reset();
134 MotorTypeSP[configSwitch].setState(ISS_ON);
135 defineProperty(MotorTypeSP);
136}
137
139{
141
142 if (isConnected())
143 {
144 defineProperty(TemperatureNP);
145 defineProperty(EncoderSP);
146 defineProperty(MaxSpeedNP);
147 defineProperty(LEDSP);
148 defineProperty(FirmwareVersionTP);
149 }
150 else
151 {
152 deleteProperty(TemperatureNP);
153 deleteProperty(EncoderSP);
154 deleteProperty(MaxSpeedNP);
155 deleteProperty(LEDSP);
156 deleteProperty(FirmwareVersionTP);
157 }
158
159 return true;
160}
161
163{
164 if (ack())
165 {
166 LOGF_INFO("%s is online. Getting focus parameters...", this->getDeviceName());
167
168 // Set motor type on startup only.
169 setMotorType((MotorTypeSP[MOTOR_DC].getState() == ISS_ON) ? MOTOR_DC : MOTOR_STEPPER);
170
171 return true;
172 }
173
174 LOGF_INFO(
175 "Error retrieving data from %s, please ensure device is powered and the port is correct.", this->getDeviceName());
176 return false;
177}
178
179
181{
182 return "Pegasus DMFC";
183}
184
185bool DMFC::ack()
186{
187 int nbytes_written = 0, nbytes_read = 0, rc = -1;
188 char errstr[MAXRBUF];
189 char cmd[2] = {0};
190 char res[16] = {0};
191
192 cmd[0] = '#';
193 cmd[1] = 0xA;
194
195 LOGF_DEBUG("CMD <%#02X>", cmd[0]);
196
197 tcflush(PortFD, TCIOFLUSH);
198
199 if ((rc = tty_write(PortFD, cmd, 2, &nbytes_written)) != TTY_OK)
200 {
201 tty_error_msg(rc, errstr, MAXRBUF);
202 LOGF_ERROR("Ack error: %s.", errstr);
203 return false;
204 }
205
206 if ((rc = tty_read_section(PortFD, res, 0xA, DMFC_TIMEOUT, &nbytes_read)) != TTY_OK)
207 {
208 tty_error_msg(rc, errstr, MAXRBUF);
209 LOGF_ERROR("Ack error: %s.", errstr);
210 return false;
211 }
212
213 // Get rid of 0xA
214 res[nbytes_read - 1] = 0;
215
216
217 if( res[nbytes_read - 2] == '\r') res[nbytes_read - 2] = 0;
218
219 LOGF_DEBUG("RES <%s>", res);
220
221 tcflush(PortFD, TCIOFLUSH);
222
223 if((strstr(res, "OK_DMFCN") != nullptr) || (strstr(res, "OK_SMFC") != nullptr) || (strstr(res, "OK_PRDG") != nullptr))
224 return true;
225
226 return false;
227}
228
229
230bool DMFC::SyncFocuser(uint32_t ticks)
231{
232 int nbytes_written = 0, rc = -1;
233 char cmd[16] = {0};
234
235 snprintf(cmd, 16, "W:%ud", ticks);
236 cmd[strlen(cmd)] = 0xA;
237
238 LOGF_DEBUG("CMD <%s>", cmd);
239
240 // Set Position
241 if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
242 {
243 char errstr[MAXRBUF];
244 tty_error_msg(rc, errstr, MAXRBUF);
245 LOGF_ERROR("sync error: %s.", errstr);
246 return false;
247 }
248
249 this->ignoreResponse();
250
251 return true;
252}
253
254bool DMFC::moveAbsolute(uint32_t newPosition)
255{
256 int nbytes_written = 0, rc = -1;
257 char cmd[16] = {0};
258
259 snprintf(cmd, 16, "M:%ud", newPosition);
260 cmd[strlen(cmd)] = 0xA;
261
262 LOGF_DEBUG("CMD <%s>", cmd);
263
264 // Set Position
265 if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
266 {
267 char errstr[MAXRBUF];
268 tty_error_msg(rc, errstr, MAXRBUF);
269 LOGF_ERROR("Absolute move error: %s.", errstr);
270 return false;
271 }
272
273 this->ignoreResponse();
274
275 return true;
276}
277
278bool DMFC::moveRelative(int relativePosition)
279{
280 int nbytes_written = 0, rc = -1;
281 char cmd[16] = {0};
282
283 snprintf(cmd, 16, "G:%d", relativePosition);
284 cmd[strlen(cmd)] = 0xA;
285
286 LOGF_DEBUG("CMD <%s>", cmd);
287
288 // Set Relative Position
289 if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
290 {
291 char errstr[MAXRBUF];
292 tty_error_msg(rc, errstr, MAXRBUF);
293 LOGF_ERROR("Relative move error: %s.", errstr);
294 return false;
295 }
296
297 this->ignoreResponse();
298
299 return true;
300}
301
302bool DMFC::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
303{
304 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
305 {
306 // Motor Type
307 if (MotorTypeSP.isNameMatch(name))
308 {
309 MotorTypeSP.update(states, names, n);
310 MotorTypeSP.setState(IPS_OK);
311 saveConfig(true, MotorTypeSP.getName());
312
313 // If we're not connected, let's then set the capability now.
314 if (!isConnected())
315 {
316 // We are only relative focuser now.
317 if (MotorTypeSP[MOTOR_DC].getState() == ISS_ON)
319 else
321 }
322 else
323 LOG_INFO("Motor type changed. Please restart driver for this change to take effect.");
324
325 MotorTypeSP.apply( );
326 return true;
327 }
328
329 // Encoders
330 if (EncoderSP.isNameMatch(name))
331 {
332 EncoderSP.update(states, names, n);
333 bool rc = setEncodersEnabled(EncoderSP[ENCODERS_ON].getState() == ISS_ON);
334 EncoderSP.setState(rc ? IPS_OK : IPS_ALERT);
335 EncoderSP.apply();
336 return true;
337 }
338
339 // LED
340 if (LEDSP.isNameMatch(name))
341 {
342 LEDSP.update(states, names, n);
343 bool rc = setLedEnabled(LEDSP[LED_ON].getState() == ISS_ON);
344 LEDSP.setState(rc ? IPS_OK : IPS_ALERT);
345 LEDSP.apply();
346 return true;
347 }
348 }
349 return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
350}
351
352bool DMFC::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
353{
354 if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
355 {
356 // MaxSpeed
357 if (MaxSpeedNP.isNameMatch(name))
358 {
359 MaxSpeedNP.update(values, names, n);
360 bool rc = setMaxSpeed(MaxSpeedNP[0].getValue());
361 MaxSpeedNP.setState(rc ? IPS_OK : IPS_ALERT);
362 MaxSpeedNP.apply();
363 return true;
364 }
365 }
366
367 return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
368}
369
370void DMFC::ignoreResponse()
371{
372 int nbytes_read = 0;
373 char res[64];
374 tty_read_section(PortFD, res, 0xA, DMFC_TIMEOUT, &nbytes_read);
375}
376
377bool DMFC::updateFocusParams()
378{
379 int nbytes_written = 0, nbytes_read = 0, rc = -1;
380 char errstr[MAXRBUF];
381 char cmd[3] = {0};
382 char res[64];
383 cmd[0] = 'A';
384 cmd[1] = 0xA;
385
386 LOGF_DEBUG("CMD <%#02X>", cmd[0]);
387
388 tcflush(PortFD, TCIOFLUSH);
389
390 if ((rc = tty_write(PortFD, cmd, 2, &nbytes_written)) != TTY_OK)
391 {
392 tty_error_msg(rc, errstr, MAXRBUF);
393 LOGF_ERROR("GetFocusParams error: %s.", errstr);
394 return false;
395 }
396
397
398 if ((rc = tty_read_section(PortFD, res, 0xA, DMFC_TIMEOUT, &nbytes_read)) != TTY_OK)
399 {
400 tty_error_msg(rc, errstr, MAXRBUF);
401 LOGF_ERROR("GetFocusParams error: %s.", errstr);
402 return false;
403 }
404
405 res[nbytes_read - 1] = 0;
406
407 // Check for '\r' at end of string and replace with nullptr (DMFC firmware version 2.8)
408 if( res[nbytes_read - 2] == '\r') res[nbytes_read - 2] = 0;
409
410 LOGF_DEBUG("RES <%s>", res);
411
412 tcflush(PortFD, TCIOFLUSH);
413
414 char *token = std::strtok(res, ":");
415
416
417 // #1 Status
418 if (token == nullptr || ((strstr(token, "OK_DMFCN") == nullptr) && (strstr(token, "OK_SMFC") == nullptr)
419 && (strstr(token, "OK_PRDG") == nullptr)))
420 {
421 LOGF_ERROR("Invalid status response. %s", res);
422 return false;
423 }
424
425 // #2 Version
426 token = std::strtok(nullptr, ":");
427
428 if (token == nullptr)
429 {
430 LOG_ERROR("Invalid version response.");
431 return false;
432 }
433
434 if (FirmwareVersionTP[0].isEmpty() || FirmwareVersionTP[0].isNameMatch(token))
435 {
436 FirmwareVersionTP[0].setText(token);
437 FirmwareVersionTP.setState(IPS_OK);
438 FirmwareVersionTP.apply();
439 }
440
441 // #3 Motor Type
442 token = std::strtok(nullptr, ":");
443
444 if (token == nullptr)
445 {
446 LOG_ERROR("Invalid motor mode response.");
447 return false;
448 }
449
450 int motorType = atoi(token);
451
452
453 if (motorType >= 0 && motorType <= 1)
454 {
455 //1 stepper
456 //0 dc
457 MotorTypeSP.reset();
458 MotorTypeSP[MOTOR_DC].setState((motorType == 0) ? ISS_ON : ISS_OFF);
459 MotorTypeSP[MOTOR_STEPPER].s = (motorType == 1) ? ISS_ON : ISS_OFF;
460 MotorTypeSP.setState(IPS_OK);
461 MotorTypeSP.apply();
462 }
463
464 // #4 Temperature
465 token = std::strtok(nullptr, ":");
466
467 if (token == nullptr)
468 {
469 LOG_ERROR("Invalid temperature response.");
470 return false;
471 }
472
473 double temperature = atof(token);
474 if (temperature == -127)
475 {
476 TemperatureNP.setState(IPS_ALERT);
477 TemperatureNP.apply();
478 }
479 else
480 {
481 if (fabs(temperature - TemperatureNP[0].getValue()) > TEMPERATURE_THRESHOLD)
482 {
483 TemperatureNP[0].setValue(temperature);
484 TemperatureNP.setState(IPS_OK);
485 TemperatureNP.apply();
486 }
487 }
488
489 // #5 Position
490 token = std::strtok(nullptr, ":");
491
492 if (token == nullptr)
493 {
494 LOG_ERROR("Invalid position response.");
495 return false;
496 }
497
498 currentPosition = atoi(token);
499 if (currentPosition != FocusAbsPosNP[0].getValue())
500 {
501 FocusAbsPosNP[0].setValue(currentPosition);
503 }
504
505 // #6 Moving Status
506 token = std::strtok(nullptr, ":");
507
508 if (token == nullptr)
509 {
510 LOG_ERROR("Invalid moving status response.");
511 return false;
512 }
513
514 isMoving = (token[0] == '1');
515
516 // #7 LED Status
517 token = std::strtok(nullptr, ":");
518
519 if (token == nullptr)
520 {
521 LOG_ERROR("Invalid LED response.");
522 return false;
523 }
524
525 int ledStatus = atoi(token);
526 if (ledStatus >= 0 && ledStatus <= 1)
527 {
528 LEDSP.reset();
529 LEDSP[ledStatus].setState(ISS_ON);
530 LEDSP.setState(IPS_OK);
531 LEDSP.apply();
532 }
533
534 // #8 Reverse Status
535 token = std::strtok(nullptr, ":");
536
537 if (token == nullptr)
538 {
539 LOG_ERROR("Invalid reverse response.");
540 return false;
541 }
542
543 int reverseStatus = atoi(token);
544 if (reverseStatus >= 0 && reverseStatus <= 1)
545 {
547 FocusReverseSP[INDI_ENABLED].setState((reverseStatus == 1) ? ISS_ON : ISS_OFF);
548 FocusReverseSP[INDI_DISABLED].setState((reverseStatus == 0) ? ISS_ON : ISS_OFF);
551 }
552
553 // #9 Encoder status
554 token = std::strtok(nullptr, ":");
555
556 if (token == nullptr)
557 {
558 LOG_ERROR("Invalid encoder response.");
559 return false;
560 }
561
562 int encoderStatus = atoi(token);
563 if (encoderStatus >= 0 && encoderStatus <= 1)
564 {
565 EncoderSP.reset();
566 EncoderSP[encoderStatus].setState(ISS_ON);
567 EncoderSP.setState(IPS_OK);
568 EncoderSP.apply();
569 }
570
571 // #10 Backlash
572 token = std::strtok(nullptr, ":");
573
574 if (token == nullptr)
575 {
576 LOG_ERROR("Invalid encoder response.");
577 return false;
578 }
579
580 int backlash = atoi(token);
581 // If backlash is zero then compensation is disabled
582 if (backlash == 0 && FocusBacklashSP[INDI_ENABLED].getState() == ISS_ON)
583 {
584 LOG_WARN("Backlash value is zero, disabling backlash switch...");
585
590 }
591 else if (backlash > 0 && (FocusBacklashSP[INDI_DISABLED].getState() == ISS_ON || backlash != FocusBacklashNP[0].getValue()))
592 {
593 if (backlash != FocusBacklashNP[0].getValue())
594 {
595 FocusBacklashNP[0].setValue(backlash);
598 }
599
600 if (FocusBacklashSP[INDI_DISABLED].getState() == ISS_ON)
601 {
606 }
607 }
608
609 return true;
610}
611
612bool DMFC::setMaxSpeed(uint16_t speed)
613{
614 int nbytes_written = 0, rc = -1;
615 char cmd[16] = {0};
616
617 snprintf(cmd, 16, "S:%d", speed);
618 cmd[strlen(cmd)] = 0xA;
619
620 LOGF_DEBUG("CMD <%s>", cmd);
621
622 tcflush(PortFD, TCIOFLUSH);
623
624 // Set Speed
625 if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
626 {
627 char errstr[MAXRBUF];
628 tty_error_msg(rc, errstr, MAXRBUF);
629 LOGF_ERROR("setMaxSpeed error: %s.", errstr);
630 return false;
631 }
632
633 this->ignoreResponse();
634 return true;
635}
636
637bool DMFC::ReverseFocuser(bool enabled)
638{
639 int nbytes_written = 0, rc = -1;
640 char cmd[16] = {0};
641
642 snprintf(cmd, 16, "N:%d", enabled ? 1 : 0);
643 cmd[strlen(cmd)] = 0xA;
644
645 LOGF_DEBUG("CMD <%s>", cmd);
646
647 tcflush(PortFD, TCIOFLUSH);
648
649 // Reverse
650 if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
651 {
652 char errstr[MAXRBUF];
653 tty_error_msg(rc, errstr, MAXRBUF);
654 LOGF_ERROR("Reverse error: %s.", errstr);
655 return false;
656 }
657
658 this->ignoreResponse();
659
660 return true;
661}
662
663bool DMFC::setLedEnabled(bool enable)
664{
665 int nbytes_written = 0, rc = -1;
666 char cmd[16] = {0};
667
668 snprintf(cmd, 16, "L:%d", enable ? 2 : 1);
669 cmd[strlen(cmd)] = 0xA;
670
671 LOGF_DEBUG("CMD <%s>", cmd);
672
673 tcflush(PortFD, TCIOFLUSH);
674
675 // Led
676 if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
677 {
678 char errstr[MAXRBUF];
679 tty_error_msg(rc, errstr, MAXRBUF);
680 LOGF_ERROR("Led error: %s.", errstr);
681 return false;
682 }
683
684 this->ignoreResponse();
685 return true;
686}
687
688bool DMFC::setEncodersEnabled(bool enable)
689{
690 int nbytes_written = 0, rc = -1;
691 char cmd[16] = {0};
692
693 snprintf(cmd, 16, "E:%d", enable ? 0 : 1);
694 cmd[strlen(cmd)] = 0xA;
695
696 LOGF_DEBUG("CMD <%s>", cmd);
697
698 tcflush(PortFD, TCIOFLUSH);
699
700 // Encoders
701 if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
702 {
703 char errstr[MAXRBUF];
704 tty_error_msg(rc, errstr, MAXRBUF);
705 LOGF_ERROR("Encoder error: %s.", errstr);
706 return false;
707 }
708
709 this->ignoreResponse();
710 return true;
711}
712
713bool DMFC::SetFocuserBacklash(int32_t steps)
714{
715 int nbytes_written = 0, rc = -1;
716 char cmd[16] = {0};
717
718 snprintf(cmd, 16, "C:%d", steps);
719 cmd[strlen(cmd)] = 0xA;
720
721 LOGF_DEBUG("CMD <%s>", cmd);
722
723 tcflush(PortFD, TCIOFLUSH);
724
725 // Backlash
726 if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
727 {
728 char errstr[MAXRBUF];
729 tty_error_msg(rc, errstr, MAXRBUF);
730 LOGF_ERROR("Backlash error: %s.", errstr);
731 return false;
732 }
733
734 this->ignoreResponse();
735 return true;
736}
737
739{
740 if (!enabled)
741 return SetFocuserBacklash(0);
742
743 return SetFocuserBacklash(FocusBacklashNP[0].getValue() > 0 ? FocusBacklashNP[0].getValue() : 1);
744}
745
746bool DMFC::setMotorType(uint8_t type)
747{
748
749 int nbytes_written = 0, rc = -1;
750 char cmd[16] = {0};
751
752 //commands:
753 //2 dc
754 //1 stepper
755 snprintf(cmd, 16, "R:%d", (type == MOTOR_STEPPER) ? 1 : 2);
756 cmd[strlen(cmd)] = 0xA;
757
758 LOGF_DEBUG("CMD <%s>", cmd);
759
760 tcflush(PortFD, TCIOFLUSH);
761
762 // Motor Type
763 if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
764 {
765 char errstr[MAXRBUF];
766 tty_error_msg(rc, errstr, MAXRBUF);
767 LOGF_ERROR("Motor type error: %s.", errstr);
768 return false;
769 }
770
771 this->ignoreResponse();
772
773 return true;
774}
775
776IPState DMFC::MoveAbsFocuser(uint32_t targetTicks)
777{
778 targetPosition = targetTicks;
779
780 bool rc = moveAbsolute(targetPosition);
781
782 if (!rc)
783 return IPS_ALERT;
784
786
787 return IPS_BUSY;
788}
789
791{
792 int relativePosition = ticks * ((dir == FOCUS_INWARD) ? -1 : 1);
793 return moveRelative(relativePosition) ? IPS_BUSY : IPS_ALERT;
794}
795
797{
798 if (!isConnected())
799 {
801 return;
802 }
803
804 bool rc = updateFocusParams();
805
806 if (rc)
807 {
809 {
810 if (isMoving == false)
811 {
816 LOG_INFO("Focuser reached requested position.");
817 }
818 }
819 }
820
822}
823
825{
826 int nbytes_written;
827 char cmd[2] = { 'H', 0xA };
828
829 if (tty_write(PortFD, cmd, 2, &nbytes_written) == TTY_OK)
830 {
835 this->ignoreResponse();
836 return true;
837 }
838 else
839 return false;
840}
841
843{
845 MotorTypeSP.save(fp);
846 EncoderSP.save(fp);
847 MaxSpeedNP.save(fp);
848 LEDSP.save(fp);
849
850 return true;
851}
double temperature
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
Definition dmfc.h:26
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
Definition dmfc.cpp:230
virtual bool SetFocuserBacklashEnabled(bool enabled) override
SetFocuserBacklashEnabled Enables or disables the focuser backlash compensation.
Definition dmfc.cpp:738
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition dmfc.cpp:796
virtual void ISGetProperties(const char *dev) override
Handles client requests for property definitions for this device or all devices. Delegates to the bas...
Definition dmfc.cpp:115
virtual bool saveConfigItems(FILE *fp) override
Definition dmfc.cpp:842
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
Definition dmfc.cpp:790
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
Definition dmfc.cpp:637
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
Definition dmfc.cpp:776
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
Definition dmfc.cpp:824
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
Definition dmfc.cpp:138
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
Definition dmfc.cpp:162
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...
Definition dmfc.cpp:352
DMFC()
Definition dmfc.cpp:39
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...
Definition dmfc.cpp:302
const char * getDefaultName() override
Definition dmfc.cpp:180
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
Definition dmfc.cpp:713
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
Definition dmfc.cpp:52
bool isConnected() const
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
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.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void addDebugControl()
Add Debug control to the driver.
INDI::PropertyNumber FocusRelPosNP
INDI::PropertySwitch FocusReverseSP
uint32_t GetCapability() const
GetFocuserCapability returns the capability of the focuser.
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertySwitch FocusBacklashSP
INDI::PropertyNumber FocusBacklashNP
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 void ISGetProperties(const char *dev) override
Handles client requests for property definitions for this device or all devices. Delegates to the bas...
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
void save(FILE *f) const
save Save property to configuration file.
const char * getName() const
bool isNameMatch(const char *otherName) const
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
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)
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
#define DMFC_TIMEOUT
Definition dmfc.cpp:33
#define TEMPERATURE_THRESHOLD
Definition dmfc.cpp:35
#define FOCUS_SETTINGS_TAB
Definition dmfc.cpp:34
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
@ 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
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition indicom.c:653
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition indicom.c:418
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition indicom.c:1243
Implementations for common driver routines.
@ TTY_OK
Definition indicom.h:54
#define MAXRBUF
Definition indidriver.c:52
int IUGetConfigOnSwitchIndex(const char *dev, const char *property, int *index)
IUGetConfigOnSwitchIndex Opens configuration file and reads single switch property to find ON switch ...
Definition indidriver.c:719
#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
uint16_t type
Definition pwc-ioctl.h:0
uint8_t cmd[4]
Definition pwc-ioctl.h:2