11static std::unique_ptr<CelestronDewPower> celestronDewPower(
new CelestronDewPower());
23 return "Celestron Dew Power";
34 RebootSP[0].
fill(
"REBOOT",
"Reboot Device",
ISS_OFF);
39 PowerConsumptionNP[0].
fill(
"CONSUMPTION_AVG_AMPS",
"Avg. Amps",
"%4.2f", 0, 999, 100, 0);
40 PowerConsumptionNP[1].
fill(
"CONSUMPTION_AMP_HOURS",
"Amp Hours",
"%4.2f", 0, 999, 100, 0);
41 PowerConsumptionNP[2].
fill(
"CONSUMPTION_WATT_HOURS",
"Watt Hours",
"%4.2f", 0, 999, 100, 0);
45 PowerStatusLP[POWER_STATUS_OVERCURRENT].
fill(
"OVERCURRENT",
"Overcurrent",
IPS_IDLE);
46 PowerStatusLP[POWER_STATUS_UNDERVOLTAGE].
fill(
"UNDERVOLTAGE",
"Under Voltage",
IPS_IDLE);
47 PowerStatusLP[POWER_STATUS_OVERVOLTAGE].
fill(
"OVERVOLTAGE",
"Over Voltage",
IPS_IDLE);
51 addParameter(
"WEATHER_AMBIENT_TEMPERATURE",
"Ambient Temperature (C)", -50, 50, 15);
52 addParameter(
"WEATHER_DEW_POINT",
"Dew Point (C)", -50, 50, 15);
53 addParameter(
"WEATHER_HUMIDITY",
"Humidity (%)", 0, 100, 15);
58 AutoDewModeSP[0].
fill(
"DEW_MODE_AMBIENT",
"Above Ambient",
ISS_OFF);
59 AutoDewModeSP[1].
fill(
"DEW_MODE_DEWPOINT",
"Above Dew Point",
ISS_ON);
62 AutoDewTempNP[0].
fill(
"AUTO_DEW_TEMP",
"Temp. Offset",
"%2.0f", 0, 20, 1, 5);
87 if (sendAUXCommand(
cmd) && readAUXResponse(response))
95 int32_t ambientTemp_mC = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
96 int32_t dewPoint_mC = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
103 lastEnvironmentData = data;
146 if (!getDewPowerControllerVersion())
148 LOG_ERROR(
"Failed to get device version.");
153 if (!getNumberOfPorts())
155 LOG_ERROR(
"Failed to get number of ports.");
160 lastPortInfoData.resize(m_NumPorts);
161 lastDewHeaterPortInfoData.resize(m_NumPorts);
162 m_PortTypes.resize(m_NumPorts);
165 uint32_t capabilities = 0;
166 for (uint8_t i = 0; i < m_NumPorts; ++i)
171 if (sendAUXCommand(
cmd) && readAUXResponse(response))
185 uint8_t portType = data[0];
186 m_PortTypes[i] = portType;
195 else if (portType == 1)
202 else if (portType == 2)
204 m_NumVariablePorts++;
221 setupComplete =
true;
242 for (uint8_t i = 0; i < m_NumPorts; ++i)
244 if (m_PortTypes[i] == 1)
246 getDewHeaterPortInfo(i);
265 LOG_INFO(
"Rebooting device (not implemented yet)...");
274 AutoDewModeSP.
update(states, names, n);
276 AutoDewModeSP.
apply();
280 return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
296 AutoDewTempNP.
update(values, names, n);
298 AutoDewTempNP.
apply();
326bool CelestronDewPower::processResponse(
AUXCommand &m)
362 LOGF_DEBUG(
"Controller NAK'd command 0x%02X (not applicable to that port).",
363 data.empty() ? 0 : data[0]);
380bool CelestronDewPower::serialReadResponse(
AUXCommand &c)
383 unsigned char buf[32];
394 if (aux_tty_read((
char * )buf, 1, READ_TIMEOUT, &n) !=
TTY_OK)
397 while (buf[0] != 0x3b);
400 if (aux_tty_read((
char * )(buf + 1), 1, READ_TIMEOUT, &n) !=
TTY_OK)
404 if (aux_tty_read((
char * )(buf + 2), buf[1] + 1, READ_TIMEOUT, &n)
405 !=
TTY_OK || n != buf[1] + 1)
407 LOG_DEBUG(
"Did not got whole packet. Dropping out.");
412 hex_dump(hexbuf, b, b.size());
413 DEBUGF(DBG_SERIAL,
"RES <%s>", hexbuf);
421 DEBUGF(DBG_SERIAL,
"Got %d bytes: ; payload length field: %d ; MSG:", n, buf[1]);
430bool CelestronDewPower::readAUXResponse(
AUXCommand &c)
433 return serialReadResponse(c);
439int CelestronDewPower::sendBuffer(
AUXBuffer buf)
445 if (aux_tty_write((
char * )buf.data(), buf.size(), &n) !=
TTY_OK)
448 std::this_thread::sleep_for(std::chrono::milliseconds(50));
450 LOG_ERROR(
"CelestronDewPower::sendBuffer");
451 if ((
unsigned)n != buf.size())
452 LOGF_WARN(
"sendBuffer: incomplete send n=%d size=%d", n, (
int)buf.size());
454 char hexbuf[32 * 3] = {0};
455 hex_dump(hexbuf, buf, buf.size());
456 DEBUGF(DBG_SERIAL,
"CMD <%s>", hexbuf);
467bool CelestronDewPower::sendAUXCommand(
AUXCommand &command)
475 tcflush(PortFD, TCIOFLUSH);
476 return (sendBuffer(buf) ==
static_cast<int>(buf.size()));
495bool CelestronDewPower::tty_set_speed(speed_t speed)
523void CelestronDewPower::hex_dump(
char *buf,
AUXBuffer data,
size_t size)
525 for (
size_t i = 0; i < size; i++)
526 sprintf(buf + 3 * i,
"%02X ", data[i]);
529 buf[3 * size - 1] =
'\0';
536int CelestronDewPower::aux_tty_read(
char *buf,
int bufsiz,
int timeout,
int *n)
539 DEBUGF(DBG_SERIAL,
"aux_tty_read: %d", PortFD);
541 if((errcode =
tty_read(PortFD, buf, bufsiz, timeout, n)) !=
TTY_OK)
554int CelestronDewPower::aux_tty_write(
char *buf,
int bufsiz,
int *n)
559 errcode =
tty_write(PortFD, buf, bufsiz, n);
571bool CelestronDewPower::getDewPowerControllerVersion()
575 if (sendAUXCommand(
cmd) && readAUXResponse(response))
579 uint32_t version = response.
getData();
580 LOGF_INFO(
"Celestron Dew/Power Controller Version: %d", version);
588bool CelestronDewPower::getNumberOfPorts()
592 if (sendAUXCommand(
cmd) && readAUXResponse(response))
596 m_NumPorts = response.
getData();
597 LOGF_INFO(
"Number of ports: %d", m_NumPorts);
604bool CelestronDewPower::getInputPower()
608 if (sendAUXCommand(
cmd) && readAUXResponse(response))
617 if (data.size() >= 6)
619 uint16_t voltage_mV = (data[0] << 8) | data[1];
620 uint16_t current_mA = (data[2] << 8) | data[3];
621 int8_t voltageStatus = (int8_t)data[4];
622 uint8_t overcurrentStatus = data[5];
635 PowerStatusLP.
apply();
637 lastInputPowerData = data;
645bool CelestronDewPower::getPortInfo(uint8_t portNumber)
648 cmd.setData(portNumber, 1);
650 if (sendAUXCommand(
cmd) && readAUXResponse(response))
658 if (data.size() >= 7)
663 LOGF_DEBUG(
"Port %d Info: Type=%d, Enabled=%d, Shorted=%d, Power=%d mW, Voltage=%d mV",
664 portNumber, data[0], data[1], data[2], (data[3] << 8) | data[4], (data[5] << 8) | data[6]);
667 else if (!data.empty())
669 LOGF_DEBUG(
"Port %d Info: Type=%d (idle, no telemetry)", portNumber, data[0]);
677bool CelestronDewPower::getDewHeaterPortInfo(uint8_t portNumber)
680 cmd.setData(portNumber, 1);
682 if (sendAUXCommand(
cmd) && readAUXResponse(response))
688 if (data.size() >= 6)
693 LOGF_DEBUG(
"Dew Port %d Info: Type=%d, Mode=%d, PowerLevel=%d, Power=%d mW, Aggression=%d C",
694 portNumber, data[0], (int8_t)data[1], data[2], (data[3] << 8) | data[4], data[5]);
703bool CelestronDewPower::setPortEnabled(uint8_t portNumber,
bool enabled)
707 data.push_back(portNumber);
708 data.push_back(enabled ? 1 : 0);
709 cmd.setDataBuffer(data);
710 return sendAUXCommand(
cmd);
713bool CelestronDewPower::setPortVoltage(uint8_t portNumber, uint16_t voltage_mV)
717 data.push_back(portNumber);
718 data.push_back((voltage_mV >> 8) & 0xFF);
719 data.push_back(voltage_mV & 0xFF);
720 cmd.setDataBuffer(data);
721 return sendAUXCommand(
cmd);
724bool CelestronDewPower::setDewHeaterAuto(uint8_t portNumber, uint8_t mode, uint8_t temp_C)
728 data.push_back(portNumber);
729 data.push_back(mode);
730 data.push_back(temp_C);
731 cmd.setDataBuffer(data);
732 return sendAUXCommand(
cmd);
735bool CelestronDewPower::setDewHeaterManual(uint8_t portNumber, uint8_t powerLevel)
739 data.push_back(portNumber);
740 data.push_back(powerLevel);
741 cmd.setDataBuffer(data);
742 return sendAUXCommand(
cmd);
745bool CelestronDewPower::setLEDBrightness(uint8_t brightness)
748 cmd.setData(brightness, 1);
749 return sendAUXCommand(
cmd);
755 return setPortEnabled(
static_cast<uint8_t
>(port), enabled);
761 auto powerLevel =
static_cast<uint8_t
>(dutyCycle / 100.0 * 255.0);
762 return setDewHeaterManual(
static_cast<uint8_t
>(port), enabled ? powerLevel : 0);
768 uint16_t voltage_mV =
static_cast<uint16_t
>(voltage * 1000.0);
769 return setPortVoltage(
static_cast<uint8_t
>(port), enabled ? voltage_mV : 0);
774 return setLEDBrightness(enabled ? 255 : 0);
782 uint8_t temp_C =
static_cast<uint8_t
>(AutoDewTempNP[0].getValue());
783 return setDewHeaterAuto(
static_cast<uint8_t
>(port), mode, temp_C);
788 return setDewHeaterManual(
static_cast<uint8_t
>(port), 0);
void logBytes(unsigned char *buf, int n, const char *deviceName, uint32_t debugLevel)
std::vector< uint8_t > AUXBuffer
@ PORTCTRL_SET_LED_BRIGHTNESS
@ PORTCTRL_SET_PORT_VOLTAGE
@ PORTCTRL_SET_PORT_ENABLED
@ PORTCTRL_DH_ENABLE_MANUAL
@ PORTCTRL_GET_NUMBER_OF_PORTS
@ PORTCTRL_DH_ENABLE_AUTO
@ PORTCTRL_GET_DH_PORT_INFO
@ PORTCTRL_GET_ENVIRONMENT
@ PORTCTRL_GET_INPUT_POWER
AUXCommands command() const
const AUXBuffer & getDataBuffer() const
uint32_t getData()
Set and Get data.
void parseBuf(AUXBuffer buf)
const char * moduleName(AUXTargets n)
static void setDebugInfo(const char *deviceName, uint8_t debugLevel)
void fillBuf(AUXBuffer &buf)
Buffer Management.
const AUXTargets & destination() const
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool SetVariablePort(size_t port, bool enabled, double voltage) override
SetVariablePort Set variable voltage port.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool SetAutoDewEnabled(size_t port, bool enabled) override
SetAutoDewEnabled Enable/disable automatic dew control.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool SetLEDEnabled(bool enabled) override
SetLEDEnabled Enable/disable power LEDs.
virtual bool SetDewPort(size_t port, bool enabled, double dutyCycle) override
SetDewPort Set DEW/Dew port duty cycle.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual const char * getDefaultName() override
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual IPState updateWeather() override
updateWeather Update weather conditions from device or service. The function should not change the st...
virtual bool SetPowerPort(size_t port, bool enabled) override
SetPowerPort Set power port on/off.
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....
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.
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.
void addDebugControl()
Add Debug control to the driver.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
bool saveConfigItems(FILE *fp)
saveConfigItems Save power properties in config file
void SetCapability(uint32_t cap)
SetPowerCapability sets the Power capabilities. All capabilities must be initialized.
@ POWER_HAS_VOLTAGE_SENSOR
@ POWER_HAS_OVERALL_CURRENT
@ POWER_HAS_PER_PORT_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.
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
bool isNameMatch(const char *otherName) const
void fill(const char *device, const char *name, const char *label, const char *group, IPState state)
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
int findOnSwitchIndex() const
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....
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.
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...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Implementations for common driver routines.
#define LOGF_INFO(fmt,...)
#define LOGF_WARN(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
#define DEBUGF(priority, msg,...)
Namespace to encapsulate INDI client, drivers, and mediator classes.
static Logger & getInstance()
Method to get a reference to the object (i.e., Singleton) It is a static method.
int addDebugLevel(const char *debugLevelName, const char *LoggingLevelName)
Adds a new debugging level to the driver.
struct termios tty_setting