Instrument Neutral Distributed Interface INDI  2.0.2
moonlite.cpp
Go to the documentation of this file.
1 /*
2  Moonlite Focuser
3  Copyright (C) 2013-2019 Jasem Mutlaq (mutlaqja@ikarustech.com)
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 "moonlite.h"
22 
23 #include "indicom.h"
24 
25 #include <cmath>
26 #include <cstring>
27 #include <memory>
28 
29 #include <termios.h>
30 #include <unistd.h>
31 
32 static std::unique_ptr<MoonLite> moonLite(new MoonLite());
33 
35 {
36  setVersion(1, 1);
37 
38  // Can move in Absolute & Relative motions, can AbortFocuser motion, and has variable speed.
41 }
42 
44 {
46 
47  FocusSpeedN[0].min = 1;
48  FocusSpeedN[0].max = 5;
49  FocusSpeedN[0].value = 1;
50 
51  // Step Mode
52  IUFillSwitch(&StepModeS[FOCUS_HALF_STEP], "FOCUS_HALF_STEP", "Half Step", ISS_OFF);
53  IUFillSwitch(&StepModeS[FOCUS_FULL_STEP], "FOCUS_FULL_STEP", "Full Step", ISS_ON);
54  IUFillSwitchVector(&StepModeSP, StepModeS, 2, getDeviceName(), "Step Mode", "", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 0,
55  IPS_IDLE);
56 
57  // Focuser temperature
58  IUFillNumber(&TemperatureN[0], "TEMPERATURE", "Celsius", "%6.2f", -50, 70., 0., 0.);
59  IUFillNumberVector(&TemperatureNP, TemperatureN, 1, getDeviceName(), "FOCUS_TEMPERATURE", "Temperature",
61 
62  // Temperature Settings
63  IUFillNumber(&TemperatureSettingN[0], "Calibration", "", "%6.2f", -100, 100, 0.5, 0);
64  IUFillNumber(&TemperatureSettingN[1], "Coefficient", "", "%6.2f", -100, 100, 0.5, 0);
65  IUFillNumberVector(&TemperatureSettingNP, TemperatureSettingN, 2, getDeviceName(), "T. Settings", "",
67 
68  // Compensate for temperature
69  IUFillSwitch(&TemperatureCompensateS[0], "Enable", "", ISS_OFF);
70  IUFillSwitch(&TemperatureCompensateS[1], "Disable", "", ISS_ON);
71  IUFillSwitchVector(&TemperatureCompensateSP, TemperatureCompensateS, 2, getDeviceName(), "T. Compensate",
73 
74  /* Relative and absolute movement */
75  FocusRelPosN[0].min = 0.;
76  FocusRelPosN[0].max = 50000.;
77  FocusRelPosN[0].value = 0;
78  FocusRelPosN[0].step = 1000;
79 
80  FocusAbsPosN[0].min = 0.;
81  FocusAbsPosN[0].max = 100000.;
82  FocusAbsPosN[0].value = 0;
83  FocusAbsPosN[0].step = 1000;
84 
87 
88  return true;
89 }
90 
92 {
94 
95  if (isConnected())
96  {
97  defineProperty(&TemperatureNP);
98  defineProperty(&StepModeSP);
99  defineProperty(&TemperatureSettingNP);
100  defineProperty(&TemperatureCompensateSP);
101 
102  GetFocusParams();
103 
104  LOG_INFO("MoonLite parameters updated, focuser ready for use.");
105  }
106  else
107  {
108  deleteProperty(TemperatureNP.name);
109  deleteProperty(StepModeSP.name);
110  deleteProperty(TemperatureSettingNP.name);
111  deleteProperty(TemperatureCompensateSP.name);
112  }
113 
114  return true;
115 }
116 
118 {
119  if (Ack())
120  {
121  LOG_INFO("MoonLite is online. Getting focus parameters...");
122  return true;
123  }
124 
125  LOG_INFO(
126  "Error retrieving data from MoonLite, please ensure MoonLite controller is powered and the port is correct.");
127  return false;
128 }
129 
131 {
132  return "MoonLite";
133 }
134 
135 bool MoonLite::Ack()
136 {
137  bool success = false;
138 
139  for (int i = 0; i < 3; i++)
140  {
141  if (readVersion())
142  {
143  success = true;
144  break;
145  }
146 
147  sleep(1);
148  }
149 
150  return success;
151 }
152 
153 bool MoonLite::readStepMode()
154 {
155  char res[ML_RES] = {0};
156 
157  if (sendCommand(":GH#", res) == false)
158  return false;
159 
160  if (strcmp(res, "FF#") == 0)
161  StepModeS[FOCUS_HALF_STEP].s = ISS_ON;
162  else if (strcmp(res, "00#") == 0)
163  StepModeS[FOCUS_FULL_STEP].s = ISS_ON;
164  else
165  {
166  LOGF_ERROR("Unknown error: focuser step value (%s)", res);
167  return false;
168  }
169 
170  return true;
171 }
172 
173 bool MoonLite::readVersion()
174 {
175  char res[ML_RES] = {0};
176 
177  if (sendCommand(":GV#", res, true, 2) == false)
178  return false;
179 
180  LOGF_INFO("Detected firmware version %c.%c", res[0], res[1]);
181 
182  return true;
183 }
184 
185 bool MoonLite::readTemperature()
186 {
187  char res[ML_RES] = {0};
188 
189  sendCommand(":C#");
190 
191  if (sendCommand(":GT#", res) == false)
192  return false;
193 
194  uint32_t temp = 0;
195  int rc = sscanf(res, "%X", &temp);
196  if (rc > 0)
197  // Signed hex
198  TemperatureN[0].value = static_cast<int16_t>(temp) / 2.0;
199  else
200  {
201  LOGF_ERROR("Unknown error: focuser temperature value (%s)", res);
202  return false;
203  }
204 
205  return true;
206 }
207 
208 bool MoonLite::readPosition()
209 {
210  char res[ML_RES] = {0};
211 
212  if (sendCommand(":GP#", res) == false)
213  return false;
214 
215  int32_t pos;
216  int rc = sscanf(res, "%X#", &pos);
217 
218  if (rc > 0)
219  FocusAbsPosN[0].value = pos;
220  else
221  {
222  LOGF_ERROR("Unknown error: focuser position value (%s)", res);
223  return false;
224  }
225 
226  return true;
227 }
228 
229 bool MoonLite::readSpeed()
230 {
231  char res[ML_RES] = {0};
232 
233  if (sendCommand(":GD#", res) == false)
234  return false;
235 
236  uint16_t speed = 0;
237  int rc = sscanf(res, "%hX#", &speed);
238 
239  if (rc > 0)
240  {
241  int focus_speed = -1;
242  while (speed > 0)
243  {
244  speed >>= 1;
245  focus_speed++;
246  }
247  FocusSpeedN[0].value = focus_speed;
248  }
249  else
250  {
251  LOGF_ERROR("Unknown error: focuser speed value (%s)", res);
252  return false;
253  }
254 
255  return true;
256 }
257 
258 bool MoonLite::isMoving()
259 {
260  char res[ML_RES] = {0};
261 
262  if (sendCommand(":GI#", res) == false)
263  return false;
264 
265  // JM 2020-03-13: 01# and 1# should be both accepted
266  if (strstr(res, "1#"))
267  return true;
268  else if (strstr(res, "0#"))
269  return false;
270 
271  LOGF_ERROR("Unknown error: isMoving value (%s)", res);
272  return false;
273 }
274 
275 bool MoonLite::setTemperatureCalibration(double calibration)
276 {
277  char cmd[ML_RES] = {0};
278  uint8_t hex = static_cast<int8_t>(calibration * 2) & 0xFF;
279  snprintf(cmd, ML_RES, ":PO%02X#", hex);
280  return sendCommand(cmd);
281 }
282 
283 bool MoonLite::setTemperatureCoefficient(double coefficient)
284 {
285  char cmd[ML_RES] = {0};
286  uint8_t hex = static_cast<int8_t>(coefficient * 2) & 0xFF;
287  snprintf(cmd, ML_RES, ":SC%02X#", hex);
288  return sendCommand(cmd);
289 }
290 
291 bool MoonLite::SyncFocuser(uint32_t ticks)
292 {
293  char cmd[ML_RES] = {0};
294  snprintf(cmd, ML_RES, ":SP%04X#", ticks);
295  return sendCommand(cmd);
296 }
297 
298 bool MoonLite::MoveFocuser(uint32_t position)
299 {
300  char cmd[ML_RES] = {0};
301  snprintf(cmd, ML_RES, ":SN%04X#", position);
302  // Set Position First
303  if (sendCommand(cmd) == false)
304  return false;
305  // Now start motion toward position
306  if (sendCommand(":FG#") == false)
307  return false;
308 
309  return true;
310 }
311 
312 bool MoonLite::setStepMode(FocusStepMode mode)
313 {
314  char cmd[ML_RES] = {0};
315  snprintf(cmd, ML_RES, ":S%c#", (mode == FOCUS_HALF_STEP) ? 'H' : 'F');
316  return sendCommand(cmd);
317 }
318 
319 bool MoonLite::setSpeed(int speed)
320 {
321  char cmd[ML_RES] = {0};
322  int hex_value = 1;
323  hex_value <<= speed;
324  snprintf(cmd, ML_RES, ":SD%02X#", hex_value);
325  return sendCommand(cmd);
326 }
327 
328 bool MoonLite::setTemperatureCompensation(bool enable)
329 {
330  char cmd[ML_RES] = {0};
331  snprintf(cmd, ML_RES, ":%c#", enable ? '+' : '-');
332  return sendCommand(cmd);
333 }
334 
335 bool MoonLite::ISNewSwitch(const char * dev, const char * name, ISState * states, char * names[], int n)
336 {
337  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
338  {
339  // Focus Step Mode
340  if (strcmp(StepModeSP.name, name) == 0)
341  {
342  int current_mode = IUFindOnSwitchIndex(&StepModeSP);
343 
344  IUUpdateSwitch(&StepModeSP, states, names, n);
345 
346  int target_mode = IUFindOnSwitchIndex(&StepModeSP);
347 
348  if (current_mode == target_mode)
349  {
350  StepModeSP.s = IPS_OK;
351  IDSetSwitch(&StepModeSP, nullptr);
352  }
353 
354  bool rc = setStepMode(target_mode == 0 ? FOCUS_HALF_STEP : FOCUS_FULL_STEP);
355  if (!rc)
356  {
357  IUResetSwitch(&StepModeSP);
358  StepModeS[current_mode].s = ISS_ON;
359  StepModeSP.s = IPS_ALERT;
360  IDSetSwitch(&StepModeSP, nullptr);
361  return false;
362  }
363 
364  StepModeSP.s = IPS_OK;
365  IDSetSwitch(&StepModeSP, nullptr);
366  return true;
367  }
368 
369  // Temperature Compensation Mode
370  if (strcmp(TemperatureCompensateSP.name, name) == 0)
371  {
372  int last_index = IUFindOnSwitchIndex(&TemperatureCompensateSP);
373  IUUpdateSwitch(&TemperatureCompensateSP, states, names, n);
374 
375  bool rc = setTemperatureCompensation((TemperatureCompensateS[0].s == ISS_ON));
376 
377  if (!rc)
378  {
379  TemperatureCompensateSP.s = IPS_ALERT;
380  IUResetSwitch(&TemperatureCompensateSP);
381  TemperatureCompensateS[last_index].s = ISS_ON;
382  IDSetSwitch(&TemperatureCompensateSP, nullptr);
383  return false;
384  }
385 
386  TemperatureCompensateSP.s = IPS_OK;
387  IDSetSwitch(&TemperatureCompensateSP, nullptr);
388  return true;
389  }
390  }
391 
392  return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
393 }
394 
395 bool MoonLite::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n)
396 {
397  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
398  {
399  // Temperature Settings
400  if (strcmp(name, TemperatureSettingNP.name) == 0)
401  {
402  IUUpdateNumber(&TemperatureSettingNP, values, names, n);
403  if (!setTemperatureCalibration(TemperatureSettingN[0].value) ||
404  !setTemperatureCoefficient(TemperatureSettingN[1].value))
405  {
406  TemperatureSettingNP.s = IPS_ALERT;
407  IDSetNumber(&TemperatureSettingNP, nullptr);
408  return false;
409  }
410 
411  TemperatureSettingNP.s = IPS_OK;
412  IDSetNumber(&TemperatureSettingNP, nullptr);
413  return true;
414  }
415  }
416 
417  return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
418 }
419 
420 void MoonLite::GetFocusParams()
421 {
422  if (readPosition())
423  IDSetNumber(&FocusAbsPosNP, nullptr);
424 
425  if (readTemperature())
426  IDSetNumber(&TemperatureNP, nullptr);
427 
428  if (readSpeed())
429  IDSetNumber(&FocusSpeedNP, nullptr);
430 
431  if (readStepMode())
432  IDSetSwitch(&StepModeSP, nullptr);
433 }
434 
436 {
437  return setSpeed(speed);
438 }
439 
440 IPState MoonLite::MoveFocuser(FocusDirection dir, int speed, uint16_t duration)
441 {
442  if (speed != static_cast<int>(FocusSpeedN[0].value))
443  {
444  if (!setSpeed(speed))
445  return IPS_ALERT;
446  }
447 
448  // either go all the way in or all the way out
449  // then use timer to stop
450  if (dir == FOCUS_INWARD)
451  MoveFocuser(0);
452  else
453  MoveFocuser(static_cast<uint32_t>(FocusMaxPosN[0].value));
454 
455  IEAddTimer(duration, &MoonLite::timedMoveHelper, this);
456  return IPS_BUSY;
457 }
458 
459 void MoonLite::timedMoveHelper(void * context)
460 {
461  static_cast<MoonLite *>(context)->timedMoveCallback();
462 }
463 
464 void MoonLite::timedMoveCallback()
465 {
466  AbortFocuser();
470  FocusTimerN[0].value = 0;
471  IDSetNumber(&FocusAbsPosNP, nullptr);
472  IDSetNumber(&FocusRelPosNP, nullptr);
473  IDSetNumber(&FocusTimerNP, nullptr);
474 }
475 
476 IPState MoonLite::MoveAbsFocuser(uint32_t targetTicks)
477 {
478  targetPos = targetTicks;
479 
480  if (!MoveFocuser(targetPos))
481  return IPS_ALERT;
482 
483  return IPS_BUSY;
484 }
485 
487 {
488  // Clamp
489  int32_t offset = ((dir == FOCUS_INWARD) ? -1 : 1) * static_cast<int32_t>(ticks);
490  int32_t newPosition = FocusAbsPosN[0].value + offset;
491  newPosition = std::max(static_cast<int32_t>(FocusAbsPosN[0].min), std::min(static_cast<int32_t>(FocusAbsPosN[0].max),
492  newPosition));
493 
494  if (!MoveFocuser(newPosition))
495  return IPS_ALERT;
496 
497  FocusRelPosN[0].value = ticks;
499 
500  return IPS_BUSY;
501 }
502 
504 {
505  if (!isConnected())
506  return;
507 
508  bool rc = readPosition();
509  if (rc)
510  {
511  if (fabs(lastPos - FocusAbsPosN[0].value) > 5)
512  {
513  IDSetNumber(&FocusAbsPosNP, nullptr);
514  lastPos = static_cast<uint32_t>(FocusAbsPosN[0].value);
515  }
516  }
517 
518  rc = readTemperature();
519  if (rc)
520  {
521  if (fabs(lastTemperature - TemperatureN[0].value) >= 0.5)
522  {
523  IDSetNumber(&TemperatureNP, nullptr);
524  lastTemperature = static_cast<uint32_t>(TemperatureN[0].value);
525  }
526  }
527 
529  {
530  if (!isMoving())
531  {
534  IDSetNumber(&FocusAbsPosNP, nullptr);
535  IDSetNumber(&FocusRelPosNP, nullptr);
536  lastPos = static_cast<uint32_t>(FocusAbsPosN[0].value);
537  LOG_INFO("Focuser reached requested position.");
538  }
539  }
540 
542 }
543 
545 {
546  return sendCommand(":FQ#");
547 }
548 
550 {
551  Focuser::saveConfigItems(fp);
552 
553  IUSaveConfigSwitch(fp, &StepModeSP);
554 
555  return true;
556 }
557 
558 bool MoonLite::sendCommand(const char * cmd, char * res, bool silent, int nret)
559 {
560  int nbytes_written = 0, nbytes_read = 0, rc = -1;
561 
562  tcflush(PortFD, TCIOFLUSH);
563 
564  LOGF_DEBUG("CMD <%s>", cmd);
565 
566  if ((rc = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
567  {
568  char errstr[MAXRBUF] = {0};
569  tty_error_msg(rc, errstr, MAXRBUF);
570  if (!silent)
571  LOGF_ERROR("Serial write error: %s.", errstr);
572  return false;
573  }
574 
575  if (res == nullptr)
576  {
577  tcdrain(PortFD);
578  return true;
579  }
580 
581  // this is to handle the GV command which doesn't return the terminator, use the number of chars expected
582  if (nret == 0)
583  {
584  rc = tty_nread_section(PortFD, res, ML_RES, ML_DEL, ML_TIMEOUT, &nbytes_read);
585  }
586  else
587  {
588  rc = tty_read(PortFD, res, nret, ML_TIMEOUT, &nbytes_read);
589  }
590  if (rc != TTY_OK)
591  {
592  char errstr[MAXRBUF] = {0};
593  tty_error_msg(rc, errstr, MAXRBUF);
594  if (!silent)
595  LOGF_ERROR("Serial read error: %s.", errstr);
596  return false;
597  }
598 
599  LOGF_DEBUG("RES <%s>", res);
600 
601  tcflush(PortFD, TCIOFLUSH);
602 
603  return true;
604 }
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
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.
INumberVectorProperty FocusSpeedNP
INumberVectorProperty FocusAbsPosNP
INumberVectorProperty FocusRelPosNP
INumberVectorProperty FocusTimerNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indifocuser.cpp:42
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual IPState MoveFocuser(FocusDirection dir, int speed, uint16_t duration) override
MoveFocuser Move focuser in a specific direction and speed for period of time.
Definition: moonlite.cpp:440
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
Definition: moonlite.cpp:549
static void timedMoveHelper(void *context)
Definition: moonlite.cpp:459
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: moonlite.cpp:503
virtual bool SetFocuserSpeed(int speed) override
SetFocuserSpeed Set Focuser speed.
Definition: moonlite.cpp:435
@ FOCUS_HALF_STEP
Definition: moonlite.h:33
@ FOCUS_FULL_STEP
Definition: moonlite.h:33
const char * getDefaultName() override
Definition: moonlite.cpp:130
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set the supplied position as the current focuser position.
Definition: moonlite.cpp:291
virtual bool Handshake() override
Handshake Try to communicate with Focuser and see if there is a valid response.
Definition: moonlite.cpp:117
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
Definition: moonlite.cpp:544
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: moonlite.cpp:335
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveAbsFocuser Move to an absolute target position.
Definition: moonlite.cpp:476
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: moonlite.cpp:91
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: moonlite.cpp:43
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: moonlite.cpp:395
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveRelFocuser Move focuser for a relative amount of ticks in a specific direction.
Definition: moonlite.cpp:486
MoonLite()
Definition: moonlite.cpp:34
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,...
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
Definition: eventloop.c:582
double max(void)
double min(void)
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
@ IP_RW
Definition: indiapi.h:186
@ IP_RO
Definition: indiapi.h:184
IPState
Property state.
Definition: indiapi.h:160
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_1OFMANY
Definition: indiapi.h:173
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition: indicom.c:482
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:474
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1167
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:666
Implementations for common driver routines.
@ TTY_OK
Definition: indicom.h:150
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indidevapi.c:25
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidevapi.c:272
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indidevapi.c:128
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indidevapi.c:148
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition: indidevapi.c:158
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
Definition: indidevapi.c:180
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidevapi.c:235
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:1362
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
#define LOG_INFO(txt)
Definition: indilogger.h:74
#define MAXRBUF
Definition: indiserver.cpp:102
__u8 cmd[4]
Definition: pwc-ioctl.h:2
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371