60 PowerMonitorNP[VOLTAGE].
fill(
"VOLTAGE",
"Voltage (V)",
"%4.2f", 0, 999, 100, 0);
70 DC1ControlNP[DC1].
fill(
"DC1",
"Dew Heater (PWM)",
"%.2f", 0, 255, 5, 0);
73 DC2ControlNP[DC2].
fill(
"DC2",
"Dew Heater (PWM)",
"%.2f", 0, 255, 5, 0);
76 DC3ControlNP[DC3].
fill(
"DC3",
"Dew Heater (PWM)",
"%.2f", 0, 255, 5, 0);
81 DC1diffSP[DC1_Manual].
fill(
"Manual",
"Manual",
ISS_ON);
82 DC1diffSP[DC1_DPD_Mode].
fill(
"DPD_Mode",
"DPD Mode",
ISS_OFF);
83 DC1diffSP[DC1_CT_Mode].
fill(
"CT_Mode",
"CT Mode",
ISS_OFF);
86 DC1diffSETNP[DC1DIFFSET].
fill(
"DC1 Auto Control",
"Dew Point Difference(C)",
"%.2f", 10, 30, 1, 0);
89 DC1constSETNP[DC1CONSTSET].
fill(
"DC1 Auto Control",
"Temperature(C)",
"%.2f", 0, 40, 1, 0);
93 DC2diffSP[DC2_Manual].
fill(
"Manual",
"Manual",
ISS_ON);
94 DC2diffSP[DC2_DPD_Mode].
fill(
"DPD_Mode",
"DPD Mode",
ISS_OFF);
95 DC2diffSP[DC2_CT_Mode].
fill(
"CT_Mode",
"CT Mode",
ISS_OFF);
98 DC2diffSETNP[DC2DIFFSET].
fill(
"DC2 Auto Control",
"Dew Point Difference(C)",
"%.2f", 10, 30, 1, 0);
101 DC2constSETNP[DC2CONSTSET].
fill(
"DC2 Auto Control",
"Temperature(C)",
"%.2f", 0, 40, 1, 0);
105 DC3diffSP[DC3_Manual].
fill(
"Manual",
"Manual",
ISS_ON);
106 DC3diffSP[DC3_DPD_Mode].
fill(
"DPD_Mode",
"DPD Mode",
ISS_OFF);
107 DC3diffSP[DC3_CT_Mode].
fill(
"CT_Mode",
"CT Mode",
ISS_OFF);
110 DC3diffSETNP[DC3DIFFSET].
fill(
"DC3 Auto Control",
"Dew Point Difference(C)",
"%.2f", 10, 30, 1, 0);
113 DC3constSETNP[DC3CONSTSET].
fill(
"DC3 Auto Control",
"Temperature(C)",
"%.2f", 0, 40, 1, 0);
117 ENVMonitorNP[Probe1_Temp].
fill(
"Probe1_Temp",
"Probe1 Temperature (C)",
"%4.2f", 0, 999, 100, 0);
118 ENVMonitorNP[Probe2_Temp].
fill(
"Probe2_Temp",
"Probe2 Temperature (C)",
"%4.2f", 0, 999, 100, 0);
119 ENVMonitorNP[Probe3_Temp].
fill(
"Probe3_Temp",
"Probe3 Temperature (C)",
"%4.2f", 0, 999, 100, 0);
120 ENVMonitorNP[ENV_Humidity].
fill(
"ENV_Humidity",
"Ambient Humidity %",
"%4.2f", 0, 999, 100, 0);
121 ENVMonitorNP[ENV_Temp].
fill(
"ENV_Temp",
"Ambient Temperature (C)",
"%4.2f", 0, 999, 100, 0);
122 ENVMonitorNP[DEW_Point].
fill(
"DEW_Point",
"Dew Point (C)",
"%4.2f", 0, 999, 100, 0);
135bool WandererDewTerminator::getData()
140 tcflush(PortFD, TCIOFLUSH);
141 int nbytes_read_name = 0,rc=-1;
149 LOGF_INFO(
"No data received, the device may not be Wanderer Dew Terminator, please check the serial port!",
"Updated");
150 LOGF_ERROR(
"Device read error: %s", errorMessage);
153 name[nbytes_read_name - 1] =
'\0';
154 if(strcmp(name,
"ZXWBPlusV3")==0||strcmp(name,
"WandererCoverV4")==0||strcmp(name,
"UltimateV2")==0||strcmp(name,
"PlusV2")==0||strcmp(name,
"ZXWBProV3")==0)
156 LOGF_INFO(
"The device is not Wanderer Dew Terminator!",
"Updated");
159 if(strcmp(name,
"ZXWBDewTerminator")!=0)
160 throw std::exception();
162 int nbytes_read_version = 0;
163 char version[64] = {0};
166 version[nbytes_read_version - 1] =
'\0';
167 firmware=std::atoi(version);
171 char temp1[64] = {0};
172 int nbytes_read_temp1= 0;
174 temp1[nbytes_read_temp1 - 1] =
'\0';
175 temp1read = std::strtod(temp1,NULL);
178 char temp2[64] = {0};
179 int nbytes_read_temp2= 0;
181 temp2[nbytes_read_temp2 - 1] =
'\0';
182 temp2read = std::strtod(temp2,NULL);
185 char temp3[64] = {0};
186 int nbytes_read_temp3= 0;
188 temp3[nbytes_read_temp3 - 1] =
'\0';
189 temp3read = std::strtod(temp3,NULL);
193 int nbytes_read_DHTH= 0;
195 DHTH[nbytes_read_DHTH - 1] =
'\0';
196 DHTHread = std::strtod(DHTH,NULL);
200 int nbytes_read_DHTT= 0;
202 DHTT[nbytes_read_DHTT - 1] =
'\0';
203 DHTTread = std::strtod(DHTT,NULL);
204 updateENV(temp1read,temp2read,temp3read,DHTHread,DHTTread);
209 char voltage[64] = {0};
210 int nbytes_read_voltage= 0;
212 voltage[nbytes_read_voltage - 1] =
'\0';
213 voltageread = std::strtod(voltage,NULL);
214 updatePower(voltageread);
220 int nbytes_read_DC1= 0;
222 DC1[nbytes_read_DC1 - 1] =
'\0';
223 DC1read = std::stoi(DC1);
228 int nbytes_read_DC2= 0;
230 DC2[nbytes_read_DC2 - 1] =
'\0';
231 DC2read = std::stoi(DC2);
236 int nbytes_read_DC3= 0;
238 DC3[nbytes_read_DC3 - 1] =
'\0';
239 DC3read = std::stoi(DC3);
246 if(DC1diffSP[DC1_DPD_Mode].getState() ==
ISS_ON)
248 if(temp1read<ENVMonitorNP[DEW_Point].value+DC1diffSETNP[DC1DIFFSET].value)
254 if(DC1CONSTMODE==
true )
256 if(temp1read<DC1constSETNP[DC1CONSTSET].value)
261 if (DC1diffSP[DC1_DPD_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe1_Temp].value==-127)
268 LOGF_ERROR(
"Temp probe 1 not connected, Dew Point Difference Mode for DC1 has exited!",
"Updated");
269 LOGF_INFO(
"You need to insert the probe firmly to the end!",
"Updated");
276 if (DC1diffSP[DC1_DPD_Mode].getState() ==
ISS_ON&&isnan(ENVMonitorNP[DEW_Point].value)==1)
283 LOGF_ERROR(
"DHT22 Humidity&Temperature sensor not connected, Dew Point Difference Mode for DC1 has exited!",
"Updated");
290 if (DC1diffSP[DC1_CT_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe1_Temp].value==-127)
297 LOGF_ERROR(
"Temp probe 1 not connected, Constant Temperature Mode for DC1 has exited!",
"Updated");
298 LOGF_INFO(
"You need to insert the probe firmly to the end!",
"Updated");
309 if(DC2DIFFMODE==
true )
311 if(temp2read<ENVMonitorNP[DEW_Point].value+DC2diffSETNP[DC2DIFFSET].value)
316 if(DC2CONSTMODE==
true )
318 if(temp2read<DC2constSETNP[DC2CONSTSET].value)
323 if (DC2diffSP[DC2_DPD_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe2_Temp].value==-127)
330 LOGF_ERROR(
"Temp probe 2 not connected, Dew Point Difference Mode for DC2 has exited!",
"Updated");
331 LOGF_INFO(
"You need to insert the probe firmly to the end!",
"Updated");
338 if (DC2diffSP[DC2_DPD_Mode].getState() ==
ISS_ON&&isnan(ENVMonitorNP[DEW_Point].value)==1)
345 LOGF_ERROR(
"DHT22 Humidity&Temperature sensor not connected, Dew Point Difference Mode for DC2 has exited!",
"Updated");
352 if (DC2diffSP[DC2_CT_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe2_Temp].value==-127)
359 LOGF_ERROR(
"Temp probe 2 not connected, Constant Temperature Mode for DC2 has exited!",
"Updated");
360 LOGF_INFO(
"You need to insert the probe firmly to the end!",
"Updated");
370 if(DC3DIFFMODE==
true )
372 if(temp3read<ENVMonitorNP[DEW_Point].value+DC3diffSETNP[DC3DIFFSET].value)
377 if(DC3CONSTMODE==
true )
379 if(temp3read<DC3constSETNP[DC3CONSTSET].value)
384 if (DC3diffSP[DC3_DPD_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe3_Temp].value==-127)
391 LOGF_ERROR(
"Temp probe 3 not connected, Dew Point Difference Mode for DC3 has exited!",
"Updated");
392 LOGF_INFO(
"You need to insert the probe firmly to the end!",
"Updated");
399 if (DC3diffSP[DC3_DPD_Mode].getState() ==
ISS_ON&&isnan(ENVMonitorNP[DEW_Point].value)==1)
406 LOGF_ERROR(
"DHT22 Humidity&Temperature sensor not connected, Dew Point Difference Mode for DC3 has exited!",
"Updated");
413 if (DC3diffSP[DC3_CT_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe3_Temp].value==-127)
420 LOGF_ERROR(
"Temp probe 3 not connected, Constant Temperature Mode for DC3 has exited!",
"Updated");
421 LOGF_INFO(
"You need to insert the probe firmly to the end!",
"Updated");
430 catch(std::exception& e)
439void WandererDewTerminator::updateENV(
double temp1,
double temp2,
double temp3,
double DHTH,
double DHTT)
441 ENVMonitorNP[Probe1_Temp].setValue(temp1);
442 ENVMonitorNP[Probe2_Temp].setValue(temp2);
443 ENVMonitorNP[Probe3_Temp].setValue(temp3);
444 ENVMonitorNP[ENV_Humidity].setValue(DHTH);
445 ENVMonitorNP[ENV_Temp].setValue(DHTT);
446 ENVMonitorNP[DEW_Point].setValue((237.7 * ((17.27 * DHTT) / (237.7 + DHTT) +
log((DHTH / 100)))) / (17.27 - ((17.27 * DHTT) / (237.7 + DHTT) +
log((DHTH / 100)))));;
448 ENVMonitorNP.
apply();
453void WandererDewTerminator::updatePower(
double voltage)
456 PowerMonitorNP[VOLTAGE].setValue(voltage);
459 PowerMonitorNP.
apply();
463void WandererDewTerminator::updateDC1(
int res)
465 DC1ControlNP[0].setValue(res);
467 DC1ControlNP.
apply();
470void WandererDewTerminator::updateDC2(
int res)
472 DC2ControlNP[0].setValue(res);
474 DC2ControlNP.
apply();
477void WandererDewTerminator::updateDC3(
int res)
479 DC3ControlNP[0].setValue(res);
481 DC3ControlNP.
apply();
495 if(firmware>=20240410)
498 LOGF_INFO(
"Firmware version: %d", firmware);
502 LOGF_INFO(
"The firmware is outdated, please upgrade to the latest firmware, or power reading calibration will be unavailable.",
"failed");
515 if(DC1diffSP[DC1_DPD_Mode].getState() ==
ISS_ON)
521 else if(DC1diffSP[DC1_CT_Mode].getState() ==
ISS_ON)
534 if(DC2diffSP[DC2_DPD_Mode].getState() ==
ISS_ON)
540 else if(DC2diffSP[DC2_CT_Mode].getState() ==
ISS_ON)
553 if(DC3diffSP[DC3_DPD_Mode].getState() ==
ISS_ON)
559 else if(DC3diffSP[DC3_CT_Mode].getState() ==
ISS_ON)
611 DC1diffSP.
update(states, names, n);
613 if(DC1diffSP[DC1_DPD_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe1_Temp].value!=-127&&isnan(ENVMonitorNP[DEW_Point].value)==0)
622 DC1diffSETNP.
apply();
625 LOGF_INFO(
"Dew Point Difference Mode for DC1 activated! WandererBox will keep the dew heater at the temperature higher than the dew point by the set value.",
"Updated");
628 else if(DC1diffSP[DC1_DPD_Mode].getState() ==
ISS_ON&&(ENVMonitorNP[Probe1_Temp].value==-127||isnan(ENVMonitorNP[DEW_Point].value)==1))
633 LOGF_INFO(
"Manual Mode for DC1 activated! Please adjust the duty cycle manually, you can also use DC1 as an ordinary switch.",
"Updated");
636 else if(DC1diffSP[DC1_CT_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe1_Temp].value!=-127)
645 DC1constSETNP.
apply();
648 LOGF_INFO(
"Constant Temperature Mode for DC1 activated! WandererBox will keep the dew heater at the set temperature.",
"Updated");
651 else if(DC1diffSP[DC1_CT_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe1_Temp].value==-127)
656 LOGF_INFO(
"Manual Mode for DC1 activated! Please adjust the duty cycle manually, you can also use DC1 as an ordinary switch.",
"Updated");
668 LOGF_INFO(
"Manual Mode for DC1 activated! Please adjust the duty cycle manually, you can also use DC1 as an ordinary switch.",
"Updated");
677 DC2diffSP.
update(states, names, n);
679 if(DC2diffSP[DC2_DPD_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe2_Temp].value!=-127&&isnan(ENVMonitorNP[DEW_Point].value)==0)
688 DC2diffSETNP.
apply();
691 LOGF_INFO(
"Dew Point Difference Mode for DC2 activated! WandererBox will keep the dew heater at the temperature higher than the dew point by the set value.",
"Updated");
694 else if(DC2diffSP[DC2_DPD_Mode].getState() ==
ISS_ON&&(ENVMonitorNP[Probe2_Temp].value==-127||isnan(ENVMonitorNP[DEW_Point].value)==1))
699 LOGF_INFO(
"Manual Mode for DC2 activated! Please adjust the duty cycle manually, you can also use DC2 as an ordinary switch.",
"Updated");
702 else if(DC2diffSP[DC2_CT_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe2_Temp].value!=-127)
711 DC2constSETNP.
apply();
714 LOGF_INFO(
"Constant Temperature Mode for DC2 activated! WandererBox will keep the dew heater at the set temperature.",
"Updated");
717 else if(DC2diffSP[DC2_CT_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe2_Temp].value==-127)
722 LOGF_INFO(
"Manual Mode for DC2 activated! Please adjust the duty cycle manually, you can also use DC2 as an ordinary switch.",
"Updated");
734 LOGF_INFO(
"Manual Mode for DC2 activated! Please adjust the duty cycle manually, you can also use DC2 as an ordinary switch.",
"Updated");
743 DC3diffSP.
update(states, names, n);
745 if(DC3diffSP[DC3_DPD_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe3_Temp].value!=-127&&isnan(ENVMonitorNP[DEW_Point].value)==0)
754 DC3diffSETNP.
apply();
757 LOGF_INFO(
"Dew Point Difference Mode for DC3 activated! WandererBox will keep the dew heater at the temperature higher than the dew point by the set value.",
"Updated");
760 else if(DC3diffSP[DC3_DPD_Mode].getState() ==
ISS_ON&&(ENVMonitorNP[Probe3_Temp].value==-127||isnan(ENVMonitorNP[DEW_Point].value)==1))
765 LOGF_INFO(
"Manual Mode for DC3 activated! Please adjust the duty cycle manually, you can also use DC3 as an ordinary switch.",
"Updated");
768 else if(DC3diffSP[DC3_CT_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe3_Temp].value!=-127)
777 DC3constSETNP.
apply();
780 LOGF_INFO(
"Constant Temperature Mode for DC3 activated! WandererBox will keep the dew heater at the set temperature.",
"Updated");
783 else if(DC3diffSP[DC3_CT_Mode].getState() ==
ISS_ON&&ENVMonitorNP[Probe3_Temp].value==-127)
788 LOGF_INFO(
"Manual Mode for DC3 activated! Please adjust the duty cycle manually, you can also use DC3 as an ordinary switch.",
"Updated");
800 LOGF_INFO(
"Manual Mode for DC3 activated! Please adjust the duty cycle manually, you can also use DC3 as an ordinary switch.",
"Updated");
806 return DefaultDevice::ISNewSwitch(dev, name, states, names, n);
817 for (
int i = 0; i < n; i++)
819 rc1 = setDewPWM(5,
static_cast<uint8_t
>(values[i]));
824 DC1ControlNP.
update(values, names, n);
825 DC1ControlNP.
apply();
833 DC1diffSETNP.
update(values, names, n);
834 DC1diffSETNP.
apply();
842 DC1constSETNP.
update(values, names, n);
843 DC1constSETNP.
apply();
850 for (
int i = 0; i < n; i++)
852 rc1 = setDewPWM(6,
static_cast<uint8_t
>(values[i]));
857 DC2ControlNP.
update(values, names, n);
858 DC2ControlNP.
apply();
866 DC2diffSETNP.
update(values, names, n);
867 DC2diffSETNP.
apply();
875 DC2constSETNP.
update(values, names, n);
876 DC2constSETNP.
apply();
883 for (
int i = 0; i < n; i++)
885 rc1 = setDewPWM(7,
static_cast<uint8_t
>(values[i]));
890 DC3ControlNP.
update(values, names, n);
891 DC3ControlNP.
apply();
899 DC3diffSETNP.
update(values, names, n);
900 DC3diffSETNP.
apply();
908 DC3constSETNP.
update(values, names, n);
909 DC3constSETNP.
apply();
918bool WandererDewTerminator::setDewPWM(uint8_t
id, uint8_t value)
921 snprintf(
cmd, 64,
"%d%03d",
id, value);
922 if (sendCommand(
cmd))
932 return "Wanderer Dew Terminator";
936bool WandererDewTerminator::sendCommand(std::string command)
938 int nbytes_written = 0, rc = -1;
939 std::string command_termination =
"\n";
945 LOGF_ERROR(
"Serial write error: %s", errorMessage);
968 DC1diffSETNP.
save(fp);
969 DC1constSETNP.
save(fp);
970 DC1ControlNP.
save(fp);
973 DC2diffSETNP.
save(fp);
974 DC2constSETNP.
save(fp);
975 DC2ControlNP.
save(fp);
978 DC3diffSETNP.
save(fp);
979 DC3constSETNP.
save(fp);
980 DC3ControlNP.
save(fp);
void log(const std::string &log)
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...
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...
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.
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)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
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 void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
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.
Implementations for common driver routines.
#define LOGF_INFO(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOGF_ERROR(fmt,...)