diff --git a/drivers.xml b/drivers.xml index 22471bcfef..7a1f10f910 100644 --- a/drivers.xml +++ b/drivers.xml @@ -749,6 +749,10 @@ indi_wandererbox_pro_v3 1.0 + + indi_wandererbox_plus_v3 + 1.0 + diff --git a/drivers/auxiliary/CMakeLists.txt b/drivers/auxiliary/CMakeLists.txt index b68e845325..6bf1480ad9 100644 --- a/drivers/auxiliary/CMakeLists.txt +++ b/drivers/auxiliary/CMakeLists.txt @@ -1,6 +1,14 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") INSTALL(FILES 99-indi_auxiliary.rules DESTINATION ${UDEVRULES_INSTALL_DIR}) ENDIF() +# ########## Wanderer Box Plus V3 ############### +SET(indi_wandererbox_plus_v3_SRC + wandererbox_plus_v3.cpp) + +add_executable(indi_wandererbox_plus_v3 ${indi_wandererbox_plus_v3_SRC}) +target_link_libraries(indi_wandererbox_plus_v3 indidriver) +install(TARGETS indi_wandererbox_plus_v3 RUNTIME DESTINATION bin) + # ########## Wanderer Box Pro V3 ############### SET(indi_wandererbox_pro_v3_SRC wandererbox_pro_v3.cpp) diff --git a/drivers/auxiliary/wandererbox_plus_v3.cpp b/drivers/auxiliary/wandererbox_plus_v3.cpp new file mode 100644 index 0000000000..0cc1ba1e9f --- /dev/null +++ b/drivers/auxiliary/wandererbox_plus_v3.cpp @@ -0,0 +1,686 @@ +/******************************************************************************* + Copyright(c) 2024 Frank Wang. All rights reserved. + + WandererBox Plus V3 + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. +*******************************************************************************/ + +#include "wandererbox_plus_v3.h" +#include "indicom.h" +#include "connectionplugins/connectionserial.h" +#include +#include +#include +#include +#include +#include +#include +#include + +// We declare an auto pointer to WandererBoxPlusV3. +static std::unique_ptr WandererBoxplusv3(new WandererBoxPlusV3()); + + + +WandererBoxPlusV3::WandererBoxPlusV3() +{ + setVersion(1, 0); +} + +bool WandererBoxPlusV3::initProperties() +{ + + INDI::DefaultDevice::initProperties(); + setDriverInterface(AUX_INTERFACE); + + + addAuxControls(); + + + // Calibrate + CalibrateSP[0].fill("Calibrate", "Calibrate Current", ISS_OFF); + CalibrateSP.fill(getDeviceName(), "Calibrate_DEVICE", "Calibrate Current", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1,60, IPS_IDLE); + + // Power Monitor + PowerMonitorNP[VOLTAGE].fill("VOLTAGE", "Voltage (V)", "%4.2f", 0, 999, 100, 0); + PowerMonitorNP[TOTAL_CURRENT].fill("TOTAL_CURRENT", "Total Current (A)", "%4.2f", 0, 999, 100, 0); + PowerMonitorNP.fill(getDeviceName(), "POWER_Monitor", "Power Monitor", MAIN_CONTROL_TAB, IP_RO,60, IPS_IDLE); + + + // USB Control + USBControlSP[INDI_ENABLED].fill("INDI_ENABLED", "On", ISS_OFF); + USBControlSP[INDI_DISABLED].fill("INDI_DISABLED", "Off", ISS_OFF); + USBControlSP.fill(getDeviceName(), "USB", "USB", MAIN_CONTROL_TAB, IP_RW,ISR_1OFMANY, 60, IPS_IDLE); + + + // DC3 + DC3ControlNP[DC3].fill( "DC3", "Dew Heater (PWM)", "%.2f", 0, 255, 5, 0); + DC3ControlNP.fill(getDeviceName(), "PWM", "DC3", DC3_TAB, IP_RW, 60, IPS_IDLE); + + // DC2SET + setDC2voltageNP[setDC2voltage].fill( "DC2SET", "Adjustable Voltage", "%.2f", 5, 13.2, 0.1, 0); + setDC2voltageNP.fill(getDeviceName(), "DC2voltageSET", "Set DC2", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); + // DC2 Control + dc2ControlSP[INDI_ENABLED].fill( "INDI_ENABLED", "On", ISS_OFF); + dc2ControlSP[INDI_DISABLED].fill( "INDI_DISABLED", "Off", ISS_ON); + dc2ControlSP.fill(getDeviceName(), "DC2", "DC2", MAIN_CONTROL_TAB, IP_RW,ISR_1OFMANY, 60, IPS_IDLE); + + // DC4-6 Control + DC4_6ControlSP[INDI_ENABLED].fill( "INDI_ENABLED", "On", ISS_OFF); + DC4_6ControlSP[INDI_DISABLED].fill( "INDI_DISABLED", "Off", ISS_ON); + DC4_6ControlSP.fill(getDeviceName(), "DC4-6", "DC4-6", MAIN_CONTROL_TAB, IP_RW,ISR_1OFMANY, 60, IPS_IDLE); + + // DC3 TEMP Difference Control + DC3diffSP[DC3_Manual].fill( "Manual", "Manual", ISS_ON); + DC3diffSP[DC3_DPD_Mode].fill( "DPD_Mode", "DPD Mode", ISS_OFF); + DC3diffSP[DC3_CT_Mode].fill( "CT_Mode", "CT Mode", ISS_OFF); + DC3diffSP.fill(getDeviceName(), "DC3_DIFF", "DC3 Dew Mode", DC3_TAB, IP_RW,ISR_1OFMANY, 60, IPS_IDLE); + + DC3diffSETNP[DC3DIFFSET].fill( "DC3 Auto Control", "Dew Point Difference(C)", "%.2f", 10, 30, 1, 0); + DC3diffSETNP.fill(getDeviceName(), "DC3_DIFF_SET", "DPD Mode", DC3_TAB, IP_RW, 60, IPS_IDLE); + + DC3constSETNP[DC3CONSTSET].fill( "DC3 Auto Control", "Temperature(C)", "%.2f", 0, 40, 1, 0); + DC3constSETNP.fill(getDeviceName(), "DC3_CONST_SET", "CT Mode", DC3_TAB, IP_RW, 60, IPS_IDLE); + + //ENV + ENVMonitorNP[Probe1_Temp].fill( "Probe1_Temp", "Probe1 Temperature (C)", "%4.2f", 0, 999, 100, 0); + ENVMonitorNP[ENV_Humidity].fill( "ENV_Humidity", "Ambient Humidity %", "%4.2f", 0, 999, 100, 0); + ENVMonitorNP[ENV_Temp].fill( "ENV_Temp", "Ambient Temperature (C)", "%4.2f", 0, 999, 100, 0); + ENVMonitorNP[DEW_Point].fill( "DEW_Point", "Dew Point (C)", "%4.2f", 0, 999, 100, 0); + ENVMonitorNP.fill(getDeviceName(), "ENV_Monitor", "Environment",ENVIRONMENT_TAB, IP_RO,60, IPS_IDLE); + serialConnection = new Connection::Serial(this); + serialConnection->setDefaultBaudRate(Connection::Serial::B_19200); + serialConnection->registerHandshake([&]() + { + return getData(); + }); + registerConnection(serialConnection); + + return true; +} + +bool WandererBoxPlusV3::getData() +{ + try + { + PortFD = serialConnection->getPortFD(); + tcflush(PortFD, TCIOFLUSH); + int nbytes_read_name = 0,rc=-1; + char name[64] = {0}; + + //Device Model////////////////////////////////////////////////////////////////////////////////////////////////////// + if ((rc = tty_read_section(PortFD, name, 'A', 3, &nbytes_read_name)) != TTY_OK) + { + char errorMessage[MAXRBUF]; + tty_error_msg(rc, errorMessage, MAXRBUF); + LOGF_INFO("No data received, the device may not be WandererBox Plus V3, please check the serial port!","Updated"); + LOGF_ERROR("Device read error: %s", errorMessage); + return false; + } + name[nbytes_read_name - 1] = '\0'; + if(strcmp(name, "ZXWBProV3")==0||strcmp(name, "WandererCoverV4")==0||strcmp(name, "UltimateV2")==0||strcmp(name, "PlusV2")==0) + { + LOGF_INFO("The device is not WandererBox Plus V3!","Updated"); + return false; + } + if(strcmp(name, "ZXWBPlusV3")!=0) + throw std::exception(); + // Frimware version///////////////////////////////////////////////////////////////////////////////////////////// + int nbytes_read_version = 0; + char version[64] = {0}; + tty_read_section(PortFD, version, 'A', 5, &nbytes_read_version); + + version[nbytes_read_version - 1] = '\0'; + firmware=std::atoi(version); + + + // Temp probe 1////////////////////////////////////////////////////////////////////////////////////////// + char temp1[64] = {0}; + int nbytes_read_temp1= 0; + tty_read_section(PortFD, temp1, 'A', 5, &nbytes_read_temp1); + temp1[nbytes_read_temp1 - 1] = '\0'; + temp1read = std::strtod(temp1,NULL); + + // DHTH////////////////////////////////////////////////////////////////////////////////////////// + char DHTH[64] = {0}; + int nbytes_read_DHTH= 0; + tty_read_section(PortFD, DHTH, 'A', 5, &nbytes_read_DHTH); + DHTH[nbytes_read_DHTH - 1] = '\0'; + DHTHread = std::strtod(DHTH,NULL); + + // DHTT////////////////////////////////////////////////////////////////////////////////////////// + char DHTT[64] = {0}; + int nbytes_read_DHTT= 0; + tty_read_section(PortFD, DHTT, 'A', 5, &nbytes_read_DHTT); + DHTT[nbytes_read_DHTT - 1] = '\0'; + DHTTread = std::strtod(DHTT,NULL); + updateENV(temp1read,DHTHread,DHTTread); + + // Total current////////////////////////////////////////////////////////////////////////////////////////// + char Tcurrent[64] = {0}; + int nbytes_read_Tcurrent= 0; + tty_read_section(PortFD, Tcurrent, 'A', 5, &nbytes_read_Tcurrent); + Tcurrent[nbytes_read_Tcurrent - 1] = '\0'; + Tcurrentread = std::strtod(Tcurrent,NULL); + + // Voltage////////////////////////////////////////////////////////////////////////////////////////// + char voltage[64] = {0}; + int nbytes_read_voltage= 0; + tty_read_section(PortFD, voltage, 'A', 5, &nbytes_read_voltage); + voltage[nbytes_read_voltage - 1] = '\0'; + voltageread = std::strtod(voltage,NULL); + updatePower(Tcurrentread,voltageread); + + // USB////////////////////////////////////////////////////////////////////////////////////////// + char USB[64] = {0}; + int nbytes_read_USB= 0; + tty_read_section(PortFD, USB, 'A', 5, &nbytes_read_USB); + USB[nbytes_read_USB - 1] = '\0'; + USBread = std::stoi(USB); + updateUSB(USBread); + + + // DC2////////////////////////////////////////////////////////////////////////////////////////// + char DC2[64] = {0}; + int nbytes_read_DC2= 0; + tty_read_section(PortFD, DC2, 'A', 5, &nbytes_read_DC2); + DC2[nbytes_read_DC2 - 1] = '\0'; + DC2read = std::stoi(DC2); + updateDC2(DC2read); + + // DC3////////////////////////////////////////////////////////////////////////////////////////// + char DC3[64] = {0}; + int nbytes_read_DC3= 0; + tty_read_section(PortFD, DC3, 'A', 5, &nbytes_read_DC3); + DC3[nbytes_read_DC3 - 1] = '\0'; + DC3read = std::stoi(DC3); + updateDC3(DC3read); + + + // DC4_6////////////////////////////////////////////////////////////////////////////////////////// + char DC4_6[64] = {0}; + int nbytes_read_DC4_6= 0; + tty_read_section(PortFD, DC4_6, 'A', 5, &nbytes_read_DC4_6); + DC4_6[nbytes_read_DC4_6 - 1] = '\0'; + DC4_6read =std::stoi(DC4_6); + updateDC4_6(DC4_6read); + + + // DC2SET////////////////////////////////////////////////////////////////////////////////////////// + char DC2SET[64] = {0}; + int nbytes_read_DC2SET= 0; + tty_read_section(PortFD, DC2SET, 'A', 5, &nbytes_read_DC2SET); + DC2SET[nbytes_read_DC2SET - 1] = '\0'; + //LOGF_INFO("All Data Updated","Updated"); + DC2SETread = std::stoi(DC2SET); + updateDC2SET(DC2SETread); + + + //DC3 DEW CONTROL + if(DC3diffSP[DC3_DPD_Mode].getState() == ISS_ON) + { + if(temp1read=20240216) + { + defineProperty(CalibrateSP); + LOGF_INFO("Firmware version: %d", firmware); + } + else + { + LOGF_INFO("The firmware is outdated, please upgrade to the latest firmware, or power reading calibration will be unavailable.","failed"); + } + defineProperty(PowerMonitorNP); + + + defineProperty(USBControlSP); + + defineProperty(setDC2voltageNP); + defineProperty(dc2ControlSP); + + defineProperty(DC4_6ControlSP); + + + defineProperty(DC3diffSP); + + + + //DC3//////////////////// + if(DC3diffSP[DC3_DPD_Mode].getState() == ISS_ON) + { + deleteProperty(DC3constSETNP); + deleteProperty(DC3ControlNP); + defineProperty(DC3diffSETNP); + } + else if(DC3diffSP[DC3_CT_Mode].getState() == ISS_ON) + { + deleteProperty(DC3ControlNP); + deleteProperty(DC3diffSETNP); + defineProperty(DC3constSETNP); + } + else + { + defineProperty(DC3ControlNP); + deleteProperty(DC3diffSETNP); + deleteProperty(DC3constSETNP); + } + defineProperty(ENVMonitorNP); + + + } + else + { + + deleteProperty(CalibrateSP); + deleteProperty(PowerMonitorNP); + deleteProperty(ENVMonitorNP); + + deleteProperty(dc2ControlSP); + deleteProperty(setDC2voltageNP); + deleteProperty(DC4_6ControlSP); + + deleteProperty(USBControlSP); + + + deleteProperty(DC3ControlNP); + + + deleteProperty(DC3diffSP); + deleteProperty(DC3diffSETNP); + + + + } + return true; +} + +bool WandererBoxPlusV3::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) +{ + // Calibrate + if (CalibrateSP.isNameMatch(name)) + { + CalibrateSP.setState(sendCommand("66300744") ? IPS_OK : IPS_ALERT); + CalibrateSP.apply(); + LOG_INFO("Calibrating Current Readings..."); + return true; + } + + + // DC2 Control + if (dc2ControlSP.isNameMatch(name)) + { + dc2ControlSP.update(states, names, n); + dc2ControlSP.setState(IPS_ALERT); + char cmd[128] = {0}; + snprintf(cmd, 128, "12%d", (dc2ControlSP[INDI_ENABLED].getState() == ISS_ON) ? 1 : 0); + dc2ControlSP.setState( sendCommand(cmd) ? IPS_OK : IPS_ALERT); + dc2ControlSP.apply(); + + return true; + } + // DC4-6 Control + if (DC4_6ControlSP.isNameMatch(name)) + { + DC4_6ControlSP.update(states, names, n); + DC4_6ControlSP.setState(IPS_ALERT); + char cmd[128] = {0}; + snprintf(cmd, 128, "10%d", (DC4_6ControlSP[INDI_ENABLED].getState() == ISS_ON) ? 1 : 0); + DC4_6ControlSP.setState( sendCommand(cmd) ? IPS_OK : IPS_ALERT); + DC4_6ControlSP.apply(); + + return true; + } + + // USB Control + if (USBControlSP.isNameMatch(name)) + { + USBControlSP.update(states, names, n); + USBControlSP.setState(IPS_ALERT); + char cmd[128] = {0}; + snprintf(cmd, 128, "11%d", (USBControlSP[INDI_ENABLED].getState() == ISS_ON) ? 1 : 0); + USBControlSP.setState( sendCommand(cmd) ? IPS_OK : IPS_ALERT); + + return true; + } + + // DC3 DEW + if (DC3diffSP.isNameMatch(name)) + { + DC3diffSP.update(states, names, n); + DC3diffSP.setState(IPS_ALERT); + if(DC3diffSP[DC3_DPD_Mode].getState() == ISS_ON&&ENVMonitorNP[Probe1_Temp].value!=-127&&isnan(ENVMonitorNP[DEW_Point].value)==0) + { + DC3DIFFMODE=true; + DC3CONSTMODE=false; + deleteProperty(DC3ControlNP); + deleteProperty(DC3constSETNP); + defineProperty(DC3diffSETNP); + + DC3diffSETNP.setState(IPS_OK); + DC3diffSETNP.apply(); + DC3diffSP.setState(IPS_OK) ; + DC3diffSP.apply(); + 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"); + return true; + } + else if(DC3diffSP[DC3_DPD_Mode].getState() == ISS_ON&&(ENVMonitorNP[Probe1_Temp].value==-127||isnan(ENVMonitorNP[DEW_Point].value)==1)) + { + DC3DIFFMODE=false; + DC3CONSTMODE=false; + DC3diffSP[DC3_Manual].setState( ISS_ON); + LOGF_INFO("Manual Mode for DC3 activated! Please adjust the duty cycle manually, you can also use DC3 as an ordinary switch.","Updated"); + DC3diffSP.apply(); + } + else if(DC3diffSP[DC3_CT_Mode].getState() == ISS_ON&&ENVMonitorNP[Probe1_Temp].value!=-127) + { + DC3CONSTMODE=true; + DC3DIFFMODE=false; + deleteProperty(DC3diffSETNP); + deleteProperty(DC3ControlNP); + defineProperty(DC3constSETNP); + + DC3constSETNP.setState(IPS_OK); + DC3constSETNP.apply(); + DC3diffSP.setState(IPS_OK) ; + DC3diffSP.apply(); + LOGF_INFO("Constant Temperature Mode for DC3 activated! WandererBox will keep the dew heater at the set temperature.","Updated"); + return true; + } + else if(DC3diffSP[DC3_CT_Mode].getState() == ISS_ON&&ENVMonitorNP[Probe1_Temp].value==-127) + { + DC3DIFFMODE=false; + DC3CONSTMODE=false; + DC3diffSP[DC3_Manual].setState( ISS_ON); + LOGF_INFO("Manual Mode for DC3 activated! Please adjust the duty cycle manually, you can also use DC3 as an ordinary switch.","Updated"); + DC3diffSP.apply(); + } + else + { + DC3DIFFMODE=false; + DC3CONSTMODE=false; + defineProperty(DC3ControlNP); + deleteProperty(DC3diffSETNP); + deleteProperty(DC3constSETNP); + DC3diffSP.setState(IPS_OK) ; + DC3diffSP.apply(); + LOGF_INFO("Manual Mode for DC3 activated! Please adjust the duty cycle manually, you can also use DC3 as an ordinary switch.","Updated"); + return true; + } + + } + + + return DefaultDevice::ISNewSwitch(dev, name, states, names, n); +} + +bool WandererBoxPlusV3::ISNewNumber(const char * dev, const char * name, double values[], char * names[], int n) +{ + if (dev && !strcmp(dev, getDeviceName())) + { + // DC3 + if (DC3ControlNP.isNameMatch(name)) + { + bool rc1 = false; + for (int i = 0; i < n; i++) + { + rc1 = setDewPWM(3, static_cast(values[i])); + } + + DC3ControlNP.setState( (rc1) ? IPS_OK : IPS_ALERT); + if (DC3ControlNP.getState() == IPS_OK) + DC3ControlNP.update(values, names, n); + DC3ControlNP.apply(); + return true; + } + if (DC3diffSETNP.isNameMatch(name)) + { + + DC3diffSETNP.setState(IPS_OK) ; + if (DC3diffSETNP.getState() == IPS_OK) + DC3diffSETNP.update(values, names, n); + DC3diffSETNP.apply(); + return true; + } + if (DC3constSETNP.isNameMatch(name)) + { + + DC3constSETNP.setState(IPS_OK) ; + if (DC3constSETNP.getState() == IPS_OK) + DC3constSETNP.update(values, names, n); + DC3constSETNP.apply(); + return true; + } + + // DC2voltageSET + if (setDC2voltageNP.isNameMatch(name)) + { + bool rc1 = false; + for (int i = 0; i < n; i++) + { + rc1 = setDewPWM(20, static_cast(10*values[i])); + } + + setDC2voltageNP.setState( (rc1) ? IPS_OK : IPS_ALERT); + if (setDC2voltageNP.getState() == IPS_OK) + setDC2voltageNP.update(values, names, n); + setDC2voltageNP.apply(); + return true; + } + + + } + return INDI::DefaultDevice::ISNewNumber(dev, name, values, names, n); +} + +bool WandererBoxPlusV3::setDewPWM(uint8_t id, uint8_t value) +{ + char cmd[64] = {0}; + snprintf(cmd, 64, "%d%03d", id, value); + if (sendCommand(cmd)) + { + return true; + } + + return false; +} + +const char *WandererBoxPlusV3::getDefaultName() +{ + return "WandererBox Pro V3"; +} + + +bool WandererBoxPlusV3::sendCommand(std::string command) +{ + int nbytes_written = 0, rc = -1; + std::string command_termination = "\n"; + LOGF_DEBUG("CMD: %s", command.c_str()); + if ((rc = tty_write_string(PortFD, (command + command_termination).c_str(), &nbytes_written)) != TTY_OK) + { + char errorMessage[MAXRBUF]; + tty_error_msg(rc, errorMessage, MAXRBUF); + LOGF_ERROR("Serial write error: %s", errorMessage); + return false; + } + return true; +} + +void WandererBoxPlusV3::TimerHit() +{ + if (!isConnected()) + { + SetTimer(2500); + return; + } + + getData(); + SetTimer(2500); +} + +bool WandererBoxPlusV3::saveConfigItems(FILE * fp) +{ + INDI::DefaultDevice::saveConfigItems(fp); + + DC3diffSP.save(fp); + DC3diffSETNP.save(fp); + DC3constSETNP.save(fp); + DC3ControlNP.save(fp); + + setDC2voltageNP.save(fp); + return true; +} + diff --git a/drivers/auxiliary/wandererbox_plus_v3.h b/drivers/auxiliary/wandererbox_plus_v3.h new file mode 100644 index 0000000000..53ccc5d551 --- /dev/null +++ b/drivers/auxiliary/wandererbox_plus_v3.h @@ -0,0 +1,163 @@ +/******************************************************************************* + Copyright(c) 2024 Frank Wang. All rights reserved. + + WandererBox Plus V3 + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. +*******************************************************************************/ + +#pragma once + +#include "defaultdevice.h" +#include +#include + +namespace Connection +{ +class Serial; +} + +class WandererBoxPlusV3 : public INDI::DefaultDevice +{ +public: + WandererBoxPlusV3(); + virtual ~WandererBoxPlusV3() = default; + + virtual bool initProperties() override; + virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override; + virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; + virtual bool updateProperties() override; + + + +protected: + const char *getDefaultName() override; + virtual bool saveConfigItems(FILE *fp) override; + virtual void TimerHit() override; + + +private: + + int firmware=0; + bool sendCommand(std::string command); + bool DC3DIFFMODE=false; + bool DC3CONSTMODE=false; + bool getData(); + static constexpr const char *ENVIRONMENT_TAB {"Sensors"}; + static constexpr const char *DC3_TAB {"DC3"}; + //Current Calibrate + INDI::PropertySwitch CalibrateSP{1}; + + + //Temp1 + double temp1read = 0; + //DHTH + double DHTHread = 0; + //DHTT + void updateENV(double temp1,double DHTH,double DHTT); + double DHTTread = 0; + //Total Current + double Tcurrentread = 0; + //Power Monitor + void updatePower(double Tcurrent,double voltage); + double voltageread = 0; + //USB + void updateUSB(int value); + int USBread = 0; + //DC2 + void updateDC2(int value); + int DC2read = 0; + //DC3 + void updateDC3(int value); + int DC3read = 0; + //DC4_6 + void updateDC4_6(int value); + int DC4_6read = 0; + //DC2set + void updateDC2SET(double value); + int DC2SETread = 0; + + bool setDewPWM(uint8_t id, uint8_t value); + + //DC Control////////////////////////////////////////////////////////////////////////////////// + INDI::PropertySwitch dc2ControlSP{2}; + INDI::PropertySwitch DC4_6ControlSP{2}; + //USB Control////////////////////////////////////////////////////////////////////////////////// + INDI::PropertySwitch USBControlSP{2}; + //DC3 Control//////////////////////////////////////////////////////////////// + INDI::PropertyNumber DC3ControlNP{1}; + enum + { + DC3, + }; + //DC3 DIFF//////////////////////////////////////////////////////////////// + INDI::PropertySwitch DC3diffSP{3}; + enum + { + DC3_Manual, + DC3_DPD_Mode, + DC3_CT_Mode, + }; + + INDI::PropertyNumber DC3diffSETNP{1}; + enum + { + DC3DIFFSET, + }; + INDI::PropertyNumber DC3constSETNP{1}; + enum + { + DC3CONSTSET, + }; + + + + //DC2 Voltage Control//////////////////////////////////////////////////////////////// + INDI::PropertyNumber setDC2voltageNP{1}; + enum + { + setDC2voltage, + }; + + // Power Monitor + + INDI::PropertyNumber PowerMonitorNP{2}; + enum + { + VOLTAGE, + TOTAL_CURRENT, + }; + + // ENV Monitor + + INDI::PropertyNumber ENVMonitorNP{4}; + enum + { + Probe1_Temp, + ENV_Humidity, + ENV_Temp, + DEW_Point, + }; + + + + int PortFD{ -1 }; + + Connection::Serial *serialConnection{ nullptr }; +};