Instrument Neutral Distributed Interface INDI  2.0.2
pegasus_ppb.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2019 Jasem Mutlaq. All rights reserved.
3 
4  Pegasus Pocket Power Box 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_ppb.h"
26 #include "indicom.h"
28 
29 #include <memory>
30 #include <regex>
31 #include <termios.h>
32 #include <cstring>
33 #include <sys/ioctl.h>
34 
35 // We declare an auto pointer to PegasusPPB.
36 static std::unique_ptr<PegasusPPB> pocket_power_box(new PegasusPPB());
37 
39 {
40  setVersion(1, 1);
41  lastSensorData.reserve(PA_N);
42 }
43 
45 {
47 
49 
50  WI::initProperties(ENVIRONMENT_TAB, ENVIRONMENT_TAB);
51 
53 
57  // Cycle all power on/off
58  IUFillSwitch(&PowerCycleAllS[POWER_CYCLE_OFF], "POWER_CYCLE_OFF", "All Off", ISS_OFF);
59  IUFillSwitch(&PowerCycleAllS[POWER_CYCLE_ON], "POWER_CYCLE_ON", "All On", ISS_OFF);
60  IUFillSwitchVector(&PowerCycleAllSP, PowerCycleAllS, 2, getDeviceName(), "POWER_CYCLE", "Cycle Power", MAIN_CONTROL_TAB,
61  IP_RW, ISR_ATMOST1, 60, IPS_IDLE);
62 
63  // DSLR on/off
64  IUFillSwitch(&DSLRPowerS[INDI_ENABLED], "INDI_ENABLED", "On", ISS_OFF);
65  IUFillSwitch(&DSLRPowerS[INDI_DISABLED], "INDI_DISABLED", "Off", ISS_ON);
66  IUFillSwitchVector(&DSLRPowerSP, DSLRPowerS, 2, getDeviceName(), "DSLR_POWER", "DSLR Power", MAIN_CONTROL_TAB, IP_RW,
67  ISR_1OFMANY, 60, IPS_IDLE);
68 
69  // Reboot
70  IUFillSwitch(&RebootS[0], "REBOOT", "Reboot Device", ISS_OFF);
71  IUFillSwitchVector(&RebootSP, RebootS, 1, getDeviceName(), "REBOOT_DEVICE", "Device", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1,
72  60, IPS_IDLE);
73 
74  // Power Sensors
75  IUFillNumber(&PowerSensorsN[SENSOR_VOLTAGE], "SENSOR_VOLTAGE", "Voltage (V)", "%4.2f", 0, 999, 100, 0);
76  IUFillNumber(&PowerSensorsN[SENSOR_CURRENT], "SENSOR_CURRENT", "Current (A)", "%4.2f", 0, 999, 100, 0);
77  IUFillNumberVector(&PowerSensorsNP, PowerSensorsN, 2, getDeviceName(), "POWER_SENSORS", "Sensors", MAIN_CONTROL_TAB, IP_RO,
78  60, IPS_IDLE);
79 
83 
84  // Power on Boot
85  IUFillSwitch(&PowerOnBootS[0], "POWER_PORT_1", "Port 1", ISS_ON);
86  IUFillSwitch(&PowerOnBootS[1], "POWER_PORT_2", "Port 2", ISS_ON);
87  IUFillSwitch(&PowerOnBootS[2], "POWER_PORT_3", "Port 3", ISS_ON);
88  IUFillSwitch(&PowerOnBootS[3], "POWER_PORT_4", "Port 4", ISS_ON);
89  IUFillSwitchVector(&PowerOnBootSP, PowerOnBootS, 4, getDeviceName(), "POWER_ON_BOOT", "Power On Boot", MAIN_CONTROL_TAB,
90  IP_RW, ISR_NOFMANY, 60, IPS_IDLE);
91 
95 
96  // Automatic Dew
97  IUFillSwitch(&AutoDewS[INDI_ENABLED], "INDI_ENABLED", "Enabled", ISS_OFF);
98  IUFillSwitch(&AutoDewS[INDI_DISABLED], "INDI_DISABLED", "Disabled", ISS_ON);
99  IUFillSwitchVector(&AutoDewSP, AutoDewS, 2, getDeviceName(), "AUTO_DEW", "Auto Dew", DEW_TAB, IP_RW, ISR_1OFMANY, 60,
100  IPS_IDLE);
101 
102  // Dew PWM
103  IUFillNumber(&DewPWMN[DEW_PWM_A], "DEW_A", "Dew A (%)", "%.2f", 0, 100, 10, 0);
104  IUFillNumber(&DewPWMN[DEW_PWM_B], "DEW_B", "Dew B (%)", "%.2f", 0, 100, 10, 0);
105  IUFillNumberVector(&DewPWMNP, DewPWMN, 2, getDeviceName(), "DEW_PWM", "Dew PWM", DEW_TAB, IP_RW, 60, IPS_IDLE);
106 
110  addParameter("WEATHER_TEMPERATURE", "Temperature (C)", -15, 35, 15);
111  addParameter("WEATHER_HUMIDITY", "Humidity %", 0, 100, 15);
112  addParameter("WEATHER_DEWPOINT", "Dew Point (C)", 0, 100, 15);
113  setCriticalParameter("WEATHER_TEMPERATURE");
114 
118  serialConnection = new Connection::Serial(this);
119  serialConnection->registerHandshake([&]()
120  {
121  return Handshake();
122  });
123  registerConnection(serialConnection);
124 
125  return true;
126 }
127 
129 {
131 
132  if (isConnected())
133  {
134  // Main Control
135  defineProperty(&PowerCycleAllSP);
136  defineProperty(&DSLRPowerSP);
137  defineProperty(&PowerSensorsNP);
138  defineProperty(&PowerOnBootSP);
139  defineProperty(&RebootSP);
140 
141  // Dew
142  defineProperty(&AutoDewSP);
143  defineProperty(&DewPWMNP);
144 
146 
147  setupComplete = true;
148  }
149  else
150  {
151  // Main Control
152  deleteProperty(PowerCycleAllSP.name);
153  deleteProperty(DSLRPowerSP.name);
154  deleteProperty(PowerSensorsNP.name);
155  deleteProperty(PowerOnBootSP.name);
156  deleteProperty(RebootSP.name);
157 
158  // Dew
159  deleteProperty(AutoDewSP.name);
160  deleteProperty(DewPWMNP.name);
161 
163 
164  setupComplete = false;
165  }
166 
167  return true;
168 }
169 
171 {
172  return "Pegasus PPB";
173 }
174 
175 bool PegasusPPB::Handshake()
176 {
177  int tty_rc = 0, nbytes_written = 0, nbytes_read = 0;
178  char command[PEGASUS_LEN] = {0}, response[PEGASUS_LEN] = {0};
179 
180  PortFD = serialConnection->getPortFD();
181 
182  LOG_DEBUG("CMD <P#>");
183 
184  tcflush(PortFD, TCIOFLUSH);
185  strncpy(command, "P#\n", PEGASUS_LEN);
186  if ( (tty_rc = tty_write_string(PortFD, command, &nbytes_written)) != TTY_OK)
187  {
188  char errorMessage[MAXRBUF];
189  tty_error_msg(tty_rc, errorMessage, MAXRBUF);
190  LOGF_ERROR("Serial write error: %s", errorMessage);
191  return false;
192  }
193 
194  // Try first with stopChar as the stop character
195  if ( (tty_rc = tty_nread_section(PortFD, response, PEGASUS_LEN, stopChar, 1, &nbytes_read)) != TTY_OK)
196  {
197  // Try 0xA as the stop character
198  if (tty_rc == TTY_OVERFLOW || tty_rc == TTY_TIME_OUT)
199  {
200  tcflush(PortFD, TCIOFLUSH);
201  tty_write_string(PortFD, command, &nbytes_written);
202  stopChar = 0xA;
203  tty_rc = tty_nread_section(PortFD, response, PEGASUS_LEN, stopChar, 1, &nbytes_read);
204  }
205 
206  if (tty_rc != TTY_OK)
207  {
208  char errorMessage[MAXRBUF];
209  tty_error_msg(tty_rc, errorMessage, MAXRBUF);
210  LOGF_ERROR("Serial read error: %s", errorMessage);
211  return false;
212  }
213  }
214 
215  tcflush(PortFD, TCIOFLUSH);
216  response[nbytes_read - 1] = '\0';
217  LOGF_DEBUG("RES <%s>", response);
218 
219  setupComplete = false;
220 
221  return !strcmp(response, "PPB_OK");
222 }
223 
224 bool PegasusPPB::ISNewSwitch(const char * dev, const char * name, ISState * states, char * names[], int n)
225 {
226  if (dev && !strcmp(dev, getDeviceName()))
227  {
228  // Cycle all power on or off
229  if (!strcmp(name, PowerCycleAllSP.name))
230  {
231  IUUpdateSwitch(&PowerCycleAllSP, states, names, n);
232 
233  PowerCycleAllSP.s = IPS_ALERT;
234  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
235  snprintf(cmd, PEGASUS_LEN, "P1:%d", IUFindOnSwitchIndex(&PowerCycleAllSP));
236  if (sendCommand(cmd, res))
237  {
238  PowerCycleAllSP.s = !strcmp(cmd, res) ? IPS_OK : IPS_ALERT;
239  }
240 
241  IUResetSwitch(&PowerCycleAllSP);
242  IDSetSwitch(&PowerCycleAllSP, nullptr);
243  return true;
244  }
245 
246  // DSLR
247  if (!strcmp(name, DSLRPowerSP.name))
248  {
249  IUUpdateSwitch(&DSLRPowerSP, states, names, n);
250  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
251  snprintf(cmd, PEGASUS_LEN, "P2:%d", (DSLRPowerS[INDI_ENABLED].s == ISS_ON) ? 1 : 0);
252  DSLRPowerSP.s = sendCommand(cmd, res) ? IPS_OK : IPS_ALERT;
253  IDSetSwitch(&DSLRPowerSP, nullptr);
254  return true;
255  }
256 
257  // Reboot
258  if (!strcmp(name, RebootSP.name))
259  {
260  RebootSP.s = reboot() ? IPS_OK : IPS_ALERT;
261  IDSetSwitch(&RebootSP, nullptr);
262  LOG_INFO("Rebooting device...");
263  return true;
264  }
265 
266  // Power on boot
267  if (!strcmp(name, PowerOnBootSP.name))
268  {
269  IUUpdateSwitch(&PowerOnBootSP, states, names, n);
270  PowerOnBootSP.s = setPowerOnBoot() ? IPS_OK : IPS_ALERT;
271  IDSetSwitch(&PowerOnBootSP, nullptr);
272  saveConfig(true, PowerOnBootSP.name);
273  return true;
274  }
275 
276  // Auto Dew
277  if (!strcmp(name, AutoDewSP.name))
278  {
279  int prevIndex = IUFindOnSwitchIndex(&AutoDewSP);
280  IUUpdateSwitch(&AutoDewSP, states, names, n);
281  if (setAutoDewEnabled(AutoDewS[INDI_ENABLED].s == ISS_ON))
282  {
283  AutoDewSP.s = IPS_OK;
284  }
285  else
286  {
287  IUResetSwitch(&AutoDewSP);
288  AutoDewS[prevIndex].s = ISS_ON;
289  AutoDewSP.s = IPS_ALERT;
290  }
291 
292  IDSetSwitch(&AutoDewSP, nullptr);
293  return true;
294  }
295  }
296 
297  return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
298 }
299 
300 bool PegasusPPB::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n)
301 {
302  if (dev && !strcmp(dev, getDeviceName()))
303  {
304  // Dew PWM
305  if (!strcmp(name, DewPWMNP.name))
306  {
307  bool rc1 = false, rc2 = false;
308  for (int i = 0; i < n; i++)
309  {
310  if (!strcmp(names[i], DewPWMN[DEW_PWM_A].name))
311  rc1 = setDewPWM(3, static_cast<uint8_t>(values[i] / 100.0 * 255.0));
312  else if (!strcmp(names[i], DewPWMN[DEW_PWM_B].name))
313  rc2 = setDewPWM(4, static_cast<uint8_t>(values[i] / 100.0 * 255.0));
314  }
315 
316  DewPWMNP.s = (rc1 && rc2) ? IPS_OK : IPS_ALERT;
317  if (DewPWMNP.s == IPS_OK)
318  IUUpdateNumber(&DewPWMNP, values, names, n);
319  IDSetNumber(&DewPWMNP, nullptr);
320  return true;
321  }
322 
323  if (strstr(name, "WEATHER_"))
324  return WI::processNumber(dev, name, values, names, n);
325  }
326  return INDI::DefaultDevice::ISNewNumber(dev, name, values, names, n);
327 }
328 
329 bool PegasusPPB::sendCommand(const char * cmd, char * res)
330 {
331  int nbytes_read = 0, nbytes_written = 0, tty_rc = 0;
332  char command[PEGASUS_LEN] = {0};
333  LOGF_DEBUG("CMD <%s>", cmd);
334 
335  for (int i = 0; i < 2; i++)
336  {
337  tcflush(PortFD, TCIOFLUSH);
338  snprintf(command, PEGASUS_LEN, "%s\n", cmd);
339  if ( (tty_rc = tty_write_string(PortFD, command, &nbytes_written)) != TTY_OK)
340  continue;
341 
342  if (!res)
343  {
344  tcflush(PortFD, TCIOFLUSH);
345  return true;
346  }
347 
348  if ( (tty_rc = tty_nread_section(PortFD, res, PEGASUS_LEN, stopChar, PEGASUS_TIMEOUT, &nbytes_read)) != TTY_OK
349  || nbytes_read == 1)
350  continue;
351 
352  tcflush(PortFD, TCIOFLUSH);
353  res[nbytes_read - 1] = '\0';
354  LOGF_DEBUG("RES <%s>", res);
355  return true;
356  }
357 
358  if (tty_rc != TTY_OK)
359  {
360  char errorMessage[MAXRBUF];
361  tty_error_msg(tty_rc, errorMessage, MAXRBUF);
362  LOGF_ERROR("Serial error: %s", errorMessage);
363  }
364 
365  return false;
366 }
367 
368 bool PegasusPPB::setAutoDewEnabled(bool enabled)
369 {
370  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
371  snprintf(cmd, PEGASUS_LEN, "PD:%d", enabled ? 1 : 0);
372  if (sendCommand(cmd, res))
373  {
374  return (!strcmp(res, cmd));
375  }
376 
377  return false;
378 }
379 
380 bool PegasusPPB::setPowerOnBoot()
381 {
382  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
383  snprintf(cmd, PEGASUS_LEN, "PE:%d%d%d%d", PowerOnBootS[0].s == ISS_ON ? 1 : 0,
384  PowerOnBootS[1].s == ISS_ON ? 1 : 0,
385  PowerOnBootS[2].s == ISS_ON ? 1 : 0,
386  PowerOnBootS[3].s == ISS_ON ? 1 : 0);
387  if (sendCommand(cmd, res))
388  {
389  return (!strcmp(res, "PE:1"));
390  }
391 
392  return false;
393 }
394 
395 bool PegasusPPB::setDewPWM(uint8_t id, uint8_t value)
396 {
397  char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0}, expected[PEGASUS_LEN] = {0};
398  snprintf(cmd, PEGASUS_LEN, "P%d:%03d", id, value);
399  snprintf(expected, PEGASUS_LEN, "P%d:%d", id, value);
400  if (sendCommand(cmd, res))
401  {
402  return (!strcmp(res, expected));
403  }
404 
405  return false;
406 }
407 
409 {
412  IUSaveConfigSwitch(fp, &AutoDewSP);
413 
414  return true;
415 }
416 
418 {
419  if (!isConnected() || setupComplete == false)
420  {
422  return;
423  }
424 
425  getSensorData();
427 }
428 
429 bool PegasusPPB::sendFirmware()
430 {
431  char res[PEGASUS_LEN] = {0};
432  if (sendCommand("PV", res))
433  {
434  LOGF_INFO("Detected firmware %s", res);
435  return true;
436  }
437 
438  return false;
439 }
440 
441 bool PegasusPPB::getSensorData()
442 {
443  char res[PEGASUS_LEN] = {0};
444  if (sendCommand("PA", res))
445  {
446  std::vector<std::string> result = split(res, ":");
447  if (result.size() < PA_N)
448  {
449  LOG_WARN("Received wrong number of detailed sensor data. Retrying...");
450  return false;
451  }
452 
453  if (result == lastSensorData)
454  return true;
455 
456  // Power Sensors
457  PowerSensorsN[SENSOR_VOLTAGE].value = std::stod(result[PA_VOLTAGE]);
458  PowerSensorsN[SENSOR_CURRENT].value = std::stod(result[PA_CURRENT]) / 65.0;
459  PowerSensorsNP.s = IPS_OK;
460  if (lastSensorData[PA_VOLTAGE] != result[PA_VOLTAGE] || lastSensorData[PA_CURRENT] != result[PA_CURRENT])
461  IDSetNumber(&PowerSensorsNP, nullptr);
462 
463  // Environment Sensors
464  setParameterValue("WEATHER_TEMPERATURE", std::stod(result[PA_TEMPERATURE]));
465  setParameterValue("WEATHER_HUMIDITY", std::stod(result[PA_HUMIDITY]));
466  setParameterValue("WEATHER_DEWPOINT", std::stod(result[PA_DEW_POINT]));
467  if (lastSensorData[PA_TEMPERATURE] != result[PA_TEMPERATURE] ||
468  lastSensorData[PA_HUMIDITY] != result[PA_HUMIDITY] ||
469  lastSensorData[PA_DEW_POINT] != result[PA_DEW_POINT])
470  {
472  IDSetLight(&critialParametersLP, nullptr);
474  IDSetNumber(&ParametersNP, nullptr);
475  }
476 
477  // Power Status
478  PowerCycleAllS[POWER_CYCLE_ON].s = (std::stoi(result[PA_PORT_STATUS]) == 1) ? ISS_ON : ISS_OFF;
479  PowerCycleAllS[POWER_CYCLE_ON].s = (std::stoi(result[PA_PORT_STATUS]) == 0) ? ISS_ON : ISS_OFF;
480  PowerCycleAllSP.s = (std::stoi(result[6]) == 1) ? IPS_OK : IPS_IDLE;
481  if (lastSensorData[PA_PORT_STATUS] != result[PA_PORT_STATUS])
482  IDSetSwitch(&PowerCycleAllSP, nullptr);
483 
484  // DSLR Power Status
485  DSLRPowerS[INDI_ENABLED].s = (std::stoi(result[PA_DSLR_STATUS]) == 1) ? ISS_ON : ISS_OFF;
486  DSLRPowerS[INDI_DISABLED].s = (std::stoi(result[PA_DSLR_STATUS]) == 0) ? ISS_ON : ISS_OFF;
487  DSLRPowerSP.s = (std::stoi(result[PA_DSLR_STATUS]) == 1) ? IPS_OK : IPS_IDLE;
488  if (lastSensorData[PA_DSLR_STATUS] != result[PA_DSLR_STATUS])
489  IDSetSwitch(&DSLRPowerSP, nullptr);
490 
491  // Dew PWM
492  DewPWMN[0].value = std::stod(result[PA_DEW_1]) / 255.0 * 100.0;
493  DewPWMN[1].value = std::stod(result[PA_DEW_2]) / 255.0 * 100.0;
494  if (lastSensorData[PA_DEW_1] != result[PA_DEW_1] || lastSensorData[PA_DEW_2] != result[PA_DEW_2])
495  IDSetNumber(&DewPWMNP, nullptr);
496 
497  // Auto Dew
498  AutoDewS[INDI_ENABLED].s = (std::stoi(result[PA_AUTO_DEW]) == 1) ? ISS_ON : ISS_OFF;
499  AutoDewS[INDI_DISABLED].s = (std::stoi(result[PA_AUTO_DEW]) == 1) ? ISS_OFF : ISS_ON;
500  if (lastSensorData[PA_AUTO_DEW] != result[PA_AUTO_DEW])
501  IDSetSwitch(&AutoDewSP, nullptr);
502 
503  lastSensorData = result;
504 
505  return true;
506  }
507 
508  return false;
509 }
510 
511 // Device Control
512 bool PegasusPPB::reboot()
513 {
514  return sendCommand("PF", nullptr);
515 }
516 
517 std::vector<std::string> PegasusPPB::split(const std::string &input, const std::string &regex)
518 {
519  // passing -1 as the submatch index parameter performs splitting
520  std::regex re(regex);
521  std::sregex_token_iterator
522  first{input.begin(), input.end(), re, -1},
523  last;
524  return {first, last};
525 }
526 
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the intial connection to the device...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
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)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function.
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
Provides interface to implement weather reporting functionality.
bool syncCriticalParameters()
updateWeatherState Send update weather state to client
void setParameterValue(std::string name, double value)
setParameterValue Update weather parameter value
bool setCriticalParameter(std::string param)
setCriticalParameter Set parameter that is considered critical to the operation of the observatory....
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process weather number properties.
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save parameters ranges in the config file.
ILightVectorProperty critialParametersLP
INumberVectorProperty ParametersNP
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...
void initProperties(const char *statusGroup, const char *paramsGroup)
Initilize focuser properties. It is recommended to call this function within initProperties() of your...
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
const char * getDefaultName() override
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: pegasus_ppb.cpp:44
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Update the value of an existing switch vector property.
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
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_1OFMANY
Definition: indiapi.h:173
@ ISR_NOFMANY
Definition: indiapi.h:175
@ ISR_ATMOST1
Definition: indiapi.h:174
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
@ TTY_TIME_OUT
Definition: indicom.h:154
@ TTY_OVERFLOW
Definition: indicom.h:158
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 IDSetLight(const ILightVectorProperty *lvp, const char *fmt,...)
Definition: indidriver.c:1251
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 LOG_DEBUG(txt)
Definition: indilogger.h:75
#define LOG_WARN(txt)
Definition: indilogger.h:73
#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