42#define USBDEWPOINT_TIMEOUT 3
53 DefaultDevice::initProperties();
56 TempProbeFoundSP[0].
fill(
"PROBE1",
"Probe 1",
ISS_OFF);
57 TempProbeFoundSP[1].
fill(
"PROBE2",
"Probe 2",
ISS_OFF);
58 TempProbeFoundSP[2].
fill(
"PROBE3",
"Probe 3",
ISS_OFF);
59 TempProbeFoundSP[3].
fill(
"PROBE4",
"Probe 4",
ISS_OFF);
63 TemperatureNP[0].
fill(
"CHANNEL1",
"Channel 1",
"%3.2f", -50., 120., 0., 0.);
64 TemperatureNP[1].
fill(
"CHANNEL2",
"Channel 2",
"%3.2f", -50., 120., 0., 0.);
65 TemperatureNP[2].
fill(
"CHANNEL3",
"Channel 3",
"%3.2f", -50., 120., 0., 0.);
66 TemperatureNP[3].
fill(
"CHANNEL4",
"Channel 4",
"%3.2f", -50., 120., 0., 0.);
70 AmbientTemperatureNP[0].
fill(
"AMBIENT",
"Ambient",
"%3.2f", 0., 100., 0., 0.);
74 HumidityNP[0].
fill(
"HUMIDITY",
"Humidity",
"%3.2f", 0., 100., 0., 0.);
78 DewpointNP[0].
fill(
"DEWPOINT",
"Dew point",
"%3.2f", -50., 120., 0., 0.);
82 ChannelOffsetNP[0].
fill(
"CHANNEL1",
"Channel 1",
"%1.2f", -5., 5., 0.25, 0.);
83 ChannelOffsetNP[1].
fill(
"CHANNEL2",
"Channel 2",
"%1.2f", -5., 5., 0.25, 0.);
84 ChannelOffsetNP[2].
fill(
"CHANNEL3",
"Channel 3",
"%1.2f", -5., 5., 0.25, 0.);
85 ChannelOffsetNP[3].
fill(
"CHANNEL4",
"Channel 4",
"%1.2f", -5., 5., 0.25, 0.);
89 AmbientOffsetNP[0].
fill(
"AMBIENT",
"Ambient",
"%1.2f", -4., 3., 0.25, 0.);
93 TrackingOffsetNP[0].
fill(
"TRACKING",
"Tracking",
"%1.0f", -4, 3, 1, 0);
98 Ch3ModeSP[1].
fill(
"CHANNEL1",
"Channel 1",
ISS_OFF);
99 Ch3ModeSP[2].
fill(
"CHANNEL2",
"Channel 2",
ISS_OFF);
101 Ch3ModeSP[4].
fill(
"CHANNEL3",
"Channel 3",
ISS_ON);
105 TrackingModeSP[0].
fill(
"AMBIENT",
"Ambient",
ISS_OFF);
106 TrackingModeSP[1].
fill(
"DEWPOINT",
"Dewpoint",
ISS_OFF);
107 TrackingModeSP[2].
fill(
"MIDPOINT",
"Midpoint",
ISS_OFF);
111 ChannelBoostSP[0].
fill(
"CHANNEL1",
"Channel 1",
ISS_OFF);
112 ChannelBoostSP[1].
fill(
"CHANNEL2",
"Channel 2",
ISS_OFF);
113 ChannelBoostSP[2].
fill(
"CHANNEL3",
"Channel 3",
ISS_OFF);
114 ChannelBoostSP[3].
fill(
"CHANNEL4",
"Channel 4",
ISS_OFF);
115 ChannelBoostSP[4].
fill(
"RESETALL",
"Reset All",
ISS_OFF);
120 FWversionNP[0].
fill(
"FIRMWARE",
"Firmware Version",
"%3.0f", 0, 999, 0, 0);
124 CheckCodeTP[0].
fill(
"CNTR_CODE",
"Handshake Code",
nullptr);
169 DefaultDevice::updateProperties();
182 if (myDCP4Firmware > 109)
190 if (myDCP4Firmware > 109)
195 LOG_INFO(
"myDCP4ESP32 parameters updated, device ready for use.");
208 if (myDCP4Firmware > 109)
216 if (myDCP4Firmware > 109)
226 return "MyDCP4ESP32";
230int MyDCP4ESP::msleep(
long duration)
241 ts.tv_sec = duration / 1000;
242 ts.tv_nsec = (duration % 1000) * 1000000;
246 res = nanosleep(&ts, &ts);
248 while (res &&
errno == EINTR);
253bool MyDCP4ESP::sendCommand(
const char *
cmd,
char *resp)
255 int nbytes_written = 0, nbytes_read = 0, rc = -1;
259 tcflush(PortFD, TCIOFLUSH);
268 msleep(MDCP_SMALL_DELAY);
275 LOGF_ERROR(
"Error reading response for command <%s>: %s.",
cmd, errstr);
281 LOGF_ERROR(
"Invalid response <%s> for command <%s>.", resp,
cmd);
286 resp[nbytes_read - 1] =
'\0';
295bool MyDCP4ESP::getActiveChannels()
299 int output[4] = {0, 0, 0, 0};
301 unsigned int channel_boost = 0;
302 unsigned int currentCh3Mode = 0;
308 channelActive[i] = 1;
314 TempProbeFoundSP.
apply();
316 if (myDCP4Firmware > 109)
333 if ((output[i] == 0) || (i == 2))
344 if ((ok != 1) || (currentCh3Mode > 4))
347 if (currentCh3Mode != CH3MODE_CH3TEMP)
348 if (!setCh3Mode( CH3MODE_CH3TEMP ))
352 if (!setChannelBoost( i + 1, 1))
359 if (!sendCommand(
cmd, resp))
364 if ((ok == 1) && (channel_boost == 0))
367 channelActive[i] = 0;
370 if (!setChannelBoost( i + 1, 0))
373 if ((i == 2) && (currentCh3Mode != CH3MODE_CH3TEMP))
374 if (!setCh3Mode(currentCh3Mode))
389 TempProbeFoundSP.
apply();
393 for (i = 0; i < 4; i++)
403bool MyDCP4ESP::Handshake()
419 LOG_INFO(
"myDCP4ESP32 is online. Getting device parameters...");
420 if (!getActiveChannels())
421 LOG_INFO(
"Could not determine active channels. Default to all active.");
424 LOG_INFO(
"Error retrieving data from myDCP4ESP32, retrying...");
426 while (--tries > 0 );
428 LOG_INFO(
"Error retrieving data from myDCP4ESP32, please ensure controller "
429 "is powered and the port is correct.");
454 CheckCodeTP[0].setText(code);
458 tcflush(PortFD, TCIOFLUSH);
472 myDCP4Firmware = firmware;
473 FWversionNP[0].setValue(firmware);
480bool MyDCP4ESP::setChannelOffset(
unsigned int channel,
float value)
506 return sendCommand(
cmd,
nullptr);
510bool MyDCP4ESP::setAmbientOffset(
float value)
515 return sendCommand(
cmd,
nullptr);
519bool MyDCP4ESP::setChannelBoost(
unsigned int channel,
unsigned int value)
522 if ((channel == 5) || (value == 0))
525 return sendCommand(
cmd,
nullptr);
527 else if (channel != 5)
531 LOG_ERROR(
"Invalid channel for setChannelBoost");
536 if (TempProbeFoundSP[channel - 1].getState() ==
ISS_OFF)
538 LOGF_INFO(
"Cannot set 100%% boost for Channel %d as no temperature probe is attached.", channel);
546 LOG_INFO(
"Cannot set 100%% boost for Channel 3 when Ch3 Mode is not set to Channel 3.");
551 return sendCommand(
cmd,
nullptr);
558bool MyDCP4ESP::setTrackingMode(
unsigned int value)
563 return sendCommand(
cmd,
nullptr);
567bool MyDCP4ESP::setCh3Mode(
unsigned int value)
573 if (value != CH3MODE_CH3TEMP)
574 setChannelBoost(3, 0);
577 return sendCommand(
cmd,
nullptr);
581bool MyDCP4ESP::setCh3Output(
unsigned int value)
586 return sendCommand(
cmd,
nullptr);
590bool MyDCP4ESP::setTrackingOffset(
int value)
595 return sendCommand(
cmd,
nullptr);
599bool MyDCP4ESP::rebootController()
601 LOG_INFO(
"Rebooting Controller and Disconnecting.");
608 LOG_INFO(
"Waiting 10 seconds before attempting to reconnect.");
619 LOGF_INFO(
"Could not reconnect waiting 10 seconds before attempt %d of 5.", i);
622 LOGF_ERROR(
"Could not reconnect after %d attempts", i - 1);
632 while ((i != 0) && (i <= 5));
644 return readSettings();
650 setChannelBoost(5, 1);
654 for (
int i = 0; i < 4; i++)
656 if (ChannelBoostSP[i].getState() != states[i] )
657 setChannelBoost(i+1, states[i]);
661 ChannelBoostSP.
update(states, names, n);
663 ChannelBoostSP.
apply();
670 Ch3ModeSP.
update(states, names, n);
680 TrackingModeSP.
update(states, names, n);
682 TrackingModeSP.
apply();
698 return readSettings();
702 ChannelOffsetNP.
update(values, names, n);
704 ChannelOffsetNP.
apply();
705 setChannelOffset(1, ChannelOffsetNP[0].getValue());
706 setChannelOffset(2, ChannelOffsetNP[1].getValue());
707 setChannelOffset(3, ChannelOffsetNP[2].getValue());
708 setChannelOffset(4, ChannelOffsetNP[3].getValue());
715 AmbientOffsetNP.
update(values, names, n);
717 AmbientOffsetNP.
apply();
718 setAmbientOffset(AmbientOffsetNP[0].getValue());
725 TrackingOffsetNP.
update(values, names, n);
727 TrackingOffsetNP.
apply();
728 setTrackingOffset(TrackingOffsetNP[0].getValue());
743 return readSettings();
750 DefaultDevice::saveConfigItems(fp);
754 ChannelOffsetNP.
save(fp);
755 AmbientOffsetNP.
save(fp);
756 TrackingOffsetNP.
save(fp);
758 TrackingModeSP.
save(fp);
763bool MyDCP4ESP::readSettings()
767 float temp1, temp2, temp3, temp4, temp_ambient,
humidity, dewpoint;
768 unsigned int output1, output2, output3, output4;
769 float ambient_offset, offset1, offset2, offset3, offset4;
771 unsigned int tracking_mode, ch3_mode, channel_boost;
782 AmbientOffsetNP[0].setValue(ambient_offset);
784 AmbientOffsetNP.
apply();
800 AmbientTemperatureNP[0].setValue(temp_ambient + ambient_offset);
802 AmbientTemperatureNP.
apply();
805 LOGF_ERROR(
"Get Ambient Temperature: Response <%s> for Command <%s> not recognized.", resp,
835 DewpointNP[0].setValue(dewpoint);
851 if ((ok == 1) && (ch3_mode <= 4))
860 if ((ch3_mode == CH3MODE_CH3TEMP) && (TempProbeFoundSP[2].getState() ==
ISS_ON))
899 ChannelOffsetNP[0].setValue(offset1);
900 ChannelOffsetNP[1].setValue(offset2);
901 ChannelOffsetNP[2].setValue(offset3);
902 ChannelOffsetNP[3].setValue(offset4);
904 ChannelOffsetNP.
apply();
921 TemperatureNP[0].setValue(temp1 + (offset1 * channelActive[0]));
922 TemperatureNP[1].setValue(temp2 + (offset2 * channelActive[1]));
925 TemperatureNP[2].setValue(temp3 + (offset3 * channelActive[2]));
927 TemperatureNP[2].setValue( 0 );
929 TemperatureNP[3].setValue(temp4 + (offset4 * channelActive[3]));
931 TemperatureNP.
apply();
944 if ((ok == 1) && (tracking_mode > 0) && (tracking_mode <= 3))
947 TrackingModeSP.
reset();
950 TrackingModeSP.
apply();
955 TrackingModeSP.
reset();
957 TrackingModeSP.
apply();
966 if (myDCP4Firmware > 109)
977 TrackingOffsetNP[0].setValue(tracking_offset);
979 TrackingOffsetNP.
apply();
987 if (myDCP4Firmware > 109)
990 ChannelBoostSP.
reset();
992 for (
int i = 1; i <= 4; i++)
1000 if (!sendCommand(
cmd, resp))
1005 if ((ok == 1) && (channel_boost <= 1))
1010 LOGF_ERROR(
"Get Channel Overrides: Response <%s> for Command <%s> not recognized.", resp,
cmd);
1014 ChannelBoostSP.
apply();
1072 setCh3Output(
static_cast<unsigned int>(dutyCycle));
1077 LOG_WARN(
"Channel 3 must be in Manual mode to set Dew port duty cycle.");
1082 LOGF_WARN(
"Dew port duty cycle cannot be set for Channel %zu.", port + 1);
1109 if (enabled && (TempProbeFoundSP[2].getState() ==
ISS_ON))
1111 return setCh3Mode(CH3MODE_CH3TEMP);
1115 return setCh3Mode(CH3MODE_MANUAL);
1117 LOG_INFO(
"AutoDew for Channel 3 can only be enabled if a temperature probe is attached.");
1122 LOGF_INFO(
"AutoDew cannot be enabled/disabled for Channel %zu.", port + 1);
1130 return rebootController();
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 ...
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
The TCP class manages connection with devices over the network via TCP/IP. Upon successful connection...
void setDefaultHost(const char *addressHost)
void setDefaultPort(uint32_t addressPort)
const char * getDeviceName() const
void addPollPeriodControl()
Add Polling period control to the driver.
void addConfigurationControl()
Add Configuration control to the driver.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
virtual bool Disconnect()
Disconnect from device.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
virtual void setConnected(bool status, IPState state=IPS_OK, const char *msg=nullptr)
Set connection switch status in the client.
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 loadConfig(bool silent=false, const char *property=nullptr)
Load the last saved configuration file.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
void RemoveTimer(int id)
Remove timer added with SetTimer.
Connection::Interface * getActiveConnection()
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
virtual bool Connect()
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
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.
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.
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::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 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 fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
virtual bool SetAutoDewEnabled(size_t port, bool enabled) override
SetAutoDewEnabled Enable/disable automatic dew control.
virtual const char * getDefaultName() override
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool SetPowerPort(size_t port, bool enabled) override
SetPowerPort Set power port on/off.
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 CyclePower() override
CyclePower Cycle power to all ports.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
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 saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool SetDewPort(size_t port, bool enabled, double dutyCycle) override
SetDewPort Set DEW/Dew port duty cycle.
virtual bool SetUSBPort(size_t port, bool enabled) override
SetUSBPort Set USB port on/off.
virtual bool SetVariablePort(size_t port, bool enabled, double voltage) override
SetVariablePort Set variable voltage port.
const char * CONNECTION_TAB
CONNECTION_TAB Where all device connection settings (serial, usb, ethernet) are defined and controlle...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
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 LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
std::unique_ptr< MyDCP4ESP > mydcp4esp(new MyDCP4ESP())
#define MDCP_SET_TRACKING_OFFSET_CMD
#define MDCP_SET_CH3_MANUAL_POWER_CMD
#define MDCP_GET_AMBIENT_OFFSET_RES
#define CDRIVER_VERSION_MAJOR
#define MDCP_GET_HUMIDITY_RES
#define MDCP_SET_TRACKING_MODE_CMD
#define MDCP_GET_VERSION_RES
#define MDCP_GET_TRACKING_OFFSET_CMD
#define CDRIVER_VERSION_MINOR
#define MDCP_GET_CHANNEL_TEMPS_RES
#define MDCP_GET_ALL_CH_OFFSET_CMD
#define MDCP_SET_CH2_OFFSET_CMD
#define MDCP_GET_ALL_CH_POWER_RES
#define MDCP_GET_AMBIENT_OFFSET_CMD
#define MDCP_GET_CH_OVERIDE_CMD
#define MDCP_SET_AMBIENT_OFFSET_CMD
#define MDCP_SET_CH3_OFFSET_CMD
#define MDCP_SET_CH_100_CMD
#define MDCP_RESET_CH_100_CMD
#define MDCP_GET_CH3_MODE_CMD
#define MDCP_GET_CH_OVERIDE_RES
#define MDCP_GET_TRACKING_OFFSET_RES
#define MDCP_GET_VERSION_CMD
#define MDCP_GET_ALL_CH_POWER_CMD
#define MDCP_GET_CH3_MODE_RES
#define MDCP_GET_CONTROLLER_CODE_RES
#define MDCP_GET_HUMIDITY_CMD
#define MDCP_GET_TRACKING_MODE_RES
#define MDCP_GET_TRACKING_MODE_CMD
#define MDCP_RESPONSE_LENGTH
#define MDCP_GET_AMBIENT_TEMPERATURE_RES
#define MDCP_GET_AMBIENT_TEMPERATURE_CMD
#define MDCP_GET_CHANNEL_TEMPS_CMD
#define MDCP_GET_DEWPOINT_RES
#define MDCP_SET_CH1_OFFSET_CMD
#define MDCP_GET_ALL_CH_OFFSET_RES
#define MDCP_GET_DEWPOINT_CMD
#define MDCP_GET_CONTROLLER_CODE_CMD
#define MDCP_SET_CH4_OFFSET_CMD
#define MDCP_SET_CH3_MODE_CMD
Namespace to encapsulate INDI client, drivers, and mediator classes.