Instrument Neutral Distributed Interface INDI  1.9.5
pegasus_ppba.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2019 Jasem Mutlaq. All rights reserved.
3 
4  Pegasus Pocket Power Box Advance Driver.
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the Free
8  Software Foundation; either version 2 of the License, or (at your option)
9  any later version.
10 
11  This program is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 
21  The full GNU General Public License is included in this distribution in the
22  file called LICENSE.
23 *******************************************************************************/
24 
25 #include "pegasus_ppba.h"
26 #include "indicom.h"
28 
29 #include <regex>
30 #include <termios.h>
31 #include <chrono>
32 #include <iomanip>
33 
34 // We declare an auto pointer to PegasusPPBA.
35 static std::unique_ptr<PegasusPPBA> ppba(new PegasusPPBA());
36 
37 PegasusPPBA::PegasusPPBA() : FI(this), WI(this)
38 {
39  setVersion(1, 2);
40  lastSensorData.reserve(PA_N);
41  lastConsumptionData.reserve(PS_N);
42  lastMetricsData.reserve(PC_N);
43 }
44 
46 {
48 
50 
57 
59  WI::initProperties(ENVIRONMENT_TAB, ENVIRONMENT_TAB);
60 
62 
66  // Quad 12v Power
67  IUFillSwitch(&QuadOutS[INDI_ENABLED], "QUADOUT_ON", "Enable", ISS_OFF);
68  IUFillSwitch(&QuadOutS[INDI_DISABLED], "QUADOUT_OFF", "Disable", ISS_OFF);
69  IUFillSwitchVector(&QuadOutSP, QuadOutS, 2, getDeviceName(), "QUADOUT_POWER", "Quad Output", MAIN_CONTROL_TAB,
70  IP_RW, ISR_ATMOST1, 60, IPS_IDLE);
71 
72  // Adjustable Power
73  // IUFillSwitch(&AdjOutS[INDI_ENABLED], "ADJOUT_ON", "Enable", ISS_OFF);
74  // IUFillSwitch(&AdjOutS[INDI_DISABLED], "ADJOUT_OFF", "Disable", ISS_OFF);
75  // IUFillSwitchVector(&AdjOutSP, AdjOutS, 2, getDeviceName(), "ADJOUT_POWER", "Adj Output", MAIN_CONTROL_TAB, IP_RW,
76  // ISR_1OFMANY, 60, IPS_IDLE);
77 
78  // Adjustable Voltage
79  IUFillSwitch(&AdjOutVoltS[ADJOUT_OFF], "ADJOUT_OFF", "Off", ISS_ON);
80  IUFillSwitch(&AdjOutVoltS[ADJOUT_3V], "ADJOUT_3V", "3V", ISS_OFF);
81  IUFillSwitch(&AdjOutVoltS[ADJOUT_5V], "ADJOUT_5V", "5V", ISS_OFF);
82  IUFillSwitch(&AdjOutVoltS[ADJOUT_8V], "ADJOUT_8V", "8V", ISS_OFF);
83  IUFillSwitch(&AdjOutVoltS[ADJOUT_9V], "ADJOUT_9V", "9V", ISS_OFF);
84  IUFillSwitch(&AdjOutVoltS[ADJOUT_12V], "ADJOUT_12V", "12V", ISS_OFF);
85  IUFillSwitchVector(&AdjOutVoltSP, AdjOutVoltS, 6, getDeviceName(), "ADJOUT_VOLTAGE", "Adj voltage", MAIN_CONTROL_TAB, IP_RW,
86  ISR_1OFMANY, 60, IPS_IDLE);
87 
88  // Reboot
89  IUFillSwitch(&RebootS[0], "REBOOT", "Reboot Device", ISS_OFF);
90  IUFillSwitchVector(&RebootSP, RebootS, 1, getDeviceName(), "REBOOT_DEVICE", "Device", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1,
91  60, IPS_IDLE);
92 
93  // Power Sensors
94  IUFillNumber(&PowerSensorsN[SENSOR_VOLTAGE], "SENSOR_VOLTAGE", "Voltage (V)", "%4.2f", 0, 999, 100, 0);
95  IUFillNumber(&PowerSensorsN[SENSOR_CURRENT], "SENSOR_CURRENT", "Current (A)", "%4.2f", 0, 999, 100, 0);
96  IUFillNumber(&PowerSensorsN[SENSOR_AVG_AMPS], "SENSOR_AVG_AMPS", "Average Current (A)", "%4.2f", 0, 999, 100, 0);
97  IUFillNumber(&PowerSensorsN[SENSOR_AMP_HOURS], "SENSOR_AMP_HOURS", "Amp hours (Ah)", "%4.2f", 0, 999, 100, 0);
98  IUFillNumber(&PowerSensorsN[SENSOR_WATT_HOURS], "SENSOR_WATT_HOURS", "Watt hours (Wh)", "%4.2f", 0, 999, 100, 0);
99  IUFillNumber(&PowerSensorsN[SENSOR_TOTAL_CURRENT], "SENSOR_TOTAL_CURRENT", "Total current (A)", "%4.2f", 0, 999, 100, 0);
100  IUFillNumber(&PowerSensorsN[SENSOR_12V_CURRENT], "SENSOR_12V_CURRENT", "12V current (A)", "%4.2f", 0, 999, 100, 0);
101  IUFillNumber(&PowerSensorsN[SENSOR_DEWA_CURRENT], "SENSOR_DEWA_CURRENT", "DewA current (A)", "%4.2f", 0, 999, 100, 0);
102  IUFillNumber(&PowerSensorsN[SENSOR_DEWB_CURRENT], "SENSOR_DEWB_CURRENT", "DewB current (A)", "%4.2f", 0, 999, 100, 0);
103  IUFillNumberVector(&PowerSensorsNP, PowerSensorsN, 9, getDeviceName(), "POWER_SENSORS", "Sensors", MAIN_CONTROL_TAB, IP_RO,
104  60, IPS_IDLE);
105 
106  IUFillLight(&PowerWarnL[0], "POWER_WARN_ON", "Current Overload", IPS_IDLE);
107  IUFillLightVector(&PowerWarnLP, PowerWarnL, 1, getDeviceName(), "POWER_WARM", "Power Warn", MAIN_CONTROL_TAB, IPS_IDLE);
108 
109  // LED Indicator
110  IUFillSwitch(&LedIndicatorS[INDI_ENABLED], "LED_ON", "Enable", ISS_ON);
111  IUFillSwitch(&LedIndicatorS[INDI_DISABLED], "LED_OFF", "Disable", ISS_OFF);
112  IUFillSwitchVector(&LedIndicatorSP, LedIndicatorS, 2, getDeviceName(), "LED_INDICATOR", "LED Indicator", MAIN_CONTROL_TAB,
113  IP_RW,
114  ISR_1OFMANY, 60, IPS_IDLE);
115 
119 
120  // Power on Boot
121  IUFillSwitch(&PowerOnBootS[0], "POWER_PORT_1", "Quad Out", ISS_ON);
122  IUFillSwitch(&PowerOnBootS[1], "POWER_PORT_2", "Adj Out", ISS_ON);
123  IUFillSwitch(&PowerOnBootS[2], "POWER_PORT_3", "Dew A", ISS_ON);
124  IUFillSwitch(&PowerOnBootS[3], "POWER_PORT_4", "Dew B", ISS_ON);
125  IUFillSwitchVector(&PowerOnBootSP, PowerOnBootS, 4, getDeviceName(), "POWER_ON_BOOT", "Power On Boot", MAIN_CONTROL_TAB,
126  IP_RW, ISR_NOFMANY, 60, IPS_IDLE);
127 
131 
132  // Automatic Dew
133  IUFillSwitch(&AutoDewS[INDI_ENABLED], "INDI_ENABLED", "Enabled", ISS_OFF);
134  IUFillSwitch(&AutoDewS[INDI_DISABLED], "INDI_DISABLED", "Disabled", ISS_OFF);
135  IUFillSwitchVector(&AutoDewSP, AutoDewS, 2, getDeviceName(), "AUTO_DEW", "Auto Dew", DEW_TAB, IP_RW, ISR_1OFMANY, 60,
136  IPS_IDLE);
137 
138  // Dew PWM
139  IUFillNumber(&DewPWMN[DEW_PWM_A], "DEW_A", "Dew A (%)", "%.2f", 0, 100, 10, 0);
140  IUFillNumber(&DewPWMN[DEW_PWM_B], "DEW_B", "Dew B (%)", "%.2f", 0, 100, 10, 0);
141  IUFillNumberVector(&DewPWMNP, DewPWMN, 2, getDeviceName(), "DEW_PWM", "Dew PWM", DEW_TAB, IP_RW, 60, IPS_IDLE);
142 
146  IUFillText(&FirmwareT[FIRMWARE_VERSION], "VERSION", "Version", "NA");
147  IUFillText(&FirmwareT[FIRMWARE_UPTIME], "UPTIME", "Uptime (h)", "NA");
148  IUFillTextVector(&FirmwareTP, FirmwareT, 2, getDeviceName(), "FIRMWARE_INFO", "Firmware", FIRMWARE_TAB, IP_RO, 60,
149  IPS_IDLE);
150 
154  addParameter("WEATHER_TEMPERATURE", "Temperature (C)", -15, 35, 15);
155  addParameter("WEATHER_HUMIDITY", "Humidity %", 0, 100, 15);
156  addParameter("WEATHER_DEWPOINT", "Dew Point (C)", 0, 100, 15);
157  setCriticalParameter("WEATHER_TEMPERATURE");
158 
162 
163  // Max Speed
164  IUFillNumber(&FocuserSettingsN[SETTING_MAX_SPEED], "SETTING_MAX_SPEED", "Max Speed (%)", "%.f", 0, 900, 100, 400);
165  IUFillNumberVector(&FocuserSettingsNP, FocuserSettingsN, 1, getDeviceName(), "FOCUSER_SETTINGS", "Settings", FOCUS_TAB,
166  IP_RW, 60, IPS_IDLE);
167 
168  // Stepping
169  IUFillSwitch(&FocuserDriveS[STEP_FULL], "STEP_FULL", "Full", ISS_OFF);
170  IUFillSwitch(&FocuserDriveS[STEP_HALF], "STEP_HALF", "Half", ISS_ON);
171  IUFillSwitch(&FocuserDriveS[STEP_FORTH], "STEP_FORTH", "1/4", ISS_OFF);
172  IUFillSwitch(&FocuserDriveS[STEP_EIGHTH], "STEP_EIGHTH", "1/8", ISS_OFF);
173  IUFillSwitchVector(&FocuserDriveSP, FocuserDriveS, 4, getDeviceName(), "FOCUSER_DRIVE", "Microstepping", FOCUS_TAB,
174  IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
175 
179  serialConnection = new Connection::Serial(this);
180  serialConnection->registerHandshake([&]()
181  {
182  return Handshake();
183  });
184  registerConnection(serialConnection);
185 
186  return true;
187 }
188 
190 {
192 
193  if (isConnected())
194  {
195  m_HasExternalMotor = findExternalMotorController();
196 
197  if (m_HasExternalMotor)
198  {
199  getXMCStartupData();
201  syncDriverInfo();
202  }
203 
204  // Main Control
205  defineProperty(&QuadOutSP);
206  //defineProperty(&AdjOutSP);
207  defineProperty(&AdjOutVoltSP);
208  defineProperty(&PowerSensorsNP);
209  defineProperty(&PowerOnBootSP);
210  defineProperty(&RebootSP);
211  defineProperty(&PowerWarnLP);
212  defineProperty(&LedIndicatorSP);
213 
214  // Dew
215  defineProperty(&AutoDewSP);
216  defineProperty(&DewPWMNP);
217 
218  // Focuser
219  if (m_HasExternalMotor)
220  {
222  defineProperty(&FocuserSettingsNP);
223  defineProperty(&FocuserDriveSP);
224  }
225 
227 
228  // Firmware
229  defineProperty(&FirmwareTP);
230 
231  setupComplete = true;
232  }
233  else
234  {
235  // Main Control
236  deleteProperty(QuadOutSP.name);
237  //deleteProperty(AdjOutSP.name);
238  deleteProperty(AdjOutVoltSP.name);
239  deleteProperty(PowerSensorsNP.name);
240  deleteProperty(PowerOnBootSP.name);
241  deleteProperty(RebootSP.name);
242  deleteProperty(PowerWarnLP.name);
243  deleteProperty(LedIndicatorSP.name);
244 
245  // Dew
246  deleteProperty(AutoDewSP.name);
247  deleteProperty(DewPWMNP.name);
248 
249  if (m_HasExternalMotor)
250  {
252  deleteProperty(FocuserSettingsNP.name);
253  deleteProperty(FocuserDriveSP.name);
254  }
255 
257 
258  deleteProperty(FirmwareTP.name);
259 
260  setupComplete = false;
261  }
262 
263  return true;
264 }
265 
267 {
268  return "Pegasus PPBA";
269 }
270 
271 bool PegasusPPBA::Handshake()
272 {
273  int tty_rc = 0, nbytes_written = 0, nbytes_read = 0;
274  char command[PEGASUS_LEN] = {0}, response[PEGASUS_LEN] = {0};
275 
276  PortFD = serialConnection->getPortFD();
277 
278  LOG_DEBUG("CMD <P#>");
279 
280  tcflush(PortFD, TCIOFLUSH);
281  strncpy(command, "P#\n", PEGASUS_LEN);
282  if ( (tty_rc = tty_write_string(PortFD, command, &nbytes_written)) != TTY_OK)
283  {
284  char errorMessage[MAXRBUF];
285  tty_error_msg(tty_rc, errorMessage, MAXRBUF);
286  LOGF_ERROR("Serial write error: %s", errorMessage);
287  return false;
288  }
289 
290  // Try first with stopChar as the stop character
291  if ( (tty_rc = tty_nread_section(PortFD, response, PEGASUS_LEN, stopChar, 1, &nbytes_read)) != TTY_OK)
292  {
293  // Try 0xA as the stop character
294  if (tty_rc == TTY_OVERFLOW || tty_rc == TTY_TIME_OUT)
295  {
296  tcflush(PortFD, TCIOFLUSH);
297  tty_write_string(PortFD, command, &nbytes_written);
298  stopChar = 0xA;
299  tty_rc = tty_nread_section(PortFD, response, PEGASUS_LEN, stopChar, 1, &nbytes_read);
300  }
301 
302  if (tty_rc != TTY_OK)
303  {
304  char errorMessage[MAXRBUF];
305  tty_error_msg(tty_rc, errorMessage, MAXRBUF);
306  LOGF_ERROR("Serial read error: %s", errorMessage);
307  return false;
308  }
309  }
310 
311  tcflush(PortFD, TCIOFLUSH);
312  response[nbytes_read - 1] = '\0';
313  LOGF_DEBUG("RES <%s>", response);
314 
315  setupComplete = false;
316 
317  return (!strcmp(response, "PPBA_OK") || !strcmp(response, "PPBM_OK"));
318 }
319 
320 bool PegasusPPBA::ISNewSwitch(const char * dev, const char * name, ISState * states, char * names[], int n)
321 {
322  if (dev && !strcmp(dev, getDeviceName()))
323  {
324  // Quad 12V Power
325  if (!strcmp(name, QuadOutSP.name))
326  {
327  IUUpdateSwitch(&QuadOutSP, states, names, n);
328 
329  QuadOutSP.s = IPS_ALERT;
330  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
331  snprintf(cmd, PEGASUS_LEN, "P1:%d", QuadOutS[INDI_ENABLED].s == ISS_ON);
332  if (sendCommand(cmd, res))
333  {
334  QuadOutSP.s = !strcmp(cmd, res) ? IPS_OK : IPS_ALERT;
335  }
336 
337  IUResetSwitch(&QuadOutSP);
338  IDSetSwitch(&QuadOutSP, nullptr);
339  return true;
340  }
341 
342  // // Adjustable Power
343  // if (!strcmp(name, AdjOutSP.name))
344  // {
345  // IUUpdateSwitch(&AdjOutSP, states, names, n);
346 
347  // AdjOutSP.s = IPS_ALERT;
348  // char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
349  // snprintf(cmd, PEGASUS_LEN, "P2:%d", AdjOutS[INDI_ENABLED].s == ISS_ON);
350  // if (sendCommand(cmd, res))
351  // {
352  // AdjOutSP.s = !strcmp(cmd, res) ? IPS_OK : IPS_ALERT;
353  // }
354 
355  // IUResetSwitch(&AdjOutSP);
356  // IDSetSwitch(&AdjOutSP, nullptr);
357  // return true;
358  // }
359 
360  // Adjustable Voltage
361  if (!strcmp(name, AdjOutVoltSP.name))
362  {
363  int previous_index = IUFindOnSwitchIndex(&AdjOutVoltSP);
364  IUUpdateSwitch(&AdjOutVoltSP, states, names, n);
365  int target_index = IUFindOnSwitchIndex(&AdjOutVoltSP);
366  int adjv = 0;
367  switch(target_index)
368  {
369  case ADJOUT_OFF:
370  adjv = 0;
371  break;
372  case ADJOUT_3V:
373  adjv = 3;
374  break;
375  case ADJOUT_5V:
376  adjv = 5;
377  break;
378  case ADJOUT_8V:
379  adjv = 8;
380  break;
381  case ADJOUT_9V:
382  adjv = 9;
383  break;
384  case ADJOUT_12V:
385  adjv = 12;
386  break;
387  }
388 
389  AdjOutVoltSP.s = IPS_ALERT;
390  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
391  snprintf(cmd, PEGASUS_LEN, "P2:%d", adjv);
392  if (sendCommand(cmd, res))
393  AdjOutVoltSP.s = IPS_OK;
394  else
395  {
396  IUResetSwitch(&AdjOutVoltSP);
397  AdjOutVoltS[previous_index].s = ISS_ON;
398  AdjOutVoltSP.s = IPS_ALERT;
399  }
400 
401  IDSetSwitch(&AdjOutVoltSP, nullptr);
402  return true;
403  }
404 
405  // Reboot
406  if (!strcmp(name, RebootSP.name))
407  {
408  RebootSP.s = reboot() ? IPS_OK : IPS_ALERT;
409  IDSetSwitch(&RebootSP, nullptr);
410  LOG_INFO("Rebooting device...");
411  return true;
412  }
413 
414  // LED Indicator
415  if (!strcmp(name, LedIndicatorSP.name))
416  {
417  IUUpdateSwitch(&LedIndicatorSP, states, names, n);
418  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
419  snprintf(cmd, PEGASUS_LEN, "PL:%d", LedIndicatorS[INDI_ENABLED].s == ISS_ON);
420  if (sendCommand(cmd, res))
421  {
422  LedIndicatorSP.s = !strcmp(cmd, res) ? IPS_OK : IPS_ALERT;
423  }
424  IDSetSwitch(&LedIndicatorSP, nullptr);
425  saveConfig(true, LedIndicatorSP.name);
426  return true;
427  }
428 
429  // Power on boot
430  if (!strcmp(name, PowerOnBootSP.name))
431  {
432  IUUpdateSwitch(&PowerOnBootSP, states, names, n);
433  PowerOnBootSP.s = setPowerOnBoot() ? IPS_OK : IPS_ALERT;
434  IDSetSwitch(&PowerOnBootSP, nullptr);
435  saveConfig(true, PowerOnBootSP.name);
436  return true;
437  }
438 
439  // Auto Dew
440  if (!strcmp(name, AutoDewSP.name))
441  {
442  int prevIndex = IUFindOnSwitchIndex(&AutoDewSP);
443  IUUpdateSwitch(&AutoDewSP, states, names, n);
444  if (setAutoDewEnabled(AutoDewS[INDI_ENABLED].s == ISS_ON))
445  {
446  AutoDewSP.s = IPS_OK;
447  }
448  else
449  {
450  IUResetSwitch(&AutoDewSP);
451  AutoDewS[prevIndex].s = ISS_ON;
452  AutoDewSP.s = IPS_ALERT;
453  }
454 
455  IDSetSwitch(&AutoDewSP, nullptr);
456  return true;
457  }
458 
459  // Microstepping
460  if (!strcmp(name, FocuserDriveSP.name))
461  {
462  int prevIndex = IUFindOnSwitchIndex(&FocuserDriveSP);
463  IUUpdateSwitch(&FocuserDriveSP, states, names, n);
464  if (setFocuserMicrosteps(IUFindOnSwitchIndex(&FocuserDriveSP) + 1))
465  {
466  FocuserDriveSP.s = IPS_OK;
467  }
468  else
469  {
470  IUResetSwitch(&FocuserDriveSP);
471  FocuserDriveS[prevIndex].s = ISS_ON;
472  FocuserDriveSP.s = IPS_ALERT;
473  }
474 
475  IDSetSwitch(&FocuserDriveSP, nullptr);
476  return true;
477  }
478 
479  if (strstr(name, "FOCUS"))
480  return FI::processSwitch(dev, name, states, names, n);
481  }
482 
483  return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
484 }
485 
486 bool PegasusPPBA::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n)
487 {
488  if (dev && !strcmp(dev, getDeviceName()))
489  {
490  // Dew PWM
491  if (!strcmp(name, DewPWMNP.name))
492  {
493  bool rc1 = false, rc2 = false;
494  for (int i = 0; i < n; i++)
495  {
496  if (!strcmp(names[i], DewPWMN[DEW_PWM_A].name))
497  rc1 = setDewPWM(3, static_cast<uint8_t>(values[i] / 100.0 * 255.0));
498  else if (!strcmp(names[i], DewPWMN[DEW_PWM_B].name))
499  rc2 = setDewPWM(4, static_cast<uint8_t>(values[i] / 100.0 * 255.0));
500  }
501 
502  DewPWMNP.s = (rc1 && rc2) ? IPS_OK : IPS_ALERT;
503  if (DewPWMNP.s == IPS_OK)
504  IUUpdateNumber(&DewPWMNP, values, names, n);
505  IDSetNumber(&DewPWMNP, nullptr);
506  return true;
507  }
508 
509  // Focuser Settings
510  if (!strcmp(name, FocuserSettingsNP.name))
511  {
512  if (setFocuserMaxSpeed(values[0]))
513  {
514  FocuserSettingsN[0].value = values[0];
515  FocuserSettingsNP.s = IPS_OK;
516  }
517  else
518  {
519  FocuserSettingsNP.s = IPS_ALERT;
520  }
521 
522  IDSetNumber(&FocuserSettingsNP, nullptr);
523  return true;
524  }
525 
526  if (strstr(name, "FOCUS_"))
527  return FI::processNumber(dev, name, values, names, n);
528 
529  if (strstr(name, "WEATHER_"))
530  return WI::processNumber(dev, name, values, names, n);
531  }
532  return INDI::DefaultDevice::ISNewNumber(dev, name, values, names, n);
533 }
534 
535 bool PegasusPPBA::sendCommand(const char * cmd, char * res)
536 {
537  int nbytes_read = 0, nbytes_written = 0, tty_rc = 0;
538  char command[PEGASUS_LEN] = {0};
539  LOGF_DEBUG("CMD <%s>", cmd);
540 
541  for (int i = 0; i < 2; i++)
542  {
543  tcflush(PortFD, TCIOFLUSH);
544  snprintf(command, PEGASUS_LEN, "%s\n", cmd);
545  if ( (tty_rc = tty_write_string(PortFD, command, &nbytes_written)) != TTY_OK)
546  continue;
547 
548  if (!res)
549  {
550  tcflush(PortFD, TCIOFLUSH);
551  return true;
552  }
553 
554  if ( (tty_rc = tty_nread_section(PortFD, res, PEGASUS_LEN, stopChar, PEGASUS_TIMEOUT, &nbytes_read)) != TTY_OK
555  || nbytes_read == 1)
556  continue;
557 
558  tcflush(PortFD, TCIOFLUSH);
559  res[nbytes_read - 1] = '\0';
560  LOGF_DEBUG("RES <%s>", res);
561  return true;
562  }
563 
564  if (tty_rc != TTY_OK)
565  {
566  char errorMessage[MAXRBUF];
567  tty_error_msg(tty_rc, errorMessage, MAXRBUF);
568  LOGF_ERROR("Serial error: %s", errorMessage);
569  }
570 
571  return false;
572 }
573 
574 bool PegasusPPBA::findExternalMotorController()
575 {
576  char res[PEGASUS_LEN] = {0};
577  if (!sendCommand("XS", res))
578  return false;
579 
580  // 200 XMC present
581  return strstr(res, "200");
582 }
583 
584 bool PegasusPPBA::setAutoDewEnabled(bool enabled)
585 {
586  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
587  snprintf(cmd, PEGASUS_LEN, "PD:%d", enabled ? 1 : 0);
588  if (sendCommand(cmd, res))
589  {
590  return (!strcmp(res, cmd));
591  }
592 
593  return false;
594 }
595 
596 bool PegasusPPBA::setPowerOnBoot()
597 {
598  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
599  snprintf(cmd, PEGASUS_LEN, "PE:%d%d%d%d", PowerOnBootS[0].s == ISS_ON ? 1 : 0,
600  PowerOnBootS[1].s == ISS_ON ? 1 : 0,
601  PowerOnBootS[2].s == ISS_ON ? 1 : 0,
602  PowerOnBootS[3].s == ISS_ON ? 1 : 0);
603  if (sendCommand(cmd, res))
604  {
605  return (!strcmp(res, "PE:1"));
606  }
607 
608  return false;
609 }
610 
611 bool PegasusPPBA::setDewPWM(uint8_t id, uint8_t value)
612 {
613  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0}, expected[PEGASUS_LEN] = {0};
614  snprintf(cmd, PEGASUS_LEN, "P%d:%03d", id, value);
615  snprintf(expected, PEGASUS_LEN, "P%d:%d", id, value);
616  if (sendCommand(cmd, res))
617  {
618  return (!strcmp(res, expected));
619  }
620 
621  return false;
622 }
623 
625 {
627  if (m_HasExternalMotor)
628  {
630  IUSaveConfigNumber(fp, &FocuserSettingsNP);
631  IUSaveConfigSwitch(fp, &FocuserDriveSP);
632  }
634  IUSaveConfigSwitch(fp, &AutoDewSP);
635  return true;
636 }
637 
639 {
640  if (!isConnected() || setupComplete == false)
641  {
643  return;
644  }
645 
646  getSensorData();
647  getConsumptionData();
648  getMetricsData();
649 
650  if (m_HasExternalMotor)
651  queryXMC();
652 
654 }
655 
656 bool PegasusPPBA::sendFirmware()
657 {
658  char res[PEGASUS_LEN] = {0};
659  if (sendCommand("PV", res))
660  {
661  LOGF_INFO("Detected firmware %s", res);
662  IUSaveText(&FirmwareT[FIRMWARE_VERSION], res);
663  IDSetText(&FirmwareTP, nullptr);
664  return true;
665  }
666 
667  return false;
668 }
669 
670 bool PegasusPPBA::getSensorData()
671 {
672  char res[PEGASUS_LEN] = {0};
673  if (sendCommand("PA", res))
674  {
675  std::vector<std::string> result = split(res, ":");
676  if (result.size() < PA_N)
677  {
678  LOG_WARN("Received wrong number of detailed sensor data. Retrying...");
679  return false;
680  }
681 
682  if (result == lastSensorData)
683  return true;
684 
685  // Power Sensors
686  PowerSensorsN[SENSOR_VOLTAGE].value = std::stod(result[PA_VOLTAGE]);
687  PowerSensorsN[SENSOR_CURRENT].value = std::stod(result[PA_CURRENT]) / 65.0;
688  PowerSensorsNP.s = IPS_OK;
689  if (lastSensorData[PA_VOLTAGE] != result[PA_VOLTAGE] || lastSensorData[PA_CURRENT] != result[PA_CURRENT])
690  IDSetNumber(&PowerSensorsNP, nullptr);
691 
692  // Environment Sensors
693  setParameterValue("WEATHER_TEMPERATURE", std::stod(result[PA_TEMPERATURE]));
694  setParameterValue("WEATHER_HUMIDITY", std::stod(result[PA_HUMIDITY]));
695  setParameterValue("WEATHER_DEWPOINT", std::stod(result[PA_DEW_POINT]));
696  if (lastSensorData[PA_TEMPERATURE] != result[PA_TEMPERATURE] ||
697  lastSensorData[PA_HUMIDITY] != result[PA_HUMIDITY] ||
698  lastSensorData[PA_DEW_POINT] != result[PA_DEW_POINT])
699  {
701  IDSetLight(&critialParametersLP, nullptr);
703  IDSetNumber(&ParametersNP, nullptr);
704  }
705 
706  // Power Status
707  QuadOutS[INDI_ENABLED].s = (std::stoi(result[PA_PORT_STATUS]) == 1) ? ISS_ON : ISS_OFF;
708  QuadOutS[INDI_DISABLED].s = (std::stoi(result[PA_PORT_STATUS]) == 1) ? ISS_OFF : ISS_ON;
709  QuadOutSP.s = (std::stoi(result[6]) == 1) ? IPS_OK : IPS_IDLE;
710  if (lastSensorData[PA_PORT_STATUS] != result[PA_PORT_STATUS])
711  IDSetSwitch(&QuadOutSP, nullptr);
712 
713  // Adjustable Power Status
714  // AdjOutS[INDI_ENABLED].s = (std::stoi(result[PA_ADJ_STATUS]) == 1) ? ISS_ON : ISS_OFF;
715  // AdjOutS[INDI_DISABLED].s = (std::stoi(result[PA_ADJ_STATUS]) == 1) ? ISS_OFF : ISS_ON;
716  // AdjOutSP.s = (std::stoi(result[PA_ADJ_STATUS]) == 1) ? IPS_OK : IPS_IDLE;
717  // if (lastSensorData[PA_ADJ_STATUS] != result[PA_ADJ_STATUS])
718  // IDSetSwitch(&AdjOutSP, nullptr);
719 
720  // Adjustable Power Status
721  IUResetSwitch(&AdjOutVoltSP);
722  if (std::stoi(result[PA_ADJ_STATUS]) == 0)
723  AdjOutVoltS[ADJOUT_OFF].s = ISS_ON;
724  else
725  {
726  AdjOutVoltS[ADJOUT_3V].s = (std::stoi(result[PA_PWRADJ]) == 3) ? ISS_ON : ISS_OFF;
727  AdjOutVoltS[ADJOUT_5V].s = (std::stoi(result[PA_PWRADJ]) == 5) ? ISS_ON : ISS_OFF;
728  AdjOutVoltS[ADJOUT_8V].s = (std::stoi(result[PA_PWRADJ]) == 8) ? ISS_ON : ISS_OFF;
729  AdjOutVoltS[ADJOUT_9V].s = (std::stoi(result[PA_PWRADJ]) == 9) ? ISS_ON : ISS_OFF;
730  AdjOutVoltS[ADJOUT_12V].s = (std::stoi(result[PA_PWRADJ]) == 12) ? ISS_ON : ISS_OFF;
731  }
732  if (lastSensorData[PA_PWRADJ] != result[PA_PWRADJ] || lastSensorData[PA_ADJ_STATUS] != result[PA_ADJ_STATUS])
733  IDSetSwitch(&AdjOutVoltSP, nullptr);
734 
735  // Power Warn
736  PowerWarnL[0].s = (std::stoi(result[PA_PWR_WARN]) == 1) ? IPS_ALERT : IPS_OK;
737  PowerWarnLP.s = (std::stoi(result[PA_PWR_WARN]) == 1) ? IPS_ALERT : IPS_OK;
738  if (lastSensorData[PA_PWR_WARN] != result[PA_PWR_WARN])
739  IDSetLight(&PowerWarnLP, nullptr);
740 
741  // Dew PWM
742  DewPWMN[0].value = std::stod(result[PA_DEW_1]) / 255.0 * 100.0;
743  DewPWMN[1].value = std::stod(result[PA_DEW_2]) / 255.0 * 100.0;
744  if (lastSensorData[PA_DEW_1] != result[PA_DEW_1] || lastSensorData[PA_DEW_2] != result[PA_DEW_2])
745  IDSetNumber(&DewPWMNP, nullptr);
746 
747  // Auto Dew
748  AutoDewS[INDI_DISABLED].s = (std::stoi(result[PA_AUTO_DEW]) == 1) ? ISS_OFF : ISS_ON;
749  AutoDewS[INDI_ENABLED].s = (std::stoi(result[PA_AUTO_DEW]) == 1) ? ISS_ON : ISS_OFF;
750  AutoDewSP.s = (std::stoi(result[PA_AUTO_DEW]) == 1) ? IPS_OK : IPS_IDLE;
751  if (lastSensorData[PA_AUTO_DEW] != result[PA_AUTO_DEW])
752  IDSetSwitch(&AutoDewSP, nullptr);
753 
754  lastSensorData = result;
755 
756  return true;
757  }
758 
759  return false;
760 }
761 
762 bool PegasusPPBA::getConsumptionData()
763 {
764  char res[PEGASUS_LEN] = {0};
765  if (sendCommand("PS", res))
766  {
767  std::vector<std::string> result = split(res, ":");
768  if (result.size() < PS_N)
769  {
770  LOG_WARN("Received wrong number of detailed consumption data. Retrying...");
771  return false;
772  }
773 
774  if (result == lastConsumptionData)
775  return true;
776 
777  // Power Sensors
778  PowerSensorsN[SENSOR_AVG_AMPS].value = std::stod(result[PS_AVG_AMPS]);
779  PowerSensorsN[SENSOR_AMP_HOURS].value = std::stod(result[PS_AMP_HOURS]);
780  PowerSensorsN[SENSOR_WATT_HOURS].value = std::stod(result[PS_WATT_HOURS]);
781  PowerSensorsNP.s = IPS_OK;
782  if (lastConsumptionData[PS_AVG_AMPS] != result[PS_AVG_AMPS] || lastConsumptionData[PS_AMP_HOURS] != result[PS_AMP_HOURS]
783  || lastConsumptionData[PS_WATT_HOURS] != result[PS_WATT_HOURS])
784  IDSetNumber(&PowerSensorsNP, nullptr);
785 
786  lastConsumptionData = result;
787 
788  return true;
789  }
790 
791  return false;
792 }
793 
794 bool PegasusPPBA::getMetricsData()
795 {
796  char res[PEGASUS_LEN] = {0};
797  if (sendCommand("PC", res))
798  {
799  std::vector<std::string> result = split(res, ":");
800  if (result.size() < PC_N)
801  {
802  LOG_WARN("Received wrong number of detailed metrics data. Retrying...");
803  return false;
804  }
805 
806  if (result == lastMetricsData)
807  return true;
808 
809  // Power Sensors
810  PowerSensorsN[SENSOR_TOTAL_CURRENT].value = std::stod(result[PC_TOTAL_CURRENT]);
811  PowerSensorsN[SENSOR_12V_CURRENT].value = std::stod(result[PC_12V_CURRENT]);
812  PowerSensorsN[SENSOR_DEWA_CURRENT].value = std::stod(result[PC_DEWA_CURRENT]);
813  PowerSensorsN[SENSOR_DEWB_CURRENT].value = std::stod(result[PC_DEWB_CURRENT]);
814  PowerSensorsNP.s = IPS_OK;
815  if (lastMetricsData[PC_TOTAL_CURRENT] != result[PC_TOTAL_CURRENT] ||
816  lastMetricsData[PC_12V_CURRENT] != result[PC_12V_CURRENT] ||
817  lastMetricsData[PC_DEWA_CURRENT] != result[PC_DEWA_CURRENT] ||
818  lastMetricsData[PC_DEWB_CURRENT] != result[PC_DEWB_CURRENT])
819  IDSetNumber(&PowerSensorsNP, nullptr);
820 
821  std::chrono::milliseconds uptime(std::stol(result[PC_UPTIME]));
822  using dhours = std::chrono::duration<double, std::ratio<3600>>;
823  std::stringstream ss;
824  ss << std::fixed << std::setprecision(3) << dhours(uptime).count();
825  IUSaveText(&FirmwareT[FIRMWARE_UPTIME], ss.str().c_str());
826  IDSetText(&FirmwareTP, nullptr);
827 
828  lastMetricsData = result;
829 
830  return true;
831  }
832 
833  return false;
834 }
835 // Device Control
836 bool PegasusPPBA::reboot()
837 {
838  return sendCommand("PF", nullptr);
839 }
840 
845 {
846  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
847  snprintf(cmd, PEGASUS_LEN, "XS:3#%u", targetTicks);
848  return (sendCommand(cmd, res) ? IPS_BUSY : IPS_ALERT);
849 }
850 
855 {
856  return MoveAbsFocuser(dir == FOCUS_INWARD ? FocusAbsPosN[0].value - ticks : FocusAbsPosN[0].value + ticks);
857 }
858 
863 {
864  return sendCommand("XS:6", nullptr);
865 }
866 
870 bool PegasusPPBA::ReverseFocuser(bool enabled)
871 {
872  char cmd[PEGASUS_LEN] = {0};
873  snprintf(cmd, PEGASUS_LEN, "XS:8#%d", enabled ? 1 : 0);
874  return sendCommand(cmd, nullptr);
875 }
876 
880 bool PegasusPPBA::SyncFocuser(uint32_t ticks)
881 {
882  char cmd[PEGASUS_LEN] = {0};
883  snprintf(cmd, PEGASUS_LEN, "XS:5#%u", ticks);
884  return sendCommand(cmd, nullptr);
885 }
886 
891 {
892  char cmd[PEGASUS_LEN] = {0};
893  snprintf(cmd, PEGASUS_LEN, "XS:10#%d", steps);
894  return sendCommand(cmd, nullptr);
895 }
896 
900 bool PegasusPPBA::setFocuserMaxSpeed(uint16_t maxSpeed)
901 {
902  char cmd[PEGASUS_LEN] = {0};
903  snprintf(cmd, PEGASUS_LEN, "XS:7#%d", maxSpeed);
904  return sendCommand(cmd, nullptr);
905 }
906 
907 bool PegasusPPBA::setFocuserMicrosteps(int value)
908 {
909  char cmd[PEGASUS_LEN] = {0};
910  snprintf(cmd, PEGASUS_LEN, "XS:9#%d", value);
911  return sendCommand(cmd, nullptr);
912 }
913 
918 {
919  char cmd[PEGASUS_LEN] = {0};
920  snprintf(cmd, PEGASUS_LEN, "XS:8#%d", enabled ? 1 : 0);
921  return sendCommand(cmd, nullptr);
922 }
923 
927 bool PegasusPPBA::getXMCStartupData()
928 {
929  char res[PEGASUS_LEN] = {0};
930 
931  // Position
932  if (sendCommand("XS:2", res))
933  {
934  uint32_t position = 0;
935  sscanf(res, "%*[^#]#%d", &position);
936  FocusAbsPosN[0].value = position;
937  }
938 
939  // Max speed
940  if (sendCommand("XS:7", res))
941  {
942  uint32_t speed = 0;
943  sscanf(res, "%*[^#]#%d", &speed);
944  FocuserSettingsN[0].value = speed;
945  }
946 
947  return true;
948 }
949 
953 void PegasusPPBA::queryXMC()
954 {
955  char res[PEGASUS_LEN] = {0};
956  uint32_t position = 0;
957  uint32_t motorRunning = 0;
958 
959  // Get Motor Status
960  if (sendCommand("XS:1", res))
961  sscanf(res, "%*[^#]#%d", &motorRunning);
962  // Get Position
963  if (sendCommand("XS:2", res))
964  sscanf(res, "%*[^#]#%d", &position);
965 
966  uint32_t lastPosition = FocusAbsPosN[0].value;
967  FocusAbsPosN[0].value = position;
968 
969  if (FocusAbsPosNP.s == IPS_BUSY && motorRunning == 0)
970  {
973  IDSetNumber(&FocusAbsPosNP, nullptr);
974  IDSetNumber(&FocusRelPosNP, nullptr);
975  }
976  else if (lastPosition != position)
977  IDSetNumber(&FocusAbsPosNP, nullptr);
978 
979 }
983 std::vector<std::string> PegasusPPBA::split(const std::string &input, const std::string &regex)
984 {
985  // passing -1 as the submatch index parameter performs splitting
986  std::regex re(regex);
987  std::sregex_token_iterator
988  first{input.begin(), input.end(), re, -1},
989  last;
990  return {first, last};
991 }
992 
PegasusPPBA::MoveAbsFocuser
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
Definition: pegasus_ppba.cpp:844
PegasusPPBA::ReverseFocuser
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
Definition: pegasus_ppba.cpp:870
INDI::FocuserInterface::FOCUSER_CAN_ABS_MOVE
@ FOCUSER_CAN_ABS_MOVE
Definition: indifocuserinterface.h:74
PegasusPPBA::MoveRelFocuser
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
Definition: pegasus_ppba.cpp:854
IP_RO
@ IP_RO
Definition: indiapi.h:183
INDI::FocuserInterface::FOCUSER_CAN_SYNC
@ FOCUSER_CAN_SYNC
Definition: indifocuserinterface.h:78
INDI::FocuserInterface::FOCUSER_CAN_REL_MOVE
@ FOCUSER_CAN_REL_MOVE
Definition: indifocuserinterface.h:75
INDI::FocuserInterface::FocusAbsPosNP
INumberVectorProperty FocusAbsPosNP
Definition: indifocuserinterface.h:282
INDI::WeatherInterface::initProperties
void initProperties(const char *statusGroup, const char *paramsGroup)
Initilize focuser properties. It is recommended to call this function within initProperties() of your...
Definition: indiweatherinterface.cpp:48
TTY_TIME_OUT
@ TTY_TIME_OUT
Definition: indicom.h:98
cmd
__u8 cmd[4]
Definition: pwc-ioctl.h:4
INDI::WeatherInterface::setCriticalParameter
bool setCriticalParameter(std::string param)
setCriticalParameter Set parameter that is considered critical to the operation of the observatory....
Definition: indiweatherinterface.cpp:167
INDI::DefaultDevice::addAuxControls
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
Definition: defaultdevice.cpp:665
IPState
IPState
Property state.
Definition: indiapi.h:158
tty_nread_section
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:657
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
ISS_OFF
@ ISS_OFF
Definition: indiapi.h:150
indicom.h
Implementations for common driver routines.
IDSetText
void IDSetText(const ITextVectorProperty *t, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing text vector property.
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
Connection::Serial
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
Definition: connectionserial.h:56
IUFillNumber
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: indidriver.c:348
ISR_NOFMANY
@ ISR_NOFMANY
Definition: indiapi.h:174
INDI::DefaultDevice::defineProperty
void defineProperty(INumberVectorProperty *property)
Definition: defaultdevice.cpp:997
MAIN_CONTROL_TAB
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
Definition: defaultdevice.cpp:34
IUFillTextVector
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: indidriver.c:477
INDI::FocuserInterface
Provides interface to implement focuser functionality.
Definition: indifocuserinterface.h:63
INDI::WeatherInterface::syncCriticalParameters
bool syncCriticalParameters()
updateWeatherState Send update weather state to client
Definition: indiweatherinterface.cpp:230
INDI::DefaultDevice::setVersion
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
Definition: defaultdevice.cpp:1219
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
_ILightVectorProperty::s
IPState s
Definition: indiapi.h:426
FOCUS_TAB
const char * FOCUS_TAB
FOCUS_TAB Where all the properties for focuser are located.
Definition: defaultdevice.cpp:41
TTY_OVERFLOW
@ TTY_OVERFLOW
Definition: indicom.h:102
IUFillLight
void IUFillLight(ILight *lp, const char *name, const char *label, IPState s)
Assign attributes for a light property. The light's auxiliary elements will be set to NULL.
Definition: indidriver.c:334
INDI::FocuserInterface::FOCUSER_CAN_ABORT
@ FOCUSER_CAN_ABORT
Definition: indifocuserinterface.h:76
IUSaveConfigNumber
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indicom.c:1455
IUFillText
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: indidriver.c:369
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
MAXRBUF
#define MAXRBUF
Definition: indidriver.c:52
INDI::WeatherInterface::ParametersNP
INumberVectorProperty ParametersNP
Definition: indiweatherinterface.h:150
INDI::DefaultDevice::initProperties
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function.
Definition: defaultdevice.cpp:917
IUResetSwitch
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indicom.c:1442
_ILightVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:420
tty_error_msg
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1156
INDI::DefaultDevice::getCurrentPollingPeriod
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
Definition: defaultdevice.cpp:1139
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
INDI::DefaultDevice::SetTimer
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
Definition: defaultdevice.cpp:865
INDI::FocuserInterface::saveConfigItems
bool saveConfigItems(FILE *fp)
saveConfigItems save focuser properties defined in the interface in config file
Definition: indifocuserinterface.cpp:596
IDSetLight
void void void void void void void IDSetLight(const ILightVectorProperty *l, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing light vector property.
PegasusPPBA
Definition: pegasus_ppba.h:39
INDI::DefaultDevice::getDriverInterface
virtual uint16_t getDriverInterface() override
Definition: defaultdevice.cpp:896
INDI::FocuserInterface::FOCUS_INWARD
@ FOCUS_INWARD
Definition: indifocuserinterface.h:68
INDI::BaseDevice::FOCUSER_INTERFACE
@ FOCUSER_INTERFACE
Definition: basedevice.h:75
INDI::DefaultDevice::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
Definition: defaultdevice.cpp:593
IUFillSwitchVector
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: indidriver.c:412
INDI::BaseDevice::INDI_ENABLED
@ INDI_ENABLED
Definition: basedevice.h:64
INDI::DefaultDevice::syncDriverInfo
void syncDriverInfo()
syncDriverInfo sends the current driver information to the client.
Definition: defaultdevice.cpp:911
pegasus_ppba.h
IUFillNumberVector
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: indidriver.c:455
PegasusPPBA::SyncFocuser
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
Definition: pegasus_ppba.cpp:880
IPS_BUSY
@ IPS_BUSY
Definition: indiapi.h:162
PegasusPPBA::TimerHit
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: pegasus_ppba.cpp:638
ISR_1OFMANY
@ ISR_1OFMANY
Definition: indiapi.h:172
INDI::WeatherInterface::critialParametersLP
ILightVectorProperty critialParametersLP
Definition: indiweatherinterface.h:158
connectionserial.h
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
INDI::FocuserInterface::processNumber
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
Definition: indifocuserinterface.cpp:168
INDI::DefaultDevice::registerConnection
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
Definition: defaultdevice.cpp:1107
INDI::FocuserInterface::FOCUSER_CAN_REVERSE
@ FOCUSER_CAN_REVERSE
Definition: indifocuserinterface.h:77
ISR_ATMOST1
@ ISR_ATMOST1
Definition: indiapi.h:173
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
IUUpdateSwitch
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:171
INDI::FocuserInterface::FocusRelPosNP
INumberVectorProperty FocusRelPosNP
Definition: indifocuserinterface.h:286
PegasusPPBA::AbortFocuser
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
Definition: pegasus_ppba.cpp:862
_ITextVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:249
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
ISNewSwitch
void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Update the value of an existing switch vector property.
Definition: defaultdevice.cpp:60
LOG_DEBUG
#define LOG_DEBUG(txt)
Definition: indilogger.h:75
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
INDI::WeatherInterface::saveConfigItems
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save parameters ranges in the config file.
Definition: indiweatherinterface.cpp:312
INDI::WeatherInterface::processNumber
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process focus number properties.
Definition: indiweatherinterface.cpp:96
INDI::FocuserInterface::SetCapability
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
Definition: indifocuserinterface.h:95
PegasusPPBA::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: pegasus_ppba.cpp:624
INDI::WeatherInterface::addParameter
void addParameter(std::string name, std::string label, double numMinOk, double numMaxOk, double percWarning)
addParameter Add a physical weather measurable parameter to the weather driver. The weather value has...
Definition: indiweatherinterface.cpp:131
IUSaveText
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indicom.c:1449
name
const char * name
Definition: indiserver.c:116
INDI::FocuserInterface::updateProperties
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
Definition: indifocuserinterface.cpp:101
INDI::FocuserInterface::initProperties
void initProperties(const char *groupName)
Initilize focuser properties. It is recommended to call this function within initProperties() of your...
Definition: indifocuserinterface.cpp:35
_ISwitchVectorProperty::s
IPState s
Definition: indiapi.h:382
INDI::DefaultDevice::saveConfig
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
Definition: defaultdevice.cpp:221
Connection::Interface::registerHandshake
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the intial connection to the device...
Definition: connectioninterface.cpp:108
PegasusPPBA::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: pegasus_ppba.cpp:45
IUUpdateNumber
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:225
INDI::FocuserInterface::processSwitch
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process focus switch properties.
Definition: indifocuserinterface.cpp:414
INDI::DefaultDevice::saveConfigItems
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
Definition: defaultdevice.cpp:175
INDI::FocuserInterface::FocusDirection
FocusDirection
Definition: indifocuserinterface.h:66
IP_RW
@ IP_RW
Definition: indiapi.h:185
LOG_WARN
#define LOG_WARN(txt)
Definition: indilogger.h:73
PegasusPPBA::PegasusPPBA
PegasusPPBA()
Definition: pegasus_ppba.cpp:37
INDI::FocuserInterface::FOCUSER_HAS_BACKLASH
@ FOCUSER_HAS_BACKLASH
Definition: indifocuserinterface.h:80
ISState
ISState
Switch state.
Definition: indiapi.h:148
Connection::Serial::getPortFD
int getPortFD() const
Definition: connectionserial.h:136
INDI::WeatherInterface
Provides interface to implement weather reporting functionality.
Definition: indiweatherinterface.h:55
IUFindOnSwitchIndex
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1424
INDI::BaseDevice::AUX_INTERFACE
@ AUX_INTERFACE
Definition: basedevice.h:87
PegasusPPBA::getDefaultName
const char * getDefaultName() override
Definition: pegasus_ppba.cpp:266
PegasusPPBA::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: pegasus_ppba.cpp:320
IUSaveConfigSwitch
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indicom.c:1465
tty_write_string
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:465
TTY_OK
@ TTY_OK
Definition: indicom.h:94
INDI::DefaultDevice::deleteProperty
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
Definition: defaultdevice.cpp:965
PegasusPPBA::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: pegasus_ppba.cpp:189
IUFillLightVector
void IUFillLightVector(ILightVectorProperty *lvp, ILight *lp, int nlp, const char *dev, const char *name, const char *label, const char *group, IPState s)
Assign attributes for a light vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidriver.c:435
PegasusPPBA::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: pegasus_ppba.cpp:486
INDI::FocuserInterface::FocusAbsPosN
INumber FocusAbsPosN[1]
Definition: indifocuserinterface.h:283
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
IDSetSwitch
void void void void void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing switch vector property.
INDI::DefaultDevice::setDriverInterface
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
Definition: defaultdevice.cpp:902
INDI::WeatherInterface::updateProperties
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
Definition: indiweatherinterface.cpp:61
IUFillSwitch
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: indidriver.c:320
INDI::BaseDevice::WEATHER_INTERFACE
@ WEATHER_INTERFACE
Definition: basedevice.h:79
INDI::DefaultDevice::updateProperties
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: defaultdevice.cpp:890
PegasusPPBA::SetFocuserBacklash
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
Definition: pegasus_ppba.cpp:890
INDI::BaseDevice::INDI_DISABLED
@ INDI_DISABLED
Definition: basedevice.h:65
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
INDI::WeatherInterface::setParameterValue
void setParameterValue(std::string name, double value)
setParameterValue Update weather parameter value
Definition: indiweatherinterface.cpp:155
ISS_ON
@ ISS_ON
Definition: indiapi.h:151
PegasusPPBA::SetFocuserBacklashEnabled
virtual bool SetFocuserBacklashEnabled(bool enabled) override
SetFocuserBacklashEnabled Enables or disables the focuser backlash compensation.
Definition: pegasus_ppba.cpp:917