33 #include <sys/ioctl.h>
36 static std::unique_ptr<PegasusPPB> pocket_power_box(
new PegasusPPB());
41 lastSensorData.reserve(PA_N);
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);
99 IUFillSwitchVector(&AutoDewSP, AutoDewS, 2,
getDeviceName(),
"AUTO_DEW",
"Auto Dew", DEW_TAB,
IP_RW,
ISR_1OFMANY, 60,
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);
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);
147 setupComplete =
true;
164 setupComplete =
false;
172 return "Pegasus PPB";
175 bool PegasusPPB::Handshake()
177 int tty_rc = 0, nbytes_written = 0, nbytes_read = 0;
178 char command[PEGASUS_LEN] = {0}, response[PEGASUS_LEN] = {0};
184 tcflush(PortFD, TCIOFLUSH);
185 strncpy(command,
"P#\n", PEGASUS_LEN);
190 LOGF_ERROR(
"Serial write error: %s", errorMessage);
200 tcflush(PortFD, TCIOFLUSH);
203 tty_rc =
tty_nread_section(PortFD, response, PEGASUS_LEN, stopChar, 1, &nbytes_read);
210 LOGF_ERROR(
"Serial read error: %s", errorMessage);
215 tcflush(PortFD, TCIOFLUSH);
216 response[nbytes_read - 1] =
'\0';
219 setupComplete =
false;
221 return !strcmp(response,
"PPB_OK");
229 if (!strcmp(name, PowerCycleAllSP.
name))
234 char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
236 if (sendCommand(
cmd, res))
247 if (!strcmp(name, DSLRPowerSP.
name))
250 char cmd[PEGASUS_LEN] = {0}, res[PEGASUS_LEN] = {0};
258 if (!strcmp(name, RebootSP.
name))
267 if (!strcmp(name, PowerOnBootSP.
name))
277 if (!strcmp(name, AutoDewSP.
name))
288 AutoDewS[prevIndex].s =
ISS_ON;
305 if (!strcmp(name, DewPWMNP.
name))
307 bool rc1 =
false, rc2 =
false;
308 for (
int i = 0; i < n; i++)
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));
323 if (strstr(name,
"WEATHER_"))
329 bool PegasusPPB::sendCommand(
const char *
cmd,
char * res)
331 int nbytes_read = 0, nbytes_written = 0, tty_rc = 0;
332 char command[PEGASUS_LEN] = {0};
335 for (
int i = 0; i < 2; i++)
337 tcflush(PortFD, TCIOFLUSH);
338 snprintf(command, PEGASUS_LEN,
"%s\n",
cmd);
344 tcflush(PortFD, TCIOFLUSH);
352 tcflush(PortFD, TCIOFLUSH);
353 res[nbytes_read - 1] =
'\0';
368 bool PegasusPPB::setAutoDewEnabled(
bool enabled)
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))
374 return (!strcmp(res,
cmd));
380 bool PegasusPPB::setPowerOnBoot()
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))
389 return (!strcmp(res,
"PE:1"));
395 bool PegasusPPB::setDewPWM(uint8_t
id, uint8_t value)
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))
402 return (!strcmp(res, expected));
429 bool PegasusPPB::sendFirmware()
431 char res[PEGASUS_LEN] = {0};
432 if (sendCommand(
"PV", res))
441 bool PegasusPPB::getSensorData()
443 char res[PEGASUS_LEN] = {0};
444 if (sendCommand(
"PA", res))
446 std::vector<std::string> result = split(res,
":");
447 if (result.size() < PA_N)
449 LOG_WARN(
"Received wrong number of detailed sensor data. Retrying...");
453 if (result == lastSensorData)
457 PowerSensorsN[SENSOR_VOLTAGE].value = std::stod(result[PA_VOLTAGE]);
458 PowerSensorsN[SENSOR_CURRENT].value = std::stod(result[PA_CURRENT]) / 65.0;
460 if (lastSensorData[PA_VOLTAGE] != result[PA_VOLTAGE] || lastSensorData[PA_CURRENT] != result[PA_CURRENT])
467 if (lastSensorData[PA_TEMPERATURE] != result[PA_TEMPERATURE] ||
468 lastSensorData[PA_HUMIDITY] != result[PA_HUMIDITY] ||
469 lastSensorData[PA_DEW_POINT] != result[PA_DEW_POINT])
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;
481 if (lastSensorData[PA_PORT_STATUS] != result[PA_PORT_STATUS])
487 DSLRPowerSP.
s = (std::stoi(result[PA_DSLR_STATUS]) == 1) ?
IPS_OK :
IPS_IDLE;
488 if (lastSensorData[PA_DSLR_STATUS] != result[PA_DSLR_STATUS])
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])
500 if (lastSensorData[PA_AUTO_DEW] != result[PA_AUTO_DEW])
503 lastSensorData = result;
512 bool PegasusPPB::reboot()
514 return sendCommand(
"PF",
nullptr);
517 std::vector<std::string> PegasusPPB::split(
const std::string &input,
const std::string ®ex)
520 std::regex re(regex);
521 std::sregex_token_iterator
522 first{input.begin(), input.end(), re, -1},
524 return {first, last};
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 ...
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 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.
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.
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.
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
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.
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
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.
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.
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.
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetLight(const ILightVectorProperty *lvp, const char *fmt,...)
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
#define LOGF_INFO(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)