Instrument Neutral Distributed Interface INDI 2.2.5
dreamfocuser.cpp
Go to the documentation of this file.
1/*
2 INDI Driver for DreamFocuser
3
4 Copyright (C) 2016 Piotr Dlugosz
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 <stdlib.h>
23#include <string.h>
24#include <stdarg.h>
25#include <math.h>
26#include <unistd.h>
27#include <time.h>
28#include <errno.h>
29#include <sys/time.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <termios.h>
33#include <memory>
34#include <indicom.h>
35
36#include "dreamfocuser.h"
37#include "config.h"
39
40/*
41COMMANDS:
42
43MMabcd0z - set position x
44response - MMabcd0z
45
46MH00000z - stop
47response - MH00000z
48
49MP00000z - read position
50response - MPabcd0z
51
52MI00000z - is moving
53response - MI000d0z - d = 1: yes, 0: no
54
55MT00000z - read temperature
56response - MT00cd0z - temperature = ((c<<8)|d)/16.0
57
58MA0000nz - read memory dword - n = address
59response - MAabcd0z(?)
60
61MBabcdnz - write memory dword - abcd = content, n = address
62response - MBabcd0z(?)
63
64MC0000nz - read memory word - n = address
65response -
66
67MDab00nz - write memory word - ab = content, n = address
68response -
69
70----
71
72MR000d0z - move with speed d & 0b1111111 (0 - 127), direction d >> 7 (1 up, 0 down)
73response - MR000d0z
74
75MW00000z - is calibrated
76response - MW000d0z - d = 1: yes (absolute mode), 0: no (relative mode)
77
78MZabcd0z - calibrate toposition x
79response - MZabcd0z
80
81MV00000z - firmware version
82response - MV00cd0z - version: c.d
83
84MG00000z - park
85response - MG00000z
86*/
87
88#define PARK_PARK 0
89#define PARK_UNPARK 1
90
91// We declare an auto pointer to DreamFocuser.
92static std::unique_ptr<DreamFocuser> dreamFocuser(new DreamFocuser());
93
94void ISPoll(void *p);
95
96
97/****************************************************************
98**
99**
100*****************************************************************/
101
103{
105
106 isAbsolute = false;
107 isMoving = false;
108 isParked = 0;
109 isVcc12V = false;
110
111 setVersion(2, 1);
112
113}
114
116{
118
119 // Default speed
120 //FocusSpeedNPsetMin(0)
121 //FocusSpeedNP[0].setMax(127);
122 //FocusSpeedNP[0].setValue(50);
123 //IUUpdateMinMax(&FocusSpeedNP);
124
125 // Max Position
126 // IUFillNumber(&MaxPositionN[0], "MAXPOSITION", "Ticks", "%.f", 1., 500000., 1000., 300000);
127 // IUFillNumberVector(&MaxPositionNP, MaxPositionN, 1, getDeviceName(), "MAXPOSITION", "Max Absolute Position", FOCUS_SETTINGS_TAB, IP_RW, 0, IPS_IDLE);
128
129 // IUFillNumber(&MaxTravelN[0], "MAXTRAVEL", "Ticks", "%.f", 1., 500000., 1000., 300000.);
130 // IUFillNumberVector(&MaxTravelNP, MaxTravelN, 1, getDeviceName(), "MAXTRAVEL", "Max Relative Travel", FOCUS_SETTINGS_TAB, IP_RW, 0, IPS_IDLE );
131
132 // // Focus Sync
133 // IUFillSwitch(&SyncS[0], "SYNC", "Synchronize", ISS_OFF);
134 // IUFillSwitchVector(&SyncSP, SyncS, 1, getDeviceName(), "SYNC", "Synchronize", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1, 60, IPS_IDLE);
135
136 // Focus Park
137 ParkSP[PARK_PARK].fill("PARK", "Park", ISS_OFF);
138 ParkSP[PARK_UNPARK].fill("UNPARK", "Unpark", ISS_OFF);
139 ParkSP.fill(getDeviceName(), "PARK", "Park", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);
140
141 // Focuser temperature
142 TemperatureNP[0].fill("TEMPERATURE", "Celsius", "%6.2f", -100, 100, 0, 0);
143 TemperatureNP.fill(getDeviceName(), "FOCUS_TEMPERATURE", "Temperature", MAIN_CONTROL_TAB,
144 IP_RO, 0, IPS_IDLE);
145
146 // Focuser humidity and dewpoint
147 WeatherNP[FOCUS_HUMIDITY].fill("FOCUS_HUMIDITY", "Humidity [%]", "%6.1f", 0, 100, 0, 0);
148 WeatherNP[FOCUS_DEWPOINT].fill("FOCUS_DEWPOINT", "Dew point [C]", "%6.1f", -100, 100, 0, 0);
149 WeatherNP.fill(getDeviceName(), "FOCUS_WEATHER", "Weather", MAIN_CONTROL_TAB, IP_RO, 0,
150 IPS_IDLE);
151
152 // We init here the property we wish to "snoop" from the target device
153 StatusSP[ABSOLUTE].fill("ABSOLUTE", "Absolute", ISS_OFF);
154 StatusSP[MOVING].fill("MOVING", "Moving", ISS_OFF);
155 StatusSP[PARKED].fill("PARKED", "Parked", ISS_OFF);
156 StatusSP.fill(getDeviceName(), "STATUS", "Status", MAIN_CONTROL_TAB, IP_RO, ISR_NOFMANY, 0,
157 IPS_IDLE);
158
159 // PresetN[0].min = PresetN[1].min = PresetN[2].min = FocusAbsPosNP[0].setMin(-MaxPositionN[0].value);
160 // PresetN[0].max = PresetN[1].max = PresetN[2].max = FocusAbsPosNP[0].setMax(MaxPositionN[0].value);
161 // strcpy(PresetN[0].format, "%6.0f");
162 // strcpy(PresetN[1].format, "%6.0f");
163 // strcpy(PresetN[2].format, "%6.0f");
164 // PresetN[0].step = PresetN[1].step = PresetN[2].step = FocusAbsPosNP[0].setStep(DREAMFOCUSER_STEP_SIZE);
165
166 // Maximum position can't be changed from driver
168
169 FocusAbsPosNP[0].setValue(0);
170 FocusRelPosNP[0].setMin(-FocusMaxPosNP[0].getMax());
171 FocusRelPosNP[0].setMax(FocusMaxPosNP[0].getMax());
173 FocusRelPosNP[0].setValue(5 * DREAMFOCUSER_STEP_SIZE);
174
175 serialConnection->setDefaultPort("/dev/ttyACM0");
178
179 return true;
180}
181
183{
185
186 if (isConnected())
187 {
188 //defineProperty(&SyncSP);
189 defineProperty(ParkSP);
190 defineProperty(TemperatureNP);
191 defineProperty(WeatherNP);
192 defineProperty(StatusSP);
193 //defineProperty(&MaxPositionNP);
194 //defineProperty(&MaxTravelNP);
195 }
196 else
197 {
198 //deleteProperty(SyncSP.name);
199 deleteProperty(ParkSP);
200 deleteProperty(TemperatureNP);
201 deleteProperty(WeatherNP);
202 deleteProperty(StatusSP);
203 //deleteProperty(MaxPositionNP.name);
204 //deleteProperty(MaxTravelNP.name);
205 }
206 return true;
207}
208
209
210/*
211void DreamFocuser::ISGetProperties(const char *dev)
212{
213 if(dev && strcmp(dev,getDeviceName()))
214 {
215 defineProperty(&MaxPositionNP);
216 loadConfig(true, "MAXPOSITION");
217 };
218 return INDI::Focuser::ISGetProperties(dev);
219}
220*/
221
222
223//bool DreamFocuser::saveConfigItems(FILE *fp)
224//{
225// INDI::Focuser::saveConfigItems(fp);
226
227// IUSaveConfigNumber(fp, &MaxPositionNP);
228// IUSaveConfigNumber(fp, &MaxTravelNP);
229
230// return true;
231//}
232
233//bool DreamFocuser::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
234//{
235
236// if(strcmp(dev, getDeviceName()) == 0)
237// {
238// // Max Position
239// if (!strcmp(MaxPositionNP.name, name))
240// {
241// IUUpdateNumber(&MaxPositionNP, values, names, n);
242
243// if (MaxPositionN[0].value > 0)
244// {
245// PresetN[0].min = PresetN[1].min = PresetN[2].min = FocusAbsPosNP[0].setMin(-MaxPositionN[0].value;);
246// PresetN[0].max = PresetN[1].max = PresetN[2].max = FocusAbsPosNP[0].setMax(MaxPositionN[0].value);
247// FocusAbsPosNP.updateMinMax();
248// IUUpdateMinMax(&PresetNP);
249// FocusAbsPosNP.apply();
250
251// LOGF_DEBUG("Focuser absolute limits: min (%g) max (%g)", FocusAbsPosNP[0].getMin(), FocusAbsPosNP[0].getMax());
252// }
253
254// MaxPositionNP.s = IPS_OK;
255// IDSetNumber(&MaxPositionNP, nullptr);
256// return true;
257// }
258
259
260// // Max Travel
261// if (!strcmp(MaxTravelNP.name, name))
262// {
263// IUUpdateNumber(&MaxTravelNP, values, names, n);
264
265// if (MaxTravelN[0].value > 0)
266// {
267// FocusRelPosNP[0].setMin(0);
268// FocusRelPosNP[0].setMax(MaxTravelN[0].value);
269// FocusRelPosNP.updateMinMax();
270// FocusRelPosNP.apply();
271
272// LOGF_DEBUG("Focuser relative limits: min (%g) max (%g)", FocusRelPosNP[0].getMin(), FocusRelPosNP[0].getMax());
273// }
274
275// MaxTravelNP.s = IPS_OK;
276// IDSetNumber(&MaxTravelNP, nullptr);
277// return true;
278// }
279
280// }
281
282// return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
283
284//}
285
286
287bool DreamFocuser::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
288{
289 if(strcmp(dev, getDeviceName()) == 0)
290 {
291 // Park
292 if (ParkSP.isNameMatch(name))
293 {
294 ParkSP.update(states, names, n);
295 int index = ParkSP.findOnSwitchIndex();
296 ParkSP.reset();
297
298 if ( (isParked && (index == PARK_UNPARK)) || ( !isParked && (index == PARK_PARK)) )
299 {
300 LOG_INFO("Park, issuing command.");
301 if ( setPark() )
302 {
303 //ParkSP.s = IPS_OK;
306 }
307 else
308 ParkSP.setState(IPS_ALERT);
309 }
310 ParkSP.apply();
311 return true;
312 }
313 }
314
315 return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
316}
317
318bool DreamFocuser::SyncFocuser(uint32_t ticks)
319{
320 return setSync(ticks);
321}
322
323/****************************************************************
324**
325**
326*****************************************************************/
327
328bool DreamFocuser::getTemperature()
329{
330 if ( dispatch_command('T') )
331 {
332 currentTemperature = ((short int)( (currentResponse.c << 8) | currentResponse.d )) / 10.;
333 currentHumidity = ((short int)( (currentResponse.a << 8) | currentResponse.b )) / 10.;
334 }
335 else
336 return false;
337 return true;
338}
339
341{
342 return getStatus();
343}
344
345bool DreamFocuser::getStatus()
346{
347 LOG_DEBUG("getStatus.");
348 if ( dispatch_command('I') )
349 {
350 isMoving = ( currentResponse.d & 3 ) != 0 ? true : false;
351 //isZero = ( (currentResponse.d>>2) & 1 ) == 1;
352 isParked = (currentResponse.d >> 3) & 3;
353 isVcc12V = ( (currentResponse.d >> 5) & 1 ) == 1;
354 }
355 else
356 return false;
357
358 if ( dispatch_command('W') ) // Is absolute?
359 isAbsolute = currentResponse.d == 1 ? true : false;
360 else
361 return false;
362
363 return true;
364}
365
366
367bool DreamFocuser::getPosition()
368{
369 //int32_t pos;
370
371 if ( dispatch_command('P') )
372 currentPosition = (currentResponse.a << 24) | (currentResponse.b << 16) | (currentResponse.c << 8) | currentResponse.d;
373 else
374 return false;
375
376 return true;
377}
378
379
380bool DreamFocuser::setPosition( int32_t position)
381{
382 if ( dispatch_command('M', position) )
383 if ( ((currentResponse.a << 24) | (currentResponse.b << 16) | (currentResponse.c << 8) | currentResponse.d) == position )
384 {
385 LOGF_DEBUG("Moving to position %d", position);
386 return true;
387 };
388 return false;
389}
390
391bool DreamFocuser::getMaxPosition()
392{
393 if ( dispatch_command('A', 0, 3) )
394 {
395 currentMaxPosition = (currentResponse.a << 24) | (currentResponse.b << 16) | (currentResponse.c << 8) | currentResponse.d;
396 LOGF_DEBUG("getMaxPosition: %d", currentMaxPosition);
397 return true;
398 }
399 else
400 LOG_ERROR("getMaxPosition error");
401
402 return false;
403}
404
405
406bool DreamFocuser::setSync( uint32_t position)
407{
408 if ( dispatch_command('Z', position) )
409 if ( static_cast<uint32_t>((currentResponse.a << 24) | (currentResponse.b << 16) | (currentResponse.c << 8) |
410 currentResponse.d) == position )
411 {
412 LOGF_DEBUG("Syncing to position %d", position);
413 return true;
414 };
415 LOG_ERROR("Sync failed.");
416 return false;
417}
418
419bool DreamFocuser::setPark()
420{
421 if (isAbsolute == false)
422 {
423 LOG_ERROR("Focuser is not in Absolute mode. Please sync before to allow parking.");
424 return false;
425 }
426
427 if ( dispatch_command('G') )
428 {
429 LOG_INFO( "Focuser park command.");
430 return true;
431 }
432 LOG_ERROR("Park failed.");
433 return false;
434}
435
437{
438 if ( dispatch_command('H') )
439 {
440 LOG_INFO("Focusing aborted.");
441 return true;
442 };
443 LOG_ERROR("Abort failed.");
444 return false;
445}
446
447
448/*
449IPState DreamFocuser::MoveFocuser(FocusDirection dir, int speed, uint16_t duration)
450{
451 DreamFocuserCommand c;
452 unsigned char d = (unsigned char) (speed & 0b01111111) | (dir == FOCUS_INWARD) ? 0b10000000 : 0;
453
454 if ( dispatch_command('R', d) )
455 {
456 gettimeofday(&focusMoveStart,nullptr);
457 focusMoveRequest = duration/1000.0;
458 if ( read_response() )
459 if ( ( currentResponse.k == 'R' ) && (currentResponse.d == d) )
460 if (duration <= getCurrentPollingPeriod())
461 {
462 usleep(getCurrentPollingPeriod() * 1000);
463 AbortFocuser();
464 return IPS_OK;
465 }
466 else
467 return IPS_BUSY;
468 }
469 return IPS_ALERT;
470}
471*/
472
474{
475 LOGF_DEBUG("MoveAbsPosition: %d", ticks);
476
477 if (isAbsolute == false)
478 {
479 LOG_ERROR("Focuser is not in Absolute mode. Please sync.");
480 return IPS_ALERT;
481 }
482
483 if (isParked != 0)
484 {
485 LOG_ERROR("Please unpark before issuing any motion commands.");
486 return IPS_ALERT;
487 }
488 if ( setPosition(ticks) )
489 {
492 return IPS_OK;
493 }
494 return IPS_ALERT;
495}
496
498{
499 int32_t finalTicks = currentPosition + ((int32_t)ticks * (dir == FOCUS_INWARD ? -1 : 1));
500
501 LOGF_DEBUG("MoveRelPosition: %d", finalTicks);
502
503 if (isParked != 0)
504 {
505 LOG_ERROR("Please unpark before issuing any motion commands.");
506 return IPS_ALERT;
507 }
508
509 if ( setPosition(finalTicks) )
510 {
513 return IPS_OK;
514 }
515 return IPS_ALERT;
516}
517
518
520{
521
522 if ( ! isConnected() )
523 return;
524
525 int oldAbsStatus = FocusAbsPosNP.getState();
526 int32_t oldPosition = currentPosition;
527
528 if ( getMaxPosition() )
529 {
530 if ( FocusMaxPosNP[0].getValue() != currentMaxPosition )
531 {
532 FocusMaxPosNP[0].setValue(currentMaxPosition);
535 SetFocuserMaxPosition(currentMaxPosition);
536 }
537 }
538 else
540
541 if ( getStatus() )
542 {
543
544 StatusSP.setState(IPS_OK);
545 if ( isMoving )
546 {
547 //LOG_INFO("Moving" );
549 StatusSP[MOVING].setState(ISS_ON);
550 }
551 else
552 {
555 StatusSP[MOVING].setState(ISS_OFF);
556 };
557
558 if ( isParked == 1 )
559 {
560 ParkSP.setState(IPS_BUSY);
561 StatusSP[PARKED].s = ISS_ON;
562 ParkSP[PARK_PARK].setState(ISS_ON);
563 }
564 else if ( isParked == 2 )
565 {
566 ParkSP.setState(IPS_OK);
567 StatusSP[PARKED].setState(ISS_ON);
568 ParkSP[PARK_PARK].setState(ISS_ON);
569 }
570 else
571 {
572 StatusSP[PARKED].setState(ISS_OFF);
573 ParkSP[PARK_UNPARK].setState(ISS_ON);
574 ParkSP.setState(IPS_IDLE);
575 }
576
577 if ( isAbsolute )
578 {
579 StatusSP[ABSOLUTE].setState(ISS_ON);
580 if ( FocusAbsPosNP[0].getMin() != 0 )
581 {
582 FocusAbsPosNP[0].setMin(0);
584 }
585 }
586 else
587 {
588 if ( FocusAbsPosNP[0].getMin() == 0 )
589 {
590 FocusAbsPosNP[0].setMin(-FocusAbsPosNP[0].getMax());
592 }
593 StatusSP[ABSOLUTE].setState(ISS_OFF);
594 }
595
596 }
597 else
598 StatusSP.setState(IPS_ALERT);
599
600 if ( getTemperature() )
601 {
602 TemperatureNP.setState(TemperatureNP[0].getValue() != currentTemperature ? IPS_BUSY : IPS_OK);
603 WeatherNP.setState(WeatherNP[FOCUS_DEWPOINT].getValue() != currentHumidity ? IPS_BUSY : IPS_OK);
604 TemperatureNP[0].setValue(currentTemperature);
605 WeatherNP[FOCUS_HUMIDITY].setValue(currentHumidity);
606 WeatherNP[FOCUS_DEWPOINT].setValue(pow(currentHumidity / 100, 1.0 / 8) * (112 + 0.9 * currentTemperature) + 0.1 * currentTemperature - 112);
607 }
608 else
609 {
610 TemperatureNP.setState(IPS_ALERT);
611 WeatherNP.setState(IPS_ALERT);
612 }
613
615 {
616 if ( getPosition() )
617 {
618 if ( oldPosition != currentPosition )
619 {
621 StatusSP[MOVING].setState(ISS_ON);
622 }
623 else FocusAbsPosNP[0].setValue(currentPosition);
624
625 {
626 StatusSP[MOVING].setState(ISS_OFF);
628 }
629 //if ( currentPosition < 0 )
630 // FocusAbsPosNP.setState(IPS_ALERT);
631 }
632 else
634 }
635
636
637 if ((oldAbsStatus != FocusAbsPosNP.getState()) || (oldPosition != currentPosition))
639
640 TemperatureNP.apply();
641 WeatherNP.apply();
642 //IDSetSwitch(&SyncSP, nullptr);
643 StatusSP.apply();
644 ParkSP.apply();
645
647
648}
649
650
651/****************************************************************
652**
653**
654*****************************************************************/
655
656unsigned char DreamFocuser::calculate_checksum(DreamFocuserCommand c)
657{
658 unsigned char z;
659
660 // calculate checksum
661 z = (c.M + c.k + c.a + c.b + c.c + c.d + c.addr) & 0xff;
662 return z;
663}
664
665bool DreamFocuser::send_command(char k, uint32_t l, unsigned char addr)
666{
667 DreamFocuserCommand c;
668 int err_code = 0, nbytes_written = 0;
669 char dreamFocuser_error[DREAMFOCUSER_ERROR_BUFFER];
670 unsigned char *x = (unsigned char *)&l;
671
672 switch(k)
673 {
674 case 'M':
675 case 'Z':
676 c.a = x[3];
677 c.b = x[2];
678 c.c = x[1];
679 c.d = x[0];
680 break;
681 case 'H':
682 case 'P':
683 case 'I':
684 case 'T':
685 case 'W':
686 case 'G':
687 case 'V':
688 c.a = 0;
689 c.b = 0;
690 c.c = 0;
691 c.d = 0;
692 break;
693 case 'R':
694 c.a = 0;
695 c.b = 0;
696 c.c = 0;
697 c.d = x[0];
698 break;
699 case 'A':
700 case 'C':
701 c.a = 0;
702 c.b = 0;
703 c.c = 0;
704 c.d = x[0];
705 break;
706 case 'B':
707 case 'D':
708 c.a = x[3];
709 c.b = x[2];
710 c.c = 0;
711 c.d = x[0];
712 break;
713 default:
714 DEBUGF(INDI::Logger::DBG_ERROR, "Unknown command: '%c'", k);
715 return false;
716 }
717 c.k = k;
718 c.addr = addr;
719 c.z = calculate_checksum(c);
720
721 LOGF_DEBUG("Sending command: c=%c, a=%hhu, b=%hhu, c=%hhu, d=%hhu ($%hhx), n=%hhu, z=%hhu", c.k, c.a, c.b, c.c, c.d, c.d,
722 c.addr, c.z);
723
724 tcflush(PortFD, TCIOFLUSH);
725
726 if ( (err_code = tty_write(PortFD, (char *)&c, sizeof(c), &nbytes_written) != TTY_OK))
727 {
728 tty_error_msg(err_code, dreamFocuser_error, DREAMFOCUSER_ERROR_BUFFER);
729 LOGF_ERROR("TTY error detected: %s", dreamFocuser_error);
730 return false;
731 }
732
733 LOGF_DEBUG("Sending complete. Number of bytes written: %d", nbytes_written);
734
735 return true;
736}
737
738bool DreamFocuser::read_response()
739{
740 int err_code = 0, nbytes_read = 0, z;
741 char err_msg[DREAMFOCUSER_ERROR_BUFFER];
742
743 //LOG_DEBUG("Read response");
744
745 // Read a single response
746 if ( (err_code = tty_read(PortFD, (char *)&currentResponse, sizeof(currentResponse), 5, &nbytes_read)) != TTY_OK)
747 {
748 tty_error_msg(err_code, err_msg, 32);
749 LOGF_ERROR("TTY error detected: %s", err_msg);
750 return false;
751 }
752 LOGF_DEBUG("Response: %c, a=%hhu, b=%hhu, c=%hhu, d=%hhu ($%hhx), n=%hhu, z=%hhu", currentResponse.k, currentResponse.a,
753 currentResponse.b, currentResponse.c, currentResponse.d, currentResponse.d, currentResponse.addr, currentResponse.z);
754
755 if ( nbytes_read != sizeof(currentResponse) )
756 {
757 LOGF_ERROR("Number of bytes read: %d, expected: %d", nbytes_read, sizeof(currentResponse));
758 return false;
759 }
760
761 z = calculate_checksum(currentResponse);
762 if ( z != currentResponse.z )
763 {
764 LOGF_ERROR("Response checksum in not correct %hhu, expected: %hhu", currentResponse.z, z );
765 return false;
766 }
767
768 if ( currentResponse.k == '!' )
769 {
770 LOG_ERROR("Focuser reported unrecognized command.");
771 return false;
772 }
773
774 if ( currentResponse.k == '?' )
775 {
776 LOG_ERROR("Focuser reported bad checksum.");
777 return false;
778 }
779
780 return true;
781}
782
783bool DreamFocuser::dispatch_command(char k, uint32_t l, unsigned char addr)
784{
785 LOG_DEBUG("send_command");
786 if ( send_command(k, l, addr) )
787 {
788 if ( read_response() )
789 {
790 LOG_DEBUG("check currentResponse.k");
791 if ( currentResponse.k == k )
792 return true;
793 }
794 }
795 return false;
796}
797
798/****************************************************************
799**
800**
801*****************************************************************/
802
804{
805 return (char *)"DreamFocuser";
806}
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
void setDefaultPort(const char *port)
setDefaultPort Set default port. Call this function in initProperties() of your driver if you want to...
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
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 * getDefaultName() override
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual IPState MoveAbsFocuser(uint32_t ticks) override
MoveFocuser the focuser to an absolute position.
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
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.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INDI::PropertyNumber FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
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 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,...
Connection::Serial * serialConnection
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
bool isNameMatch(const char *otherName) const
void setPermission(IPerm permission)
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)
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
#define PARK_UNPARK
#define PARK_PARK
void ISPoll(void *p)
Definition fli_wheel.c:393
#define DREAMFOCUSER_STEP_SIZE
#define DREAMFOCUSER_ERROR_BUFFER
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_NOFMANY
Definition indiapi.h:173
@ 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
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 LOG_DEBUG(txt)
Definition indilogger.h:75
#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 DEBUGF(priority, msg,...)
Definition indilogger.h:57
#define getDeviceName