diff --git a/release/aqualinkd-arm64 b/release/aqualinkd-arm64 index 31eb858..13d4720 100755 Binary files a/release/aqualinkd-arm64 and b/release/aqualinkd-arm64 differ diff --git a/release/aqualinkd-armhf b/release/aqualinkd-armhf index 119d5fb..0314961 100755 Binary files a/release/aqualinkd-armhf and b/release/aqualinkd-armhf differ diff --git a/release/serial_logger-arm64 b/release/serial_logger-arm64 index 23c72f5..85cc24d 100755 Binary files a/release/serial_logger-arm64 and b/release/serial_logger-arm64 differ diff --git a/release/serial_logger-armhf b/release/serial_logger-armhf index 0a75ef2..4a63fc6 100755 Binary files a/release/serial_logger-armhf and b/release/serial_logger-armhf differ diff --git a/source/aq_panel.c b/source/aq_panel.c index 5bcb5bc..ace5b0f 100644 --- a/source/aq_panel.c +++ b/source/aq_panel.c @@ -19,6 +19,7 @@ #include #include +#include "rs_devices.h" #include "config.h" #include "aq_panel.h" #include "serialadapter.h" @@ -134,7 +135,7 @@ void checkPanelConfig(struct aqualinkdata *aqdata) { // Check panel rev for common errors. // Aqualink Touch. - if ( _aqconfig_.extended_device_id >= 0x30 && _aqconfig_.extended_device_id <= 0x33) { + if ( is_aqualink_touch_id(_aqconfig_.extended_device_id)) { if ( !isMASKSET(aqdata->panel_support_options, RSP_SUP_AQLT)) { LOG(PANL_LOG, LOG_ERR, "Panel REV %s does not support AqualinkTouch protocol, please change configuration option '%s'\n",aqdata->panel_rev, CFG_N_extended_device_id); LOG(PANL_LOG, LOG_WARNING, "Removing option '%s', please correct configuration\n",CFG_N_extended_device_id); @@ -144,7 +145,7 @@ void checkPanelConfig(struct aqualinkdata *aqdata) { } // One Touch - if ( _aqconfig_.extended_device_id >= 0x40 && _aqconfig_.extended_device_id <= 0x43) { + if ( is_onetouch_id(_aqconfig_.extended_device_id)) { if ( !isMASKSET(aqdata->panel_support_options, RSP_SUP_ONET)) { LOG(PANL_LOG, LOG_ERR, "Panel REV %s does not support OneTouch protocol, please change configuration option '%s'\n",aqdata->panel_rev, CFG_N_extended_device_id); LOG(PANL_LOG, LOG_WARNING, "Removing option '%s', please correct configuration\n",CFG_N_extended_device_id); @@ -154,7 +155,7 @@ void checkPanelConfig(struct aqualinkdata *aqdata) { } // Serial Adapter - if ( _aqconfig_.rssa_device_id >= 0x48 && _aqconfig_.rssa_device_id <= 0x49) { + if ( is_rsserialadapter_id(_aqconfig_.rssa_device_id)) { if ( !isMASKSET(aqdata->panel_support_options, RSP_SUP_RSSA)) { LOG(PANL_LOG, LOG_ERR, "Panel REV %s does not support RS SerialAdapter protocol, please change configuration option '%s'\n",aqdata->panel_rev, CFG_N_rssa_device_id); LOG(PANL_LOG, LOG_WARNING, "Removing option '%s', please correct configuration\n",CFG_N_rssa_device_id); @@ -1223,7 +1224,10 @@ bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON, req { // Check for panel programmable light. if so simple ON isn't going to work well // Could also add "light mode" check, as this is only valid for panel configured light not aqualinkd configured light. - if (isPLIGHT(button->special_mask) && button->led->state == OFF) { + if (isPLIGHT(button->special_mask) && isVBUTTON(button->special_mask)) { + programDeviceLightMode(aqdata, (isON?0:-1), deviceIndex); // -1 means off 0 means use current light mode + //aq_program(AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE, button, (isON?0:-1), 0, aqdata); // should use this in teh furuter, or get programDeviceLightMode to call it. + } else if (isPLIGHT(button->special_mask) && button->led->state == OFF) { // Full range dimmer can get stuck off on rev T.2 (maybe others), to overcome use allbutton with any % other than 0 if ( ((clight_detail *)button->special_mask_ptr)->lightType == LC_DIMMER2 || ((clight_detail *)button->special_mask_ptr)->lightType == LC_DIMMER ) // NSF should remove this once figured out Line #1354 programDeviceLightBrightness() diff --git a/source/aq_programmer.c b/source/aq_programmer.c index 91f544b..f44ea21 100644 --- a/source/aq_programmer.c +++ b/source/aq_programmer.c @@ -723,6 +723,9 @@ void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, pr int tries = 120; static int waitTime = 1; int i=0; + + // Make sure to update UI + SET_DIRTY(threadCtrl->aqdata->is_dirty); /* i = 0; while (get_aq_cmd_length() > 0 && ( i++ <= tries) ) { @@ -767,6 +770,9 @@ void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, pr threadCtrl->aqdata->active_thread.ptype, threadCtrl->aqdata->active_thread.thread_id, ptypeName(threadCtrl->aqdata->active_thread.ptype)); + + // Make sure to update UI + SET_DIRTY(threadCtrl->aqdata->is_dirty); } void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl) diff --git a/source/aq_serial.c b/source/aq_serial.c index 9ad0c46..7f22fdb 100644 --- a/source/aq_serial.c +++ b/source/aq_serial.c @@ -31,6 +31,7 @@ #include "aq_serial.h" +#include "rs_devices.h" #include "utils.h" #include "config.h" #include "packetLogger.h" @@ -53,17 +54,17 @@ emulation_type getJandyDeviceType(unsigned char ID) { // Using emulation_type from aqprogrammer. At some point may merge into one // and call device type - if (ID >= 0x08 && ID <= 0x0B) + if ( is_allbutton_id(ID) ) return ALLBUTTON; - if (ID >= 0x40 && ID <= 0x43) + if ( is_onetouch_id(ID)) return ONETOUCH; - if (ID >= 0x48 && ID <= 0x4B) + if ( is_rsserialadapter_id(ID)) return RSSADAPTER; - if (ID >= 0x60 && ID <= 0x63) + if ( is_pda_id(ID)) return AQUAPDA; - if (ID >= 0x30 && ID <= 0x33) + if (is_aqualink_touch_id(ID )) return IAQTOUCH; - if (ID >= 0xa0 && ID <= 0xa3) + if (is_iaqualink_id(ID)) return IAQUALNK; /* diff --git a/source/aq_serial.h b/source/aq_serial.h index f5985e2..eaa7c8e 100644 --- a/source/aq_serial.h +++ b/source/aq_serial.h @@ -41,22 +41,63 @@ const char *getJandyDeviceName(emulation_type etype); # Jandy pump ID's # 0x78, 0x79, 0x7A, 0x7B */ -#define PENTAIR_DEC_PUMP_MIN 96 // 0x60 -#define PENTAIR_DEC_PUMP_MAX 111 // 0x6F -#define JANDY_DEC_SWG_MIN 80 // 0x50 -#define JANDY_DEC_SWG_MAX 83 // 0x53 -#define JANDY_DEC_PUMP_MIN 120 // 0x78 -#define JANDY_DEC_PUMP_MAX 123 // 0x7b -// Have also seen epump at 0xe0 with panel rev W that supports more pumps -#define JANDY_DEC_PUMP2_MIN 224 // 0xe0 -#define JANDY_DEC_PUMP2_MAX 228 // 0xe3 // (should be 0xEF?????) Their are probably more, but this is a guess -#define JANDY_DEC_JXI_MIN 104 // 0x68 -#define JANDY_DEC_JXI_MAX 107 // 0x6B -#define JANDY_DEC_LX_MIN 56 // 0x38 -#define JANDY_DEC_LX_MAX 59 // 0x3B -#define JANDY_DEC_CHEM_MIN 128 // 0x80 -#define JANDY_DEC_CHEM_MAX 131 // 0x83 +/* +#define PENTAIR_DEV_PUMP_MIN 0x60 // 96 +#define PENTAIR_DEV_PUMP_MAX 0x6F // 111 + +#define JANDY_DEV_SWG_MIN 0x50 // 80 +#define JANDY_DEV_SWG_MAX 0x53 // 83 + +#define JANDY_DEV_PUMP_MIN 0x78 // 120 +#define JANDY_DEV_PUMP_MAX 0x7B // 123 +// Have also seen epump at 0xE0 with panel rev W that supports more pumps +#define JANDY_DEV_PUMP2_MIN 0xE0 // 224 +#define JANDY_DEV_PUMP2_MAX 0xE3 // 228 // (should be 0xEF?????) Guess + +#define JANDY_DEV_JXI_MIN 0x68 // 104 +#define JANDY_DEV_JXI_MAX 0x6B // 107 + +#define JANDY_DEV_LX_MIN 0x38 // 56 +#define JANDY_DEV_LX_MAX 0x3B // 59 + +#define JANDY_DEV_CHEM_MIN 0x80 // 128 +#define JANDY_DEV_CHEM_MAX 0x83 // 131 + +#define JANDY_DEV_IAQLN_MIN 0xA0 // 160 +#define JANDY_DEV_IAQLN_MAX 0xA3 // 163 + +#define JANDY_DEV_AQLNK_MIN 0x30 // 48 +#define JANDY_DEV_AQLNK_MAX 0x33 // 51 + +#define JANDY_DEV_HPUMP_MIN 0x70 // 112 +#define JANDY_DEV_HPUMP_MAX 0x73 // 115 + +#define JANDY_DEV_JLIGHT_MIN 0xF0 // 240 +#define JANDY_DEV_JLIGHT_MAX 0xF4 // 244 (guess) +*/ +/* Below is a guess. We *think* 0x84 and 0x86 are one TruSense, so assuming 0x85 and 0x87 would be a 2nd */ +// 0x83 is ChemLink and 0x88 is heater, so 84 to 86 are free +//#define JANDY_DEV_CHEM_ANLZ_MIN 0x84 +//#define JANDY_DEV_CHEM_ANLZ_MAX 0x87 + +/* +#define PENTAIR_DEV_PUMP_MIN 96 // 0x60 +#define PENTAIR_DEV_PUMP_MAX 111 // 0x6F +#define JANDY_DEV_SWG_MIN 80 // 0x50 +#define JANDY_DEV_SWG_MAX 83 // 0x53 +#define JANDY_DEV_PUMP_MIN 120 // 0x78 +#define JANDY_DEV_PUMP_MAX 123 // 0x7b +// Have also seen epump at 0xe0 with panel rev W that supports more pumps +#define JANDY_DEV_PUMP2_MIN 224 // 0xe0 +#define JANDY_DEV_PUMP2_MAX 228 // 0xe3 // (should be 0xEF?????) Their are probably more, but this is a guess + +#define JANDY_DEV_JXI_MIN 104 // 0x68 +#define JANDY_DEV_JXI_MAX 107 // 0x6B +#define JANDY_DEV_LX_MIN 56 // 0x38 +#define JANDY_DEV_LX_MAX 59 // 0x3B +#define JANDY_DEV_CHEM_MIN 128 // 0x80 +#define JANDY_DEV_CHEM_MAX 131 // 0x83 #define JANDY_DEV_IAQLN_MIN 0xa0 // #define JANDY_DEV_IAQLN_MAX 0xa3 // 0 @@ -70,13 +111,13 @@ const char *getJandyDeviceName(emulation_type etype); #define JANDY_DEV_JLIGHT_MIN 0xF0 #define JANDY_DEV_JLIGHT_MAX 0xF4 // 0xF4 is total guess. -//#define JANDY_DEC_CHEM_SENSOR1 0x84 // Not sure if this is a range or not. -//#define JANDY_DEC_CHEM_SENSOR2 0x86 // Not sure if this is a range or not. - +//#define JANDY_DEV_CHEM_SENSOR1 0x84 // Not sure if this is a range or not. +//#define JANDY_DEV_CHEM_SENSOR2 0x86 // Not sure if this is a range or not. +*/ /* Below is a guess. We *think* 0x84 and 0x86 are one TruSense, so assuming 0x85 and 0x87 would be a 2nd */ // 0x83 is ChemLink and 0x88 is heater, so 84 to 86 are free -#define JANDY_DEV_CHEM_ANLZ_MIN 0x84 -#define JANDY_DEV_CHEM_ANLZ_MAX 0x87 +//#define JANDY_DEV_CHEM_ANLZ_MIN 0x84 +//#define JANDY_DEV_CHEM_ANLZ_MAX 0x87 /* //===== Device ID's =====// diff --git a/source/aqualink.h b/source/aqualink.h index 58cca99..a74f097 100644 --- a/source/aqualink.h +++ b/source/aqualink.h @@ -10,6 +10,8 @@ #include "sensors.h" //#include "aq_panel.h" // Moved to later in file to overcome circular dependancy. (crappy I know) +#define PRINTF(format, ...) printf("%s:%d: " format, __FILE__, __LINE__, ##__VA_ARGS__) + #define isMASK_SET(bitmask, mask) ((bitmask & mask) == mask) #define setMASK(bitmask, mask) (bitmask |= mask) #define removeMASK(bitmask, mask) (bitmask &= ~mask) diff --git a/source/aqualinkd.c b/source/aqualinkd.c index d6a4c8a..9f531ba 100644 --- a/source/aqualinkd.c +++ b/source/aqualinkd.c @@ -29,6 +29,7 @@ #include // Need GNU_SOURCE & XOPEN defined for strptime #define AQUALINKD_C +#include "rs_devices.h" #include "mongoose.h" #include "aqualink.h" #include "utils.h" @@ -589,7 +590,7 @@ int startup(char *self, char *cfgFile) // Sanity check on Device ID's against panel type if (isRS_PANEL) { - if ( (_aqconfig_.device_id >= 0x08 && _aqconfig_.device_id <= 0x0B) || _aqconfig_.device_id == 0x00 || _aqconfig_.device_id == 0xFF) { + if ( is_allbutton_id(_aqconfig_.device_id) || _aqconfig_.device_id == 0x00 || _aqconfig_.device_id == 0xFF) { // We are good } else { LOG(AQUA_LOG,LOG_ERR, "Device ID 0x%02hhx does not match RS panel, Going to search for ID!\n", _aqconfig_.device_id); @@ -597,7 +598,7 @@ int startup(char *self, char *cfgFile) //return EXIT_FAILURE; } } else if (isPDA_PANEL) { - if ( (_aqconfig_.device_id >= 0x60 && _aqconfig_.device_id <= 0x63) || _aqconfig_.device_id == 0x33 || _aqconfig_.device_id == 0xFF) { + if ( is_pda_id(_aqconfig_.device_id) || _aqconfig_.device_id == 0x33 || _aqconfig_.device_id == 0xFF) { if ( _aqconfig_.device_id == 0x33 ) { LOG(AQUA_LOG,LOG_NOTICE, "Enabeling iAqualink protocol.\n"); _aqconfig_.enable_iaqualink = true; @@ -613,7 +614,7 @@ int startup(char *self, char *cfgFile) } if (_aqconfig_.rssa_device_id != 0x00) { - if (_aqconfig_.rssa_device_id >= 0x48 && _aqconfig_.rssa_device_id <= 0x4B /*&& _aqconfig_.rssa_device_id != 0xFF*/) { + if ( is_rsserialadapter_id(_aqconfig_.rssa_device_id) ) { // We are good } else { LOG(AQUA_LOG,LOG_ERR, "RSSA Device ID 0x%02hhx does not match RS panel, please check config!\n", _aqconfig_.rssa_device_id); @@ -623,9 +624,7 @@ int startup(char *self, char *cfgFile) if (_aqconfig_.extended_device_id != 0x00) { - if ( (_aqconfig_.extended_device_id >= 0x30 && _aqconfig_.extended_device_id <= 0x33) || - (_aqconfig_.extended_device_id >= 0x40 && _aqconfig_.extended_device_id <= 0x43) /*|| - _aqconfig_.extended_device_id != 0xFF*/ ) { + if ( is_aqualink_touch_id(_aqconfig_.extended_device_id) || is_onetouch_id(_aqconfig_.extended_device_id ) ) { // We are good } else { LOG(AQUA_LOG,LOG_ERR, "Extended Device ID 0x%02hhx does not match OneTouch or AqualinkTouch ID, please check config!\n", _aqconfig_.extended_device_id); @@ -1087,13 +1086,13 @@ void main_loop() } #endif - if (_aqconfig_.rssa_device_id >= 0x48 && _aqconfig_.rssa_device_id <= 0x49) { + if ( is_rsserialadapter_id(_aqconfig_.rssa_device_id )) { addPanelRSserialAdapterInterface(); } - if (_aqconfig_.extended_device_id >= 0x40 && _aqconfig_.extended_device_id <= 0x43) { + if ( is_onetouch_id(_aqconfig_.extended_device_id)) { addPanelOneTouchInterface(); - } else if (_aqconfig_.extended_device_id >= 0x30 && _aqconfig_.extended_device_id <= 0x33) { + } else if ( is_aqualink_touch_id(_aqconfig_.extended_device_id)) { addPanelIAQTouchInterface(); } diff --git a/source/auto_configure.c b/source/auto_configure.c index 5d7e55c..74c98f3 100644 --- a/source/auto_configure.c +++ b/source/auto_configure.c @@ -3,6 +3,7 @@ #include #include +#include "rs_devices.h" #include "aqualink.h" #include "aq_serial.h" #include "auto_configure.h" @@ -147,9 +148,23 @@ bool auto_configure(struct aqualinkdata *aqdata, unsigned char* packet, int pack PDA_ID = packet[PKT_DEST]; } + if (is_iaqualink_id(lastID) && packet[PKT_DEST] == DEV_MASTER && seen_iAqualink2 == false ) + { // Saw a iAqualink2/3 device, so can't use ID, but set to read device info. + // NSF This is not a good way to check, will probably be false positive if you are using iAqualink2 and hit restart. + _aqconfig_.extended_device_id2 = 0x00; + _aqconfig_.enable_iaqualink = false; + _aqconfig_.read_RS485_devmask |= READ_RS485_IAQUALNK; + seen_iAqualink2 = true; + LOG(AQUA_LOG,LOG_NOTICE, "Saw inuse iAqualink2/3 ID 0x%02hhx, turning off AqualinkD on that ID\n",lastID); + } + + + if (lastID != 0x00 && packet[PKT_DEST] == DEV_MASTER ) { // Can't use got a reply to the last probe. - lastID = 0x00; - } else if (lastID != 0x00 && packet[PKT_DEST] != DEV_MASTER) { + lastID = 0x00; + } + else if (lastID != 0x00 && packet[PKT_DEST] != DEV_MASTER) + { // We can use last ID. // Save the first good ID. if (firstprobe == 0x00 && lastID != 0x60) { @@ -165,26 +180,20 @@ bool auto_configure(struct aqualinkdata *aqdata, unsigned char* packet, int pack SET_DIRTY(aqdata->is_dirty); //AddAQDstatusMask(AUTOCONFIGURE_PANEL); // Not implimented yet. } - - - if ( (lastID >= 0x08 && lastID <= 0x0B) && - (_aqconfig_.device_id == 0x00 || _aqconfig_.device_id == 0xFF) ) { + if ( is_allbutton_id(lastID) && (_aqconfig_.device_id == 0x00 || _aqconfig_.device_id == 0xFF) ) { _aqconfig_.device_id = lastID; LOG(AQUA_LOG,LOG_NOTICE, "Found valid unused device ID 0x%02hhx\n",lastID); foundIDs++; - } else if ( (lastID >= 0x48 && lastID <= 0x49) && - (_aqconfig_.rssa_device_id == 0x00 || _aqconfig_.rssa_device_id == 0xFF) ) { + } else if ( is_rsserialadapter_id(lastID) && (_aqconfig_.rssa_device_id == 0x00 || _aqconfig_.rssa_device_id == 0xFF) ) { _aqconfig_.rssa_device_id = lastID; LOG(AQUA_LOG,LOG_NOTICE, "Found valid unused RSSA ID 0x%02hhx\n",lastID); foundIDs++; - } else if ( (lastID >= 0x40 && lastID <= 0x43) && - (_aqconfig_.extended_device_id == 0x00 || _aqconfig_.extended_device_id == 0xFF) ) { + } else if ( is_onetouch_id(lastID) && (_aqconfig_.extended_device_id == 0x00 || _aqconfig_.extended_device_id == 0xFF) ) { _aqconfig_.extended_device_id = lastID; _aqconfig_.extended_device_id_programming = true; // Don't increase foundIDs as we prefer not to use this one. LOG(AQUA_LOG,LOG_NOTICE, "Found valid unused extended ID 0x%02hhx\n",lastID); - } else if ( (lastID >= 0x30 && lastID <= 0x33) && - (_aqconfig_.extended_device_id < 0x30 || _aqconfig_.extended_device_id > 0x33)) { //Overide if it's been set to Touch or not set. + } else if ( is_aqualink_touch_id(lastID) && (_aqconfig_.extended_device_id < 0x30 || _aqconfig_.extended_device_id > 0x33)) { //Overide if it's been set to Touch or not set. _aqconfig_.extended_device_id = lastID; _aqconfig_.extended_device_id_programming = true; if (!seen_iAqualink2) { @@ -211,15 +220,19 @@ bool auto_configure(struct aqualinkdata *aqdata, unsigned char* packet, int pack } if ( (packet[PKT_CMD] == CMD_PROBE) && ( - (packet[PKT_DEST] >= 0x08 && packet[PKT_DEST] <= 0x0B) || + is_allbutton_id(packet[PKT_DEST]) || //(packet[PKT_DEST] >= 0x60 && packet[PKT_DEST] <= 0x63) || - (packet[PKT_DEST] >= 0x40 && packet[PKT_DEST] <= 0x43) || - (packet[PKT_DEST] >= 0x30 && packet[PKT_DEST] <= 0x33) || - (packet[PKT_DEST] >= 0x48 && packet[PKT_DEST] <= 0x49) )) + is_rsserialadapter_id(packet[PKT_DEST]) || + is_aqualink_touch_id(packet[PKT_DEST]) || + is_onetouch_id(packet[PKT_DEST]) )) { lastID = packet[PKT_DEST]; // Store the valid ID. } - else if (packet[PKT_DEST] >= 0xa0 && packet[PKT_DEST] <= 0xa3 && seen_iAqualink2 == false ) // we get a packet to iAqualink2/3 make sure to turn off, + else if (is_iaqualink_id(packet[PKT_DEST])) { + lastID = packet[PKT_DEST]; // Store the valid ID. + } + /* + else if (is_iaqualink_id(packet[PKT_DEST]) && seen_iAqualink2 == false ) // we get a packet to iAqualink2/3 make sure to turn off, { // Saw a iAqualink2/3 device, so can't use ID, but set to read device info. // NSF This is not a good way to check, will probably be false positive if you are using iAqualink2 and hit restart. _aqconfig_.extended_device_id2 = 0x00; @@ -227,7 +240,7 @@ bool auto_configure(struct aqualinkdata *aqdata, unsigned char* packet, int pack _aqconfig_.read_RS485_devmask |= READ_RS485_IAQUALNK; seen_iAqualink2 = true; LOG(AQUA_LOG,LOG_NOTICE, "Saw inuse iAqualink2/3 ID 0x%02hhx, turning off AqualinkD on that ID\n",packet[PKT_DEST]); - } + }*/ if (!done) return false; diff --git a/source/auto_configure.h b/source/auto_configure.h index 0e4796c..481ccdc 100644 --- a/source/auto_configure.h +++ b/source/auto_configure.h @@ -5,5 +5,4 @@ bool auto_configure(struct aqualinkdata *aqdata, unsigned char* packet, int packet_length, int rs_fd); - #endif //AUTO_CONFIGURE_H_ \ No newline at end of file diff --git a/source/color_lights.c b/source/color_lights.c index d74e0f7..744b085 100644 --- a/source/color_lights.c +++ b/source/color_lights.c @@ -23,14 +23,14 @@ bool isShowMode(const char *mode); char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] = //char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] = { - // AqualnkD Colors ignored as no names in control panel. + // 0 = AqualnkD Colors ignored as no names in control panel. { "Off", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18" }, - { // Jandy Color + { // 1 = Jandy Color "Off", "Alpine White", // 0x41 "Sky Blue", "Cobalt Blue", - "Caribbean Blue", + "Caribbean Blu", "Spring Green", "Emerald Green", "Emerald Rose", @@ -39,12 +39,12 @@ char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] = "Violet", "Color Splash" }, - { // Jandy LED + { // 2 = Jandy LED "Off", "Alpine White", "Sky Blue", "Cobalt Blue", - "Caribbean Blue", + "Caribbean Blu", "Spring Green", "Emerald Green", "Emerald Rose", @@ -56,7 +56,7 @@ char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] = "Fat Tuesday", "Disco Tech" }, - { // SAm/SAL + { // 3 = SAm/SAL "Off", "White", "Light Green", @@ -66,7 +66,7 @@ char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] = "Lavender", "Magenta" }, - { // Color Logic + { // 4 = Color Logic "Off", "Voodoo Lounge", // 0x41 (both home and sim) "Deep Blue Sea", // 0x42 (both gome and sim) @@ -81,7 +81,7 @@ char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] = "Mardi Gras", // 0x50 (home panel) // 0x4b (simulator) "Cool Cabaret" // 0x51 (home panel) // 0x4c }, - { // IntelliBrite + { // 5 = IntelliBrite "Off", "SAm", "Party", @@ -96,7 +96,7 @@ char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] = "White", "Magenta" }, - { // Haywood Universal Color + { // 6 = Haywood Universal Color "Off", "Voodoo Lounge", // 0x41 (both home and sim) // Looks like 28 + = 0x41 = 1st index "Deep Blue Sea", // 0x42 (both gome and sim) @@ -116,7 +116,7 @@ char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] = "Mardi Gras", // 0x50 (home panel) // 0x4b (simulator) "Cool Cabaret" // 0x51 (home panel) // 0x4c }, - {// Jandy Infinate Water Colors (RS485) + {// 7 = Jandy Infinate Water Colors (RS485) "Off", "Alpine White", "Sky Blue", @@ -134,16 +134,16 @@ char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] = "Fat Tuesday", "Disco Tech" }, - {/*Spare 2*/}, - {/*Spare 3*/}, - { // Dimmer // From manual this is 0 for off, 128+ so 153 = 25% = 0x99 + {/* 8 = Spare 2*/}, + {/* 9 = Spare 3*/}, + { // 10 = Dimmer // From manual this is 0 for off, 128+ so 153 = 25% = 0x99 "Off", "25%", // 0x99 (simulator) = 153 dec "50%", // 0xb2 (simulator) = 178 dec same as (0x99 + 25) "75%", // 0xcb (simulator) = 203 dec "100%" // 0xe4 = 228 dec }, - {/* Dimmer with full range */} + {/* 11 = Dimmer with full range */} }; // DON'T FORGET TO CHANGE #define DIMMER_LIGHT_INDEX 10 in color_lights.h @@ -251,9 +251,15 @@ const char *get_currentlight_mode_name(clight_detail light, emulation_type proto } // Rename any modes depending on emulation type if (protocol == ALLBUTTON) { + // Afternoon Skies = Afternoon Sky if (strcmp(_color_light_options[light.lightType][light.currentValue],"Afternoon Skies") == 0) { return "Afternoon Sky"; } + //Caribbean Blue = Caribbean Blu + if (strcmp(_color_light_options[light.lightType][light.currentValue],"Caribbean Blue") == 0) { + return "Caribbean Blu"; + } + } return _color_light_options[light.lightType][light.currentValue]; diff --git a/source/config.c b/source/config.c index e83ce15..0360ae0 100644 --- a/source/config.c +++ b/source/config.c @@ -42,6 +42,7 @@ #define CONFIG_C +#include "rs_devices.h" #include "config.h" #include "utils.h" #include "aq_serial.h" @@ -1321,7 +1322,7 @@ bool populatePumpData(struct aqualinkdata *aqdata, char *pumpcfg ,aqkey *button, strncpy(pump->pumpName ,cleanwhitespace(value), PUMP_NAME_LENGTH-1); } else if (strncasecmp(pumpcfg, "pumpID", 6) == 0) { pump->pumpID = strtoul(cleanalloc(value), NULL, 16); - if ( (int)pump->pumpID >= PENTAIR_DEC_PUMP_MIN && (int)pump->pumpID <= PENTAIR_DEC_PUMP_MAX) { + if ( is_pentair_pump_id(pump->pumpID) ) { pump->prclType = PENTAIR; } else { pump->prclType = JANDY; @@ -1858,10 +1859,8 @@ void check_print_config (struct aqualinkdata *aqdata) aqdata->pumps[j].pumpName[0]=='\0'?"":aqdata->pumps[j].pumpName); } } - for (j = 0; j < aqdata->num_lights; j++) { - if (aqdata->lights[j].button == &aqdata->aqbuttons[i]) { - sprintf(ext,"Light Progm %-1d |",aqdata->lights[j].lightType); - } + if (isPLIGHT(aqdata->aqbuttons[i].special_mask)) { + sprintf(ext,"Light Progm %-1d |", ((clight_detail *)aqdata->aqbuttons[i].special_mask_ptr)->lightType); } if (isVBUTTON(aqdata->aqbuttons[i].special_mask)) { if (aqdata->aqbuttons[i].rssd_code != NUL) { @@ -2061,12 +2060,12 @@ int save_config_js(const char* inBuf, int inSize, char* outBuf, int outSize, str // The above will reset all the panel profocol masks since it re-sets the panel, so set them back here. - if (_aqconfig_.rssa_device_id >= 0x48 && _aqconfig_.rssa_device_id <= 0x49) { + if (is_rsserialadapter_id(_aqconfig_.rssa_device_id)) { addPanelRSserialAdapterInterface(); } - if (_aqconfig_.extended_device_id >= 0x40 && _aqconfig_.extended_device_id <= 0x43) { + if (is_onetouch_id(_aqconfig_.extended_device_id)) { addPanelOneTouchInterface(); - } else if (_aqconfig_.extended_device_id >= 0x30 && _aqconfig_.extended_device_id <= 0x33) { + } else if ( is_aqualink_touch_id(_aqconfig_.extended_device_id)) { addPanelIAQTouchInterface(); } diff --git a/source/devices_jandy.c b/source/devices_jandy.c index 6b6f8f7..bab8173 100644 --- a/source/devices_jandy.c +++ b/source/devices_jandy.c @@ -14,9 +14,12 @@ * https://github.com/sfeakes/aqualinkd */ + #include #include +#include +#include "rs_devices.h" #include "devices_jandy.h" #include "aq_serial.h" #include "aqualink.h" @@ -134,62 +137,61 @@ bool processJandyPacket(unsigned char *packet_buffer, int packet_length, struct interestedInNextAck = DRS_NONE; previous_packet_to = NUL; } - else if (READ_RSDEV_SWG && packet_buffer[PKT_DEST] >= JANDY_DEC_SWG_MIN && packet_buffer[PKT_DEST] <= JANDY_DEC_SWG_MAX) + else if (READ_RSDEV_SWG && is_swg_id(packet_buffer[PKT_DEST])) { interestedInNextAck = DRS_SWG; printJandyDebugPacket("SWG", packet_buffer, packet_length); rtn = processPacketToSWG(packet_buffer, packet_length, aqdata/*, _aqconfig_.swg_zero_ignore*/); previous_packet_to = packet_buffer[PKT_DEST]; } - else if (READ_RSDEV_ePUMP && ( (packet_buffer[PKT_DEST] >= JANDY_DEC_PUMP_MIN && packet_buffer[PKT_DEST] <= JANDY_DEC_PUMP_MAX) - || (packet_buffer[PKT_DEST] >= JANDY_DEC_PUMP2_MIN && packet_buffer[PKT_DEST] <= JANDY_DEC_PUMP2_MAX) ) ) + else if (READ_RSDEV_ePUMP && is_jandy_pump_id(packet_buffer[PKT_DEST])) { interestedInNextAck = DRS_EPUMP; printJandyDebugPacket("EPump", packet_buffer, packet_length); rtn = processPacketToJandyPump(packet_buffer, packet_length, aqdata); previous_packet_to = packet_buffer[PKT_DEST]; } - else if (READ_RSDEV_JXI && packet_buffer[PKT_DEST] >= JANDY_DEC_JXI_MIN && packet_buffer[PKT_DEST] <= JANDY_DEC_JXI_MAX) + else if (READ_RSDEV_JXI && is_jxi_heater_id(packet_buffer[PKT_DEST])) { interestedInNextAck = DRS_JXI; printJandyDebugPacket("JXi", packet_buffer, packet_length); rtn = processPacketToJandyJXiHeater(packet_buffer, packet_length, aqdata); previous_packet_to = packet_buffer[PKT_DEST]; } - else if (READ_RSDEV_LX && packet_buffer[PKT_DEST] >= JANDY_DEC_LX_MIN && packet_buffer[PKT_DEST] <= JANDY_DEC_LX_MAX) + else if (READ_RSDEV_LX && is_lx_heater_id(packet_buffer[PKT_DEST])) { interestedInNextAck = DRS_LX; printJandyDebugPacket("LX", packet_buffer, packet_length); rtn = processPacketToJandyLXHeater(packet_buffer, packet_length, aqdata); previous_packet_to = packet_buffer[PKT_DEST]; } - else if (READ_RSDEV_CHEM_FEDR && packet_buffer[PKT_DEST] >= JANDY_DEC_CHEM_MIN && packet_buffer[PKT_DEST] <= JANDY_DEC_CHEM_MAX) + else if (READ_RSDEV_CHEM_FEDR && is_chem_feeder_id(packet_buffer[PKT_DEST] )) { interestedInNextAck = DRS_CHEM_FEED; printJandyDebugPacket("ChemL", packet_buffer, packet_length); rtn = processPacketToJandyChemFeeder(packet_buffer, packet_length, aqdata); previous_packet_to = packet_buffer[PKT_DEST]; } - else if (READ_RSDEV_CHEM_ANLZ && packet_buffer[PKT_DEST] == JANDY_DEV_CHEM_ANLZ_MIN && packet_buffer[PKT_DEST] == JANDY_DEV_CHEM_ANLZ_MAX) + else if (READ_RSDEV_CHEM_ANLZ && is_chem_anlzer_id(packet_buffer[PKT_DEST])) { interestedInNextAck = DRS_CHEM_ANLZ; printJandyDebugPacket("CemSnr", packet_buffer, packet_length); rtn = processPacketToJandyChemAnalyzer(packet_buffer, packet_length, aqdata); previous_packet_to = packet_buffer[PKT_DEST]; } - else if (READ_RSDEV_iAQLNK && packet_buffer[PKT_DEST] >= JANDY_DEV_AQLNK_MIN && packet_buffer[PKT_DEST] <= JANDY_DEV_AQLNK_MAX + else if (READ_RSDEV_iAQLNK && is_aqualink_touch_id(packet_buffer[PKT_DEST]) // should we add is_iaqualink_id() as well???? && packet_buffer[PKT_DEST] != _aqconfig_.extended_device_id) // We would have already read extended_device_id frame { process_iAqualinkStatusPacket(packet_buffer, packet_length, aqdata); } - else if (READ_RSDEV_HPUMP && packet_buffer[PKT_DEST] >= JANDY_DEV_HPUMP_MIN && packet_buffer[PKT_DEST] <= JANDY_DEV_HPUMP_MAX) + else if (READ_RSDEV_HPUMP && is_heat_pump_id(packet_buffer[PKT_DEST] )) { interestedInNextAck = DRS_HEATPUMP; printJandyDebugPacket("HPump", packet_buffer, packet_length); rtn = processPacketToHeatPump(packet_buffer, packet_length, aqdata); previous_packet_to = packet_buffer[PKT_DEST]; } - else if (READ_RSDEV_JLIGHT && packet_buffer[PKT_DEST] >= JANDY_DEV_JLIGHT_MIN && packet_buffer[PKT_DEST] <= JANDY_DEV_JLIGHT_MAX) + else if (READ_RSDEV_JLIGHT && is_jandy_light_id(packet_buffer[PKT_DEST])) { interestedInNextAck = DRS_JLIGHT; printJandyDebugPacket("JLight", packet_buffer, packet_length); diff --git a/source/devices_pentair.c b/source/devices_pentair.c index 64ba768..3ff496b 100644 --- a/source/devices_pentair.c +++ b/source/devices_pentair.c @@ -21,6 +21,7 @@ #include #include "aqualink.h" +#include "rs_devices.h" #include "aq_serial.h" #include "devices_pentair.h" #include "utils.h" @@ -45,7 +46,7 @@ bool processPentairPacket(unsigned char *packet, int packet_length, struct aqual //static int pumpIndex = 1; // Status from pump - if ( packet[PEN_PKT_CMD] == PEN_CMD_STATUS && packet[PEN_PKT_FROM] >= PENTAIR_DEC_PUMP_MIN && packet[PEN_PKT_FROM] <= PENTAIR_DEC_PUMP_MAX ){ + if ( packet[PEN_PKT_CMD] == PEN_CMD_STATUS && is_pentair_pump_id(packet[PEN_PKT_FROM] ) ){ // We have Pentair Pump packet, let's see if it's configured. //printf("PUMP\n"); @@ -97,7 +98,7 @@ bool processPentairPacket(unsigned char *packet, int packet_length, struct aqual // } // Set RPM/GPM to pump - else if (packet[PEN_PKT_CMD] == PEN_CMD_SPEED && packet[PEN_PKT_DEST] >= PENTAIR_DEC_PUMP_MIN && packet[PEN_PKT_DEST] <= PENTAIR_DEC_PUMP_MAX) { + else if (packet[PEN_PKT_CMD] == PEN_CMD_SPEED && packet[PEN_PKT_DEST] >= PENTAIR_DEV_PUMP_MIN && packet[PEN_PKT_DEST] <= PENTAIR_DEV_PUMP_MAX) { //(msg.extractPayloadByte(2) & 32) >> 5 === 0 ? 'RPM' : 'GPM'; @@ -110,7 +111,7 @@ bool processPentairPacket(unsigned char *packet, int packet_length, struct aqual } } // Set power to pump - else if (packet[PEN_PKT_CMD] == PEN_CMD_POWER && packet[PEN_PKT_DEST] >= PENTAIR_DEC_PUMP_MIN && packet[PEN_PKT_DEST] <= PENTAIR_DEC_PUMP_MAX) { + else if (packet[PEN_PKT_CMD] == PEN_CMD_POWER && packet[PEN_PKT_DEST] >= PENTAIR_DEV_PUMP_MIN && packet[PEN_PKT_DEST] <= PENTAIR_DEV_PUMP_MAX) { if (packet[9] == 0x0A) { LOG(DPEN_LOG, LOG_INFO,"Pentair Pump 0x%02hhx request set power ON\n",packet[PEN_PKT_DEST]); } else { diff --git a/source/iaqtouch.c b/source/iaqtouch.c index ea251e7..c69494e 100644 --- a/source/iaqtouch.c +++ b/source/iaqtouch.c @@ -187,9 +187,13 @@ struct iaqt_page_button *iaqtFindButtonByLabel(const char *label) { for (i=0; i < IAQ_PAGE_BUTTONS; i++) { //if (_pageButtons[i].state != 0 || _pageButtons[i].type != 0 || _pageButtons[i].unknownByte != 0) - if (rsm_strcmp((char *)buttons[i].name,label) == 0) + if (rsm_strcmp((char *)buttons[i].name,label) == 0) { + LOG(IAQT_LOG, LOG_DEBUG, "Found button '%s'\n",label); return &buttons[i]; + } } + + LOG(IAQT_LOG, LOG_DEBUG, "Did not find button '%s'\n",label); return NULL; } @@ -958,7 +962,8 @@ bool process_iaqtouch_packet(unsigned char *packet, int length, struct aqualinkd // NEED to rethink this approach. ie, selecting light needs to hold open while showing page, no page end, then select light color, then message "please wait", the finally done } } - } else if (isPDA_PANEL && packet[PKT_CMD] == CMD_IAQ_MSG_LONG) { + //} else if (isPDA_PANEL && packet[PKT_CMD] == CMD_IAQ_MSG_LONG) { // might want to add isPDA or JandyInfinateLight + } else if (packet[PKT_CMD] == CMD_IAQ_MSG_LONG) { char *sp; // Set disply message if PDA panel memset(message, 0, AQ_MSGLONGLEN + 1); diff --git a/source/iaqtouch_aq_programmer.c b/source/iaqtouch_aq_programmer.c index b743399..5d624e3 100644 --- a/source/iaqtouch_aq_programmer.c +++ b/source/iaqtouch_aq_programmer.c @@ -615,19 +615,32 @@ void *set_aqualink_iaqtouch_light_colormode( void *ptr ) int typ = atoi(&buf[10]); bool use_current_mode = false; bool turn_off = false; + aqkey *key = NULL; waitForSingleThreadOrTerminate(threadCtrl, AQ_SET_IAQTOUCH_LIGHTCOLOR_MODE); //char *buf = (char*)threadCtrl->thread_args; - - if (btn < 0 || btn >= aqdata->total_buttons ) { - LOG(IAQT_LOG, LOG_ERR, "Can't program light mode on button %d\n", btn); - cleanAndTerminateThread(threadCtrl); - return ptr; + struct programmerArgs *pargs = &threadCtrl->pArgs; + if (pargs->button != NULL) { + key = threadCtrl->pArgs.button; + val = pargs->value; + if (isPLIGHT(key->special_mask)) { + typ = ((clight_detail *)key->special_mask_ptr)->lightType; + } else { + LOG(IAQT_LOG, LOG_ERR, "Can't can't get light type for button %s\n", key->label); + cleanAndTerminateThread(threadCtrl); + return ptr; + } + } else { + if (btn < 0 || btn >= aqdata->total_buttons ) { + LOG(IAQT_LOG, LOG_ERR, "Can't program light mode on button %d\n", btn); + cleanAndTerminateThread(threadCtrl); + return ptr; + } + key = &aqdata->aqbuttons[btn]; } - aqkey *key = &aqdata->aqbuttons[btn]; //unsigned char code = key->code; // We also need to cater for light being ON AND changing the color mode. we have extra OK to hit. @@ -635,11 +648,11 @@ void *set_aqualink_iaqtouch_light_colormode( void *ptr ) use_current_mode = true; LOG(IAQT_LOG, LOG_INFO, "Light Programming #: %d, button: %s, color light type: %d, using current mode\n", val, key->label, typ); // NOT SURE WHAT TO DO HERE..... No color mode and iaatouch doesn;t support last color in PDA mode. - } else if (val == -1) { + } else if (val == -1) { turn_off = true; LOG(IAQT_LOG, LOG_INFO, "Light Programming #: %d, button: %s, color light type: %d, Turning off\n", val, key->label, typ); - } else { - mode_name = light_mode_name(typ, val-1, IAQTOUCH); + } else { + mode_name = light_mode_name(typ, val, IAQTOUCH); use_current_mode = false; if (mode_name == NULL) { LOG(IAQT_LOG, LOG_ERR, "Light Programming #: %d, button: %s, color light type: %d, couldn't find mode name '%s'\n", val, key->label, typ, mode_name); @@ -650,9 +663,12 @@ void *set_aqualink_iaqtouch_light_colormode( void *ptr ) } } + // See if it's on the current page button = iaqtFindButtonByLabel(key->label); - + +PRINTF("First button find = %s\n",button==NULL?"null":button->name); + if (button == NULL) { // No luck, go to the device page if ( goto_iaqt_page(IAQ_PAGE_DEVICES, aqdata) == false ) @@ -660,12 +676,14 @@ void *set_aqualink_iaqtouch_light_colormode( void *ptr ) button = iaqtFindButtonByLabel(key->label); +PRINTF("Second button find = %s\n",button==NULL?"null":button->name); // If not found see if page has next if (button == NULL && iaqtFindButtonByIndex(16)->type == 0x03 ) { iaqt_queue_cmd(KEY_IAQTCH_NEXT_PAGE); waitfor_iaqt_nextPage(aqdata); // This will fail, since not looking at device page 2 buttons button = iaqtFindButtonByLabel(key->label); +PRINTF("Third button find = %s\n",button==NULL?"null":button->name); } } @@ -673,7 +691,9 @@ void *set_aqualink_iaqtouch_light_colormode( void *ptr ) LOG(IAQT_LOG, LOG_ERR, "IAQ Touch did not find '%s' button on device list\n", key->label); goto f_end; } +PRINTF("FOUND button = %s\n",button==NULL?"null":button->name); // WE have a iaqualink button, press it. + LOG(IAQT_LOG, LOG_DEBUG, "IAQ Touch found '%s' sending keycode '0x%02hhx'\n", key->label, button->keycode); send_aqt_cmd(button->keycode); // See if we want to use the last color, or turn it off @@ -681,6 +701,7 @@ void *set_aqualink_iaqtouch_light_colormode( void *ptr ) // After pressing the button, Just need to wait for 5 seconds and it will :- // a) if off turn on and default to last color. // b) if on, turn off. (pain that we need to wait 5 seconds.) +PRINTF("******** WAIT for next message\n"); waitfor_iaqt_queue2empty(); waitfor_iaqt_nextPage(aqdata); if (use_current_mode) { @@ -707,19 +728,29 @@ void *set_aqualink_iaqtouch_light_colormode( void *ptr ) goto f_end; } + // Now find the light mode and press it. button = iaqtFindButtonByLabel(mode_name); if (button == NULL) { LOG(IAQT_LOG, LOG_ERR, "IAQ Touch did find color '%s' in color light page\n",mode_name); goto f_end; } + + LOG(IAQT_LOG, LOG_DEBUG, "IAQ Touch found '%s' sending keycode '0x%02hhx'\n", mode_name, button->keycode); + send_aqt_cmd(button->keycode); + waitfor_iaqt_queue2empty(); + // Wait for popup message to disapera + unsigned char page; + while ( (page = waitfor_iaqt_nextPage(aqdata)) != NUL) { + PRINTF("******** next page is '0x%02hhx'\n",page); + } //LOG(IAQT_LOG, LOG_ERR, "IAQ Touch WAIYING FOR 1 MESSAGES\n"); //waitfor_iaqt_messages(aqdata, 1); // Finally found the color. select it - send_aqt_cmd(button->keycode); - waitfor_iaqt_nextPage(aqdata); + //send_aqt_cmd(button->keycode); + //waitfor_iaqt_nextPage(aqdata); f_end: goto_iaqt_page(IAQ_PAGE_HOME, aqdata); diff --git a/source/net_services.c b/source/net_services.c index 0a5e982..12c9de3 100644 --- a/source/net_services.c +++ b/source/net_services.c @@ -1376,11 +1376,11 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float //aqualinkd/CHEM/pH/set //aqualinkd/CHEM/ORP/set if ( strncasecmp(ri2, "ORP", 3) == 0 ) { - _aqualink_data->orp = round(value); + SET_IF_CHANGED(_aqualink_data->orp, round(value), _aqualink_data->is_dirty); rtn = uActioned; LOG(NET_LOG,LOG_NOTICE, "%s: request to set ORP to %d\n",actionName[from],_aqualink_data->orp); } else if ( strncasecmp(ri2, "Ph", 2) == 0 ) { - _aqualink_data->ph = value; + SET_IF_CHANGED(_aqualink_data->ph, value, _aqualink_data->is_dirty); rtn = uActioned; LOG(NET_LOG,LOG_NOTICE, "%s: request to set Ph to %.2f\n",actionName[from],_aqualink_data->ph); } else { diff --git a/source/rs_devices.h b/source/rs_devices.h new file mode 100644 index 0000000..6bbca5c --- /dev/null +++ b/source/rs_devices.h @@ -0,0 +1,95 @@ + +#ifndef RS_DEVICES_H_ +#define RS_DEVICES_H_ + +#include + +#define ALLBUTTON_MIN 0x08 +#define ALLBUTTON_MAX 0x0B + +#define RS_SERIAL_ADAPTER_MIN 0x48 +#define RS_SERIAL_ADAPTER_MAX 0x49 + +#define ONETOUCH_MIN 0x40 +#define ONETOUCH_MAX 0x43 + +#define AQUALINKTOUCH_MIN 0x30 +#define AQUALINKTOUCH_MAX 0x33 + +#define IAQUALINK_MIN 0xA0 +#define IAQUALINK_MAX 0xA3 + +#define SPA_REMOTE_MIN 0x20 +#define SPA_REMOTE_MAX 0x23 + +#define REMOTE_PWR_CENT_MIN 0x28 +#define REMOTE_PWR_CENT_MAX 0x2B + +#define PC_DOCK_MIN 0x58 +#define PC_DOCK_MAX 0x5B + +#define PDA_MIN 0x60 +#define PDA_MAX 0x63 + +#define JANDY_DEV_SWG_MIN 0x50 +#define JANDY_DEV_SWG_MAX 0x53 + +#define JANDY_DEV_PUMP_MIN 0x78 +#define JANDY_DEV_PUMP_MAX 0x7B + +#define JANDY_DEV_PUMP2_MIN 0xE0 +#define JANDY_DEV_PUMP2_MAX 0xE3 + +#define JANDY_DEV_JXI_MIN 0x68 +#define JANDY_DEV_JXI_MAX 0x6B + +#define JANDY_DEV_LX_MIN 0x38 +#define JANDY_DEV_LX_MAX 0x3B + +#define JANDY_DEV_CHEM_MIN 0x80 +#define JANDY_DEV_CHEM_MAX 0x83 + +#define JANDY_DEV_HPUMP_MIN 0x70 +#define JANDY_DEV_HPUMP_MAX 0x73 + +#define JANDY_DEV_JLIGHT_MIN 0xF0 +#define JANDY_DEV_JLIGHT_MAX 0xF4 + +#define JANDY_DEV_CHEM_ANLZ_MIN 0x84 +#define JANDY_DEV_CHEM_ANLZ_MAX 0x87 + +#define PENTAIR_DEV_PUMP_MIN 0x60 +#define PENTAIR_DEV_PUMP_MAX 0x6F + + +// Helper macro for range checks +#define BETWEEN_UCHAR(val, min, max) ((unsigned char)(val) >= (unsigned char)(min) && (unsigned char)(val) <= (unsigned char)(max)) + + +// --- Inline ID checkers --- +static inline bool is_allbutton_id(unsigned char val) { return BETWEEN_UCHAR(val, ALLBUTTON_MIN, ALLBUTTON_MAX); } +static inline bool is_rsserialadapter_id(unsigned char val) { return BETWEEN_UCHAR(val, RS_SERIAL_ADAPTER_MIN, RS_SERIAL_ADAPTER_MAX); } +static inline bool is_onetouch_id(unsigned char val) { return BETWEEN_UCHAR(val, ONETOUCH_MIN, ONETOUCH_MAX); } +static inline bool is_aqualink_touch_id(unsigned char val) { return BETWEEN_UCHAR(val, AQUALINKTOUCH_MIN, AQUALINKTOUCH_MAX); } +static inline bool is_iaqualink_id(unsigned char val) { return BETWEEN_UCHAR(val, IAQUALINK_MIN, IAQUALINK_MAX); } +static inline bool is_spa_remote_id(unsigned char val) { return BETWEEN_UCHAR(val, SPA_REMOTE_MIN, SPA_REMOTE_MAX); } +static inline bool is_remote_powercenter_id(unsigned char val){ return BETWEEN_UCHAR(val, REMOTE_PWR_CENT_MIN, REMOTE_PWR_CENT_MAX); } +static inline bool is_pc_dock_id(unsigned char val) { return BETWEEN_UCHAR(val, PC_DOCK_MIN, PC_DOCK_MAX); } +static inline bool is_pda_id(unsigned char val) { return BETWEEN_UCHAR(val, PDA_MIN, PDA_MAX); } + +static inline bool is_swg_id(unsigned char val) { return BETWEEN_UCHAR(val, JANDY_DEV_SWG_MIN, JANDY_DEV_SWG_MAX); } +static inline bool is_jxi_heater_id(unsigned char val) { return BETWEEN_UCHAR(val, JANDY_DEV_JXI_MIN, JANDY_DEV_JXI_MAX); } +static inline bool is_lx_heater_id(unsigned char val) { return BETWEEN_UCHAR(val, JANDY_DEV_LX_MIN, JANDY_DEV_LX_MAX); } +static inline bool is_chem_feeder_id(unsigned char val) { return BETWEEN_UCHAR(val, JANDY_DEV_CHEM_MIN, JANDY_DEV_CHEM_MAX); } +static inline bool is_chem_anlzer_id(unsigned char val) { return BETWEEN_UCHAR(val, JANDY_DEV_CHEM_ANLZ_MIN, JANDY_DEV_CHEM_ANLZ_MAX); } +static inline bool is_heat_pump_id(unsigned char val) { return BETWEEN_UCHAR(val, JANDY_DEV_HPUMP_MIN, JANDY_DEV_HPUMP_MAX); } +static inline bool is_jandy_light_id(unsigned char val) { return BETWEEN_UCHAR(val, JANDY_DEV_JLIGHT_MIN, JANDY_DEV_JLIGHT_MAX); } + +static inline bool is_jandy_pump_std_id(unsigned char val) { return BETWEEN_UCHAR(val, JANDY_DEV_PUMP_MIN, JANDY_DEV_PUMP_MAX); } +static inline bool is_jandy_pump_new_id(unsigned char val) { return BETWEEN_UCHAR(val, JANDY_DEV_PUMP2_MIN, JANDY_DEV_PUMP2_MAX); } +static inline bool is_jandy_pump_id(unsigned char val) {return is_jandy_pump_std_id(val) || is_jandy_pump_new_id(val);} + +static inline bool is_pentair_pump_id(unsigned char val) { return BETWEEN_UCHAR(val, PENTAIR_DEV_PUMP_MIN, PENTAIR_DEV_PUMP_MAX); } + + +#endif // RS_DEVICES_H_ \ No newline at end of file diff --git a/source/serial_logger.c b/source/serial_logger.c index 63a9a6d..1215deb 100644 --- a/source/serial_logger.c +++ b/source/serial_logger.c @@ -26,6 +26,7 @@ #include #include +#include "rs_devices.h" #include "serial_logger.h" #include "aq_serial.h" #include "utils.h" @@ -161,6 +162,7 @@ int serial_logger (int rs_fd, char *port_name, int logLevel, int slogger_packets #define EPUMP " <-- Jandy VSP ePump" #define EPUMP2 " <-- Jandy VSP (rev W or newer)" #define CHEM " <-- Chemlink" +#define CHEM_ANLZ " <-- TruSense" #define JXI_HEATER " <-- JXi / LRZ Heater" #define IAQLNK2 " <-- iAqualink 2.0" @@ -181,6 +183,72 @@ int serial_logger (int rs_fd, char *port_name, int logLevel, int slogger_packets // 0xE0 -> this is pump ID on rev W panel (16 pumps available total) - so maybe last is 0xF0 or 0xEF +const char *getDevice(unsigned char ID) +{ + if (ID >= 0x00 && ID <= 0x03) + return MASTER; + + if (is_allbutton_id(ID)) + return KEYPAD; + + if (is_swg_id(ID)) + return SWG; + + if (is_spa_remote_id(ID)) + return SPA_R; + + if (is_aqualink_touch_id(ID)) + return AQUA; + + if (is_onetouch_id(ID)) + return ONE_T; + + if (is_rsserialadapter_id(ID)) + return RS_SERL; + + if (is_pc_dock_id(ID)) + return PC_DOCK; + + if (is_pda_id(ID)) + return PDA; + + if (is_lx_heater_id(ID)) + return LX_HEATER; + + if (is_jxi_heater_id(ID)) + return JXI_HEATER; + + if (is_heat_pump_id(ID)) + return HEAT_PUMP; + + if (is_jandy_pump_id(ID)) + return EPUMP; + + if (is_chem_feeder_id(ID)) + return CHEM; + + if (is_chem_anlzer_id(ID)) + return CHEM_ANLZ; + + if (is_iaqualink_id(ID)) + return IAQLNK2; + + if (is_remote_powercenter_id(ID)) + return REM_PWR_CENT; + + if (is_jandy_pump_std_id(ID)) + return EPUMP; + + if (is_jandy_pump_new_id(ID)) + return EPUMP2; + + if (is_jandy_light_id(ID)) + return JWC_LIGHTS; + + return UNKNOWN; +} + +/* const char *getDevice(unsigned char ID) { if (ID >= 0x00 && ID <= 0x03) return MASTER; @@ -241,6 +309,8 @@ const char *getDevice(unsigned char ID) { return UNKNOWN; } +*/ + const char *getPentairDevice(unsigned char ID) { if (ID >= 0x60 && ID <= 0x6F) @@ -715,7 +785,8 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo bool found_vsp =false; bool found_jxi =false; bool found_lx =false; - bool found_chem =false; + bool found_chemlink =false; + bool found_trusense =false; bool found_pent_vsp =false; bool found_iAqualnk =false; @@ -935,17 +1006,19 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo } if (slog[i].inuse == true) { - if (slog[i].ID >= JANDY_DEC_SWG_MIN && slog[i].ID <= JANDY_DEC_SWG_MAX) { + if ( is_swg_id(slog[i].ID)) { found_swg =true; - } else if (slog[i].ID >= JANDY_DEC_PUMP_MIN && slog[i].ID <= JANDY_DEC_PUMP_MAX) { + } else if ( is_jandy_pump_id(slog[i].ID )) { found_vsp =true; - } else if (slog[i].ID >= JANDY_DEC_JXI_MIN && slog[i].ID <= JANDY_DEC_JXI_MAX) { + } else if ( is_jxi_heater_id(slog[i].ID)) { found_jxi =true; - } else if (slog[i].ID >= JANDY_DEC_LX_MIN && slog[i].ID <= JANDY_DEC_LX_MAX) { + } else if ( is_lx_heater_id(slog[i].ID)) { found_lx =true; - } else if (slog[i].ID >= JANDY_DEC_CHEM_MIN && slog[i].ID <= JANDY_DEC_CHEM_MAX) { - found_chem =true; - } else if (slog[i].ID >= JANDY_DEV_AQLNK_MIN && slog[i].ID <= JANDY_DEV_AQLNK_MAX) { + } else if ( is_chem_feeder_id(slog[i].ID )) { + found_chemlink =true; + } else if ( is_chem_anlzer_id(slog[i].ID )) { + found_trusense =true; + } else if ( is_iaqualink_id(slog[i].ID )) { found_iAqualnk =true; } } @@ -960,7 +1033,7 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo (pent_slog[i].inuse == false)?canUseExtended(pent_slog[i].ID):getPentairDevice(pent_slog[i].ID)); if (pent_slog[i].inuse == true) { - if (pent_slog[i].ID >= PENTAIR_DEC_PUMP_MIN && pent_slog[i].ID <= PENTAIR_DEC_PUMP_MAX) { + if (is_pentair_pump_id(pent_slog[i].ID)) { found_pent_vsp=true; } } @@ -1027,11 +1100,13 @@ int _serial_logger(int rs_fd, char *port_name, int logPackets, int logLevel, boo LOG(SLOG_LOG, LOG_NOTICE, "read_RS485_JXi = yes\n"); if (found_lx) LOG(SLOG_LOG, LOG_NOTICE, "read_RS485_LX = yes\n"); - if (found_chem) - LOG(SLOG_LOG, LOG_NOTICE, "read_RS485_Chem = yes\n"); + if (found_chemlink) + LOG(SLOG_LOG, LOG_NOTICE, "read_RS485_ChemLink = yes\n"); + if (found_trusense) + LOG(SLOG_LOG, LOG_NOTICE, "read_RS485_TruSense = yes\n"); if (found_iAqualnk) LOG(SLOG_LOG, LOG_NOTICE, "read_RS485_iAqualink = yes\n"); - else if (!found_iAqualnk && (extID >= JANDY_DEV_AQLNK_MIN && extID <= JANDY_DEV_AQLNK_MAX)) + else if (!found_iAqualnk && (is_aqualink_touch_id(extID))) LOG(SLOG_LOG, LOG_NOTICE, "enable_iaqualink = yes\n"); LOG(SLOG_LOG, LOG_NOTICE, "-------------------------\n"); diff --git a/web/controller.html b/web/controller.html index 4aaefe8..0c39106 100644 --- a/web/controller.html +++ b/web/controller.html @@ -52,8 +52,9 @@ --tile_status_text: rgb(87, 87, 87); --value_tile_normal_color: rgb(4, 159, 248); - --value_tile_attention_color: rgb(255, 187, 0); - --value_tile_outofrange_color: rgb(255, 123, 0); + /*--value_tile_attention_color: rgb(255, 187, 0);*/ + --value_tile_attention_color: rgb(255, 160, 0); + --value_tile_outofrange_color: rgb(255, 100, 0); --options_radio_ball: 20px; --options_radio_highlight: #2196F3; @@ -711,7 +712,7 @@ //console.log("The code is not running inside an iframe."); } - console.log("Tile width "+window.getComputedStyle(document.documentElement).getPropertyValue('--tile-width')); + //console.log("Tile width "+window.getComputedStyle(document.documentElement).getPropertyValue('--tile-width')); } function populateLightProgram(type=0, current_mode="") { @@ -2808,8 +2809,10 @@ socket_di.onopen = function() { // success! get_devices(); - // Set another load 1 minute from now just incase the server hasn't got all the devices yet - window.setTimeout(get_devices, (60 * 1000)); + // Set recurring fetch every 1 minute + if (!window.devicesInterval) { + window.devicesInterval = setInterval(() => {get_devices();}, 60 * 1000); + } // Get Status just incase control panel hasn't connected yet get_status(); } @@ -2821,8 +2824,6 @@ } else if (data.type == 'devices') { check_devices(data); resetBackgroundSize(); - //window.setTimeout(get_devices, (300 * 1000)); // Check for new dvices ever 5 mins. - window.setTimeout(get_devices, (60 * 1000)); // Check for new dvices ever 1 mins. } else if (data.type == 'schedules') { cs_schedules(data); }