36static std::unique_ptr<PegasusPPB> pocket_power_box(
new PegasusPPB());
41 lastSensorData.reserve(PA_N);
64 RebootSP[0].
fill(
"REBOOT",
"Reboot Device",
ISS_OFF);
73 PowerOnBootSP[POWER_PORT_1].
fill(
"POWER_PORT_1",
"Port 1",
ISS_ON);
74 PowerOnBootSP[POWER_PORT_2].
fill(
"POWER_PORT_2",
"Port 2",
ISS_ON);
75 PowerOnBootSP[POWER_PORT_3].
fill(
"POWER_PORT_3",
"Port 3",
ISS_ON);
76 PowerOnBootSP[POWER_PORT_4].
fill(
"POWER_PORT_4",
"Port 4",
ISS_ON);
83 addParameter(
"WEATHER_TEMPERATURE",
"Temperature (C)", -15, 35, 15);
84 addParameter(
"WEATHER_HUMIDITY",
"Humidity %", 0, 100, 15);
85 addParameter(
"WEATHER_DEWPOINT",
"Dew Point (C)", 0, 100, 15);
115 setupComplete =
true;
127 setupComplete =
false;
135 return "Pegasus PPB";
138bool PegasusPPB::Handshake()
140 int tty_rc = 0, nbytes_written = 0, nbytes_read = 0;
141 char command[PEGASUS_LEN] = {0}, response[PEGASUS_LEN] = {0};
147 tcflush(PortFD, TCIOFLUSH);
148 strncpy(command,
"P#\n", PEGASUS_LEN);
153 LOGF_ERROR(
"Serial write error: %s", errorMessage);
163 tcflush(PortFD, TCIOFLUSH);
166 tty_rc =
tty_nread_section(PortFD, response, PEGASUS_LEN, stopChar, 1, &nbytes_read);
173 LOGF_ERROR(
"Serial read error: %s", errorMessage);
178 tcflush(PortFD, TCIOFLUSH);
179 response[nbytes_read - 1] =
'\0';
182 setupComplete =
false;
189 return !strcmp(response,
"PPB_OK");
199 DSLRPowerSP.
update(states, names, n);
200 char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
219 PowerOnBootSP.
update(states, names, n);
221 PowerOnBootSP.
apply();
231 return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
238 if (strstr(name,
"WEATHER_"))
260bool PegasusPPB::sendCommand(
const char *
cmd,
char * res)
262 int nbytes_read = 0, nbytes_written = 0, tty_rc = 0;
263 char command[PEGASUS_LEN] = {0};
266 for (
int i = 0; i < 2; i++)
268 tcflush(PortFD, TCIOFLUSH);
269 snprintf(command, PEGASUS_LEN,
"%s\n",
cmd);
275 tcflush(PortFD, TCIOFLUSH);
283 tcflush(PortFD, TCIOFLUSH);
284 res[nbytes_read - 1] =
'\0';
299bool PegasusPPB::setAutoDewEnabled(
bool enabled)
301 char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
302 snprintf(
cmd, PEGASUS_LEN,
"PD:%d", enabled ? 1 : 0);
303 if (sendCommand(
cmd, res))
305 return (!strcmp(res,
cmd));
311bool PegasusPPB::setPowerEnabled(uint8_t port,
bool enabled)
313 char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
314 snprintf(
cmd, PEGASUS_LEN,
"P%d:%d", port, enabled ? 1 : 0);
315 if (sendCommand(
cmd, res))
317 return (!strcmp(res,
cmd));
323bool PegasusPPB::setPowerOnBoot()
325 char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
326 snprintf(
cmd, PEGASUS_LEN,
"PE:%d%d%d%d", PowerOnBootSP[POWER_PORT_1].getState() ==
ISS_ON ? 1 : 0,
327 PowerOnBootSP[POWER_PORT_2].getState() ==
ISS_ON ? 1 : 0,
328 PowerOnBootSP[POWER_PORT_3].getState() ==
ISS_ON ? 1 : 0,
329 PowerOnBootSP[POWER_PORT_4].getState() ==
ISS_ON ? 1 : 0);
330 if (sendCommand(
cmd, res))
332 return (!strcmp(res,
"PE:1"));
338bool PegasusPPB::setDewPWM(uint8_t
id, uint8_t value)
340 char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0}, expected[PEGASUS_LEN] = {0};
341 snprintf(
cmd, PEGASUS_LEN,
"P%d:%03d",
id, value);
342 snprintf(expected, PEGASUS_LEN,
"P%d:%d",
id, value);
343 if (sendCommand(
cmd, res))
345 return (!strcmp(res, expected));
355 PowerOnBootSP.
save(fp);
375bool PegasusPPB::sendFirmware()
377 char res[PEGASUS_LEN] = {0};
378 if (sendCommand(
"PV", res))
387bool PegasusPPB::getSensorData()
389 char res[PEGASUS_LEN] = {0};
390 if (sendCommand(
"PA", res))
392 std::vector<std::string> result = split(res,
":");
393 if (result.size() < PA_N)
395 LOGF_WARN(
"Received wrong number of detailed sensor data. Expected at least %d, got %zu. Retrying...", PA_N, result.size());
399 if (result == lastSensorData)
405 if (result.size() > PA_VOLTAGE && result.size() > PA_CURRENT)
410 if (lastSensorData.size() > PA_CURRENT &&
411 (lastSensorData[PA_VOLTAGE] != result[PA_VOLTAGE] || lastSensorData[PA_CURRENT] != result[PA_CURRENT]))
416 if (result.size() > PA_TEMPERATURE && result.size() > PA_HUMIDITY && result.size() > PA_DEW_POINT)
421 if (lastSensorData.size() > PA_DEW_POINT &&
422 (lastSensorData[PA_TEMPERATURE] != result[PA_TEMPERATURE] ||
423 lastSensorData[PA_HUMIDITY] != result[PA_HUMIDITY] ||
424 lastSensorData[PA_DEW_POINT] != result[PA_DEW_POINT]))
434 if (result.size() > PA_PORT_STATUS && !result[PA_PORT_STATUS].empty())
436 const std::string& portStatus = result[PA_PORT_STATUS];
440 if (lastSensorData.size() > PA_PORT_STATUS && lastSensorData[PA_PORT_STATUS] != result[PA_PORT_STATUS])
446 if (result.size() > PA_DSLR_STATUS && !result[PA_DSLR_STATUS].empty())
448 int dslrStatus = std::stoi(result[PA_DSLR_STATUS]);
452 if (lastSensorData.size() > PA_DSLR_STATUS && lastSensorData[PA_DSLR_STATUS] != result[PA_DSLR_STATUS])
457 if (result.size() > PA_DEW_1 && result.size() > PA_DEW_2)
463 if (lastSensorData.size() > PA_DEW_2 &&
464 (lastSensorData[PA_DEW_1] != result[PA_DEW_1] || lastSensorData[PA_DEW_2] != result[PA_DEW_2]))
470 if (result.size() > PA_DEW_1 && result.size() > PA_DEW_2)
472 bool dewChannelChanged =
false;
475 auto newState = (std::stoi(result[PA_DEW_1]) > 0) ?
ISS_ON :
ISS_OFF;
479 dewChannelChanged =
true;
484 auto newState = (std::stoi(result[PA_DEW_2]) > 0) ?
ISS_ON :
ISS_OFF;
488 dewChannelChanged =
true;
491 if (dewChannelChanged)
496 if (result.size() > PA_AUTO_DEW && !result[PA_AUTO_DEW].empty())
500 if (lastSensorData.size() > PA_AUTO_DEW && lastSensorData[PA_AUTO_DEW] != result[PA_AUTO_DEW])
504 lastSensorData = result;
507 catch (
const std::exception& e)
509 LOGF_ERROR(
"Error parsing sensor data: %s. Response was: %s", e.what(), res);
518bool PegasusPPB::reboot()
520 return sendCommand(
"PF",
nullptr);
523std::vector<std::string> PegasusPPB::split(
const std::string &input,
const std::string ®ex)
526 std::regex re(regex);
527 std::sregex_token_iterator
528 first{input.begin(), input.end(), re, -1},
530 return {first, last};
539 return setPowerEnabled(port + 1, enabled);
546 auto pwmValue =
static_cast<uint8_t
>(dutyCycle / 100.0 * 255.0);
547 return setDewPWM(port + 3, enabled ? pwmValue : 0);
560 char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
561 snprintf(
cmd, PEGASUS_LEN,
"PL:%d", enabled ? 1 : 0);
562 if (sendCommand(
cmd, res))
564 return (!strcmp(res,
cmd));
572 return setAutoDewEnabled(enabled);
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the initial connection to the devic...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
const char * getDeviceName() const
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 setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
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()
Initialize 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.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
INDI::PropertySwitch DewChannelsSP
bool saveConfigItems(FILE *fp)
saveConfigItems Save power properties in config file
INDI::PropertySwitch AutoDewSP
void SetCapability(uint32_t cap)
SetPowerCapability sets the Power capabilities. All capabilities must be initialized.
@ POWER_HAS_VOLTAGE_SENSOR
@ POWER_HAS_OVERALL_CURRENT
INDI::PropertyNumber PowerSensorsNP
bool processNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process Power number properties.
void initProperties(const char *groupName, size_t nPowerPorts=0, size_t nDewPorts=0, size_t nVariablePorts=0, size_t nAutoDewPorts=0, size_t nUSBPorts=0)
Initialize Power properties. It is recommended to call this function within initProperties() of your ...
bool processText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process Power text properties.
bool processSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process Power switch properties.
INDI::PropertySwitch PowerChannelsSP
INDI::PropertyNumber DewChannelDutyCycleNP
bool updateProperties()
updateProperties Define or Delete Power properties based on the connection status of the base device
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
bool isNameMatch(const char *otherName) const
bool update(const ISState states[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
void addParameter(std::string name, std::string label, double numMinOk, double numMaxOk, double percWarning, bool flipWarning=false)
Add a physical weather measurable parameter to the weather driver.
bool setCriticalParameter(std::string name)
setCriticalParameter Set parameter that is considered critical to the operation of the observatory....
bool syncCriticalParameters()
Synchronize and update the state of all critical parameters.
void setParameterValue(std::string name, double value)
setParameterValue Update weather parameter value
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.
INDI::PropertyNumber ParametersNP
void initProperties(const char *statusGroup, const char *paramsGroup)
Initialize focuser properties. It is recommended to call this function within initProperties() of you...
bool updateProperties()
updateProperties Define or Delete Rotator properties based on the connection status of the base devic...
INDI::PropertyLight critialParametersLP
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual bool SetUSBPort(size_t port, bool enabled) override
SetUSBPort Set USB port on/off.
virtual bool SetPowerPort(size_t port, bool enabled) override
Power Interface Implementations.
virtual bool SetAutoDewEnabled(size_t port, bool enabled) override
SetAutoDewEnabled Enable/disable automatic dew control.
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 SetVariablePort(size_t port, bool enabled, double voltage) override
SetVariablePort Set variable voltage port.
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 CyclePower() override
CyclePower Cycle power to all ports.
virtual bool SetLEDEnabled(bool enabled) override
SetLEDEnabled Enable/disable power LEDs.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
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....
virtual bool SetDewPort(size_t port, bool enabled, double dutyCycle) override
SetDewPort Set DEW/Dew port duty cycle.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
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
Implementations for common driver routines.
#define LOGF_INFO(fmt,...)
#define LOGF_WARN(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)
Namespace to encapsulate INDI client, drivers, and mediator classes.