#ifndef AQUALINK_H_ #define AQUALINK_H_ #include #include #include #include "aq_serial.h" #include "aq_programmer.h" #include "sensors.h" //#include "aq_panel.h" // Moved to later in file to overcome circular dependancy. (crappy I know) #define isMASK_SET(bitmask, mask) ((bitmask & mask) == mask) #define setMASK(bitmask, mask) (bitmask |= mask) #define removeMASK(bitmask, mask) (bitmask &= ~mask) #define SIGRESTART SIGUSR1 #define SIGRUPGRADE SIGUSR2 #ifdef AQ_NO_THREAD_NETSERVICE #define DEFAULT_POLL_SPEED -1 #define DEFAULT_POLL_SPEED_NON_THREADDED 2 #endif #define CLIGHT_PANEL_FIX // Overcome bug in some jandy panels where color light status of on is not in LED status #define TIME_CHECK_INTERVAL 3600 //#define TIME_CHECK_INTERVAL 100 // DEBUG ONLY #define ACCEPTABLE_TIME_DIFF 120 // Use these settings to test time //#define TIME_CHECK_INTERVAL 100 //#define ACCEPTABLE_TIME_DIFF 10 #define MAX_ZERO_READ_BEFORE_RECONNECT_NONBLOCKING 100000 // 10k normally #define MAX_ZERO_READ_BEFORE_RECONNECT_BLOCKING (25 / (SERIAL_BLOCKING_TIME / 10) ) // Want this to be 25 seconds, so it's depdand on how long the serial blocking is // Time in ms to delay between read requests in non blocking serial port. Have to set something to stop CPU spiking. #define NONBLOCKING_SERIAL_DELAY 2 // The below will change state of devices before that are actually set on the control panel, this helps // with duplicate messages that come in quick succession that can catch the state before it happens. //#define PRESTATE_ONOFF #define PRESTATE_SWG_SETPOINT //#define PRESTATE_HEATER_SETPOINT // This one is not implimented yet void intHandler(int dummy); bool isAqualinkDStopping(); #ifdef AQ_PDA bool checkAqualinkTime(); // Only need to externalise this for PDA #endif // There are cases where SWG will read 80% in allbutton and 0% in onetouch/aqualinktouch, this will compile that in or out //#define READ_SWG_FROM_EXTENDED_ID //#define TOTAL_BUTTONS 12 /* #ifndef AQ_RS16 #define TOTAL_BUTTONS 12 #else #define TOTAL_BUTTONS 20 #define RS16_VBUTTONS_START 13 // RS16 panel has 4 buttons with no LED's, so list them for manual matching to RS messages #define RS16_VBUTTONS_END 16 // RS16 panel has 4 buttons with no LED's, so list them for manual matching to RS messages #endif */ #define TEMP_UNKNOWN -999 #define TEMP_REFRESH -998 #define AQ_UNKNOWN TEMP_UNKNOWN //#define UNKNOWN TEMP_UNKNOWN #define DATE_STRING_LEN 30 #define MAX_PUMPS 4 #define MAX_LIGHTS 4 #define MAX_SENSORS 4 bool isVirtualButtonEnabled(); #define PUMP_RPM_MAX 3450 #define PUMP_RPM_MIN 600 #define PUMP_GPM_MAX 130 #define PUMP_GPM_MIN 15 enum { FAHRENHEIT, CELSIUS, UNKNOWN }; typedef struct aqualinkkey { //int number; //aqledstate *state; aqled *led; char *label; char *name; //#ifdef AQ_PDA // char *pda_label; //#endif unsigned char code; unsigned char rssd_code; int dz_idx; uint8_t special_mask; void *special_mask_ptr; } aqkey; // special_mask for above aqualinkkey structure. #define VS_PUMP (1 << 0) #define PROGRAM_LIGHT (1 << 1) #define TIMER_ACTIVE (1 << 2) //#define DIMMER_LIGHT (1 << 3) // NOT USED (Use PROGRAM_LIGHT or type LC_DIMMER) #define VIRTUAL_BUTTON (1 << 4) // Below are types of VIRT_BUTTON, SO VIRT_BUTTON must also be set #define VIRTUAL_BUTTON_ALT_LABEL (1 << 5) #define VIRTUAL_BUTTON_CHILLER (1 << 6) //typedef struct ProgramThread ProgramThread; // Definition is later struct programmingthread { pthread_t *thread_id; pthread_mutex_t thread_mutex; pthread_cond_t thread_cond; program_type ptype; //void *thread_args; }; /* typedef enum panel_status { CONNECTED, CHECKING_CONFIG, CONECTING, LOOKING_IDS, STARTING, SERIAL_ERROR, // Errors that stop reading serial port should be below this line NO_IDS_ERROR, } panel_status; */ typedef enum action_type { NO_ACTION = -1, POOL_HTR_SETPOINT, SPA_HTR_SETPOINT, FREEZE_SETPOINT, CHILLER_SETPOINT, SWG_SETPOINT, SWG_BOOST, PUMP_RPM, PUMP_VSPROGRAM, POOL_HTR_INCREMENT, // Setpoint add value (can be negative) SPA_HTR_INCREMENT, // Setpoint add value ON_OFF, TIMER, LIGHT_MODE, LIGHT_BRIGHTNESS, DATE_TIME } action_type; struct action { action_type type; time_t requested; int value; int id; // Only used for Pumps at the moment. //char value[10]; }; // Moved to aq_programmer to stop circular dependancy /* typedef enum pump_type { PT_UNKNOWN = -1, EPUMP, VSPUMP, VFPUMP } pump_type; */ /* typedef enum simulator_type { SIM_NONE, SIM_ALLB, SIM_ONET, SIM_PDA, SIM_IAQT } simulator_type; */ // Set Point types typedef enum SP_TYPE{ SP_POOL, SP_SPA, SP_CHILLER } SP_TYPE; //#define PUMP_PRIMING -1 //#define PUMP_OFFLINE -2 //#define PUMP_ERROR -3 #define PUMP_OFF_RPM 0 #define PUMP_OFF_GPM PUMP_OFF_RPM #define PUMP_OFF_WAT PUMP_OFF_RPM // FUTURE VSP STATUS, keep panel status and RS485 status seperate typedef enum panel_vsp_status { PS_OK = 0, // Start at 0 to match actual status from RS, but go down from their. PS_OFF = -1, PS_PRIMING = -2, PS_OFFLINE = -3, PS_ERROR = -4 } panel_vsp_status; #define PUMP_NAME_LENGTH 30 // Overall Status of Aqualinkd #define CONNECTED ( 1 << 0 ) // All is good (every other mask should be cleared) #define NOT_CONNECTED ( 1 << 2 ) // Serial Error maybe rename #define AUTOCONFIGURE_ID ( 1 << 3 ) #define AUTOCONFIGURE_PANEL ( 1 << 4 ) #define CHECKING_CONFIG ( 1 << 5 ) //#define LOOKING_IDS ( 1 << 6 ) #define CONNECTING ( 1 << 7 ) #define ERROR_NO_DEVICE_ID ( 1 << 8 ) // maybe covered in NOT_CONNECTED #define ERROR_SERIAL ( 1 << 9 ) typedef struct pumpd { int rpm; int gpm; int watts; int maxSpeed; // Max rpm or gpm depending on pump int minSpeed; unsigned char pumpID; int pumpIndex; char pumpName[PUMP_NAME_LENGTH]; //char *pumpName; pump_type pumpType; //int buttonID; protocolType prclType; aqkey *button; //bool updated; // Other VSP values read directly from RS485 int mode; // 0 local control, 1 remote control //int driveState; // Haven't figured out what this is yet int status; panel_vsp_status pStatus; // FUTURE VSP STATUS, int pressureCurve; } pump_detail; // color light modes (Aqualink program, Jandy, Jandy LED, SAm/SAL, Color Logic, Intellibrite) typedef enum clight_type { LC_PROGRAMABLE=0, LC_JANDY, LC_JANDYLED, LC_SAL, LC_CLOGIG, LC_INTELLIB, LC_HAYWCL, LC_SPARE_1, LC_SPARE_2, LC_SPARE_3, LC_DIMMER, // use 0, 25, 50, 100 LC_DIMMER2, // use range 0 to 100 NUMBER_LIGHT_COLOR_TYPES // This is used to size and count so add more prior to this } clight_type; /* typedef enum { MD_CHILLER, MD_HEATPUMP } heatmump_mode; */ typedef struct vbuttond { char *altlabel; bool in_alt_mode; // Example if altlabel="chiller", if last seen was chiller message this is true. //heatmump_mode chiller_mode; // Add any other special params for virtual button } vbutton_detail; typedef enum { NET_MQTT=0, NET_API, NET_WS, NET_DZMQTT, NET_TIMER, // Timer or Scheduler (eg poweron/freezeprotect check) UNACTION_TIMER } request_source; typedef struct clightd { clight_type lightType; aqkey *button; int currentValue; int lastValue; // Used for AqualinkD self programming aqledstate RSSDstate; // state from rs serial adapter } clight_detail; #include "aq_panel.h" struct aqualinkdata { //panel_status panelstatus; uint16_t status_mask; char version[AQ_MSGLEN*2]; // Will be replaced by below in future char revision[AQ_MSGLEN]; // Will be replaced by below in future // The below 4 are set (sometimes) but not used yet char panel_rev[AQ_MSGLEN]; // From panel char panel_cpu[AQ_MSGLEN]; // From panel char panel_string[AQ_MSGLEN]; // This is from actual PANEL not aqualinkd's config uint16_t panel_support_options; char date[AQ_MSGLEN]; char time[AQ_MSGLEN]; char last_message[AQ_MSGLONGLEN+1]; // Last ascii message from panel - allbutton (or PDA) protocol char last_display_message[AQ_MSGLONGLEN+1]; // Last message to display in web UI bool is_display_message_programming; aqled aqualinkleds[TOTAL_LEDS]; aqkey aqbuttons[TOTAL_BUTTONS]; unsigned short total_buttons; unsigned short virtual_button_start; int air_temp; int pool_temp; int spa_temp; int temp_units; //bool single_device; // Pool or Spa only, not Pool & Spa (Thermostat setpoints are different) int battery; int frz_protect_set_point; int pool_htr_set_point; int spa_htr_set_point; int swg_percent; int swg_ppm; int chiller_set_point; aqkey *chiller_button; //heatmump_mode chiller_mode; unsigned char ar_swg_device_status; // Actual state unsigned char heater_err_status; aqledstate swg_led_state; // Display state for UI's aqledstate service_mode_state; aqledstate frz_protect_state; //aqledstate chiller_state; int num_pumps; pump_detail pumps[MAX_PUMPS]; int num_lights; clight_detail lights[MAX_LIGHTS]; bool boost; char boost_msg[10]; int boost_duration; // need to remove boost message and use this int boost_linked_device; float ph; int orp; // Below this line is not state related. (Future just do a mem compare for change) //aqkey *orderedbuttons[TOTAL_BUTTONS]; // Future to reduce RS4,6,8,12,16 & spa buttons //unsigned short total_ordered_buttons; unsigned char last_packet_type; int swg_delayed_percent; //bool simulate_panel; // NSF remove in future unsigned char simulator_packet[AQ_MAXPKTLEN+1]; bool simulator_packet_updated; int simulator_packet_length; //bool simulator_active; // should be redundant with other two unsigned char simulator_id; //simulator_type simulator_active; emulation_type simulator_active; bool aqManagerActive; int open_websockets; struct programmingthread active_thread; struct action unactioned; unsigned char raw_status[AQ_PSTLEN]; // Multiple threads update this value. volatile bool updated; char self[AQ_MSGLEN*2]; int num_sensors; external_sensor sensors[MAX_SENSORS]; #ifdef AQ_MANAGER volatile bool run_slogger; int slogger_packets; bool slogger_debug; char slogger_ids[20]; #endif int rs16_vbutton_start; int rs16_vbutton_end; #ifdef AQ_PDA int pool_heater_index; int spa_heater_index; int solar_heater_index; #endif // Timing for DEBUG #ifdef AQ_DEBUG struct timespec last_active_time; struct timespec start_active_time; #endif // Overcome color light bug, by reconnecting allbutton panel. //bool reconnectAllButton; }; #endif