diff --git a/README.md b/README.md index 1bac5a8..016697d 100644 --- a/README.md +++ b/README.md @@ -132,16 +132,20 @@ NEED TO FIX FOR THIS RELEASE. # pickup speed faster on iaqualinktouch after change --> -# Updates in 2.4.1 (under development) +# Updates in 2.5.0 (under development) * PDA panel Rev 6.0 or newer that do not have a Jandy iAqualink device attached can use the AqualinkTouch protocol rather than PDA protocol. * This is faster, more reliable and does not intefear with the physical PDA device (like existing implimentation) * Please consider this very much BETA at the moment. - * use `device_id=0x33` in aqualinkd.conf + * use `device_id=0x33` in aqualinkd.conf. +* PDA panel Rev 6.0 of newer WITH a Jandy iAqualink device attached can use `read_RS485_iAqualink = yes` to speed up device state change detection. * Added MQTT vsp_pump/speed/set for setting speed (RPM/GPM) by %, for automation hubs. +* Added full dimmer range support for dimmable lights (not limited to 0,25,50,75,100 anymore) +* Added vsp and dimmer to hassio and homebridge-aqualinkd plugin as full range dimmer controls. +* Updated UI for support fullrange dimmer. * cleaned up code for spa_mode and spa for newer pannels. * Allow VSP to be asigned to virtual button. * Fixed bug with timer not starting. -* Increase Speed of detecting device state changes. +* Increase Speed of detecting device state changes. # Updates in Release 2.4.0 * WARNING Breaking change if you use dimmer (please change button_??_lightMode from 6 to 10) diff --git a/release/aqualinkd-amd64 b/release/aqualinkd-amd64 index d6706e8..b69341a 100755 Binary files a/release/aqualinkd-amd64 and b/release/aqualinkd-amd64 differ diff --git a/release/aqualinkd-arm64 b/release/aqualinkd-arm64 index 15a3032..4658aa6 100755 Binary files a/release/aqualinkd-arm64 and b/release/aqualinkd-arm64 differ diff --git a/release/aqualinkd-armhf b/release/aqualinkd-armhf index db2029e..63d629c 100755 Binary files a/release/aqualinkd-armhf and b/release/aqualinkd-armhf differ diff --git a/release/aqualinkd.conf b/release/aqualinkd.conf index da44eb5..f3ce9bd 100755 --- a/release/aqualinkd.conf +++ b/release/aqualinkd.conf @@ -91,12 +91,14 @@ device_id=0x00 # JXi = Jandy JXi heater (might also be LXi heaters) # LX = Jandy LX & LT heaters # Chem = Jandy Chemical Feeder +# iAqualink = Read iAqualink2 (wifi device). Only relivent in PDA mode IF you have iAqualink2/3 device #read_RS485_swg = yes #read_RS485_ePump = yes #read_RS485_vsfPump = yes #read_RS485_JXi = yes #read_RS485_LX = yes #read_RS485_Chem = yes +#read_RS485_iAqualink = yes # Keep the panel time synced with systemtime. Make sure to set systemtime / NTP correctly. keep_paneltime_synced = yes @@ -146,7 +148,7 @@ report_zero_spa_temp = yes # dead. # ~40 and we will be replying too slowley, so keep below that. # 10~20 is about what most device reply in. But 0-4 works well. -rs485_frame_delay = 4 +rs485_frame_delay = 0 # Get rid of the startup warning message about no low latency. BETTER option is to buy a better adapter. #ftdi_low_latency = no @@ -264,8 +266,8 @@ use_panel_aux_labels=no # button_01_pumpIndex=1 # If you have assigned this pump an index number in your Aqualink control panel, (Between 1 & 4), put it here for VSP, RPM, Primp information to be captured. # -# button_xx_lightMode = (0=Aqualink program, 1=Jandy, 2=Jandy LED, 3=SAm/SAL, 4=Color Logic, 5=Intellibrite, 6=Hayw Univ Color, 7,8,9(future), 10=Dimmer) -# +# button_xx_lightMode = (0=Aqualink program, 1=Jandy, 2=Jandy LED, 3=SAm/SAL, 4=Color Logic, 5=Intellibrite, 6=Hayw Univ Color, 7,8,9(future), 10=Dimmer, 11=Full Range Dimmer) +# # Below are settings for standard buttons on RS-8 Combo panel used as example. button_01_label=Filter Pump diff --git a/release/serial_logger-arm64 b/release/serial_logger-arm64 index f14ab58..70b76f6 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 da04486..48d77f6 100755 Binary files a/release/serial_logger-armhf and b/release/serial_logger-armhf differ diff --git a/source/aq_mqtt.h b/source/aq_mqtt.h index b693634..a045f53 100644 --- a/source/aq_mqtt.h +++ b/source/aq_mqtt.h @@ -56,6 +56,8 @@ #define PUMP_SPEED_TOPIC "/Speed" #define LIGHT_PROGRAM_TOPIC "/program" +#define LIGHT_DIMMER_VALUE_TOPIC "/brightness" + /* #define AIR_TEMPERATURE "Air" #define POOL_TEMPERATURE "Pool_Water" diff --git a/source/aq_panel.c b/source/aq_panel.c index b47d526..5f8b1e0 100644 --- a/source/aq_panel.c +++ b/source/aq_panel.c @@ -30,6 +30,7 @@ void initPanelButtons(struct aqualinkdata *aqdata, bool rspda, int size, bool combo, bool dual); void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button); + char *name2label(char *str) { int len = strlen(str); @@ -687,6 +688,9 @@ const char* getRequestName(request_source source) case NET_TIMER: return "Timer"; break; + case UNACTION_TIMER: + return "UnactionTimer"; + break; } static char buf[25]; @@ -740,6 +744,9 @@ const char* getActionName(action_type type) case DATE_TIME: return "Date Time"; break; + case LIGHT_BRIGHTNESS: + return "Light Brightness"; + break; } static char buf[25]; @@ -821,11 +828,15 @@ bool setDeviceState(struct aqualinkdata *aqdata, int deviceIndex, bool isON, req // Domoticz has a bad habbit of resending the same state back to us, when we use the PRESTATE_ONOFF option // since allbutton (default) is stateless, and rssaadapter is statefull, use rssaadapter for any domoricz requests set_aqualink_rssadapter_aux_state(button, isON); + //} else if ( source == NET_TIMER && isRSSA_ENABLED ) { + // Timer will sometimes send duplicate, so use RSSA since that protocol has on/off rather than toggle + // set_aqualink_rssadapter_aux_state(button, isON); } else if (button->special_mask & PROGRAM_LIGHT && isRSSA_ENABLED) { // If off and program light, use the RS serial adapter since that is overiding the state now. set_aqualink_rssadapter_aux_state(button, isON); } else { //set_iaqualink_aux_state(button, isON); + //set_aqualink_rssadapter_aux_state(button, isON); aq_send_allb_cmd(button->code); } @@ -882,24 +893,62 @@ bool programDeviceValue(struct aqualinkdata *aqdata, action_type type, int value return true; } + +void programDeviceLightBrightness(struct aqualinkdata *aqdata, int value, int button, bool expectMultiple) +{ + clight_detail *light = getProgramableLight(aqdata, button); + + if (!isRSSA_ENABLED) { + LOG(PANL_LOG,LOG_ERR, "Light mode brightness is only supported with `rssa_device_id` set\n"); + return; + } + + if (light == NULL) { + LOG(PANL_LOG,LOG_ERR, "Light mode control not configured for button %d\n",button); + return; + } + + // DIMMER is 0,25,50,100 DIMMER2 is range + if (light->lightType == LC_DIMMER) { + value = round(value / 25); + } + + if (!expectMultiple) { + programDeviceLightMode(aqdata, value, button); + return; + } + + time(&aqdata->unactioned.requested); + aqdata->unactioned.value = value; + aqdata->unactioned.type = LIGHT_MODE; + aqdata->unactioned.id = button; + + return; +} + + //void programDeviceLightMode(struct aqualinkdata *aqdata, char *value, int button) +//void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button) void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button) { - int i; - clight_detail *light = NULL; #ifdef AQ_PDA if (isPDA_PANEL && !isPDA_IAQT) { LOG(PANL_LOG,LOG_ERR, "Light mode control not supported in PDA mode\n"); return; } #endif + /* + int i; + clight_detail *light = NULL; for (i=0; i < aqdata->num_lights; i++) { if (&aqdata->aqbuttons[button] == aqdata->lights[i].button) { // Found the programmable light light = &aqdata->lights[i]; break; } - } + }*/ + + clight_detail *light = getProgramableLight(aqdata, button); if (light == NULL) { LOG(PANL_LOG,LOG_ERR, "Light mode control not configured for button %d\n",button); @@ -916,13 +965,18 @@ void programDeviceLightMode(struct aqualinkdata *aqdata, int value, int button) _aqconfig_.light_programming_initial_off, _aqconfig_.light_programming_mode ); aq_programmer(AQ_SET_LIGHTPROGRAM_MODE, buf, aqdata); - } else if (isRSSA_ENABLED && light->lightType != LC_DIMMER) { - unsigned char rssd_value = value; - set_aqualink_rssadapter_aux_extended_state(light->button, rssd_value); + } else if (isRSSA_ENABLED && light->lightType == LC_DIMMER2) { + // Dimmer needs to be turned on before you set dimmer level + if (light->button->led->state != ON) { + set_aqualink_rssadapter_aux_extended_state(light->button, RS_SA_ON); + } + set_aqualink_rssadapter_aux_extended_state(light->button, value); } else if (isRSSA_ENABLED && light->lightType == LC_DIMMER) { // Dimmer needs to be turned on first - set_aqualink_rssadapter_aux_extended_state(light->button, RS_SA_ON); - // Value 1 = 25, 1 = 50, 3 = 75, 4 = 100 (need to convert value into binary) + if (light->button->led->state != ON) { + set_aqualink_rssadapter_aux_extended_state(light->button, RS_SA_ON); + } + // Value 1 = 25, 2 = 50, 3 = 75, 4 = 100 (need to convert value into binary) if (value >= 1 && value <= 4) { // If value is not on of those vales, then ignore unsigned char rssd_value = value * 25; @@ -979,6 +1033,9 @@ bool panel_device_request(struct aqualinkdata *aqdata, action_type type, int dev //start_timer(aqdata, &aqdata->aqbuttons[deviceIndex], deviceIndex, value); start_timer(aqdata, deviceIndex, value); break; + case LIGHT_BRIGHTNESS: + programDeviceLightBrightness(aqdata, value, deviceIndex, (source==NET_MQTT?true:false)); + break; case LIGHT_MODE: if (value <= 0) { // Consider this a bad/malformed request to turn the light off. @@ -1013,6 +1070,7 @@ bool panel_device_request(struct aqualinkdata *aqdata, action_type type, int dev // Programmable light has been updated, so update the status in AqualinkD void updateButtonLightProgram(struct aqualinkdata *aqdata, int value, int button) { + /* int i; clight_detail *light = NULL; @@ -1023,6 +1081,8 @@ void updateButtonLightProgram(struct aqualinkdata *aqdata, int value, int button break; } } + */ + clight_detail *light = getProgramableLight(aqdata, button); if (light == NULL) { LOG(PANL_LOG,LOG_ERR, "Button not found for light button index=%d\n",button); @@ -1032,6 +1092,21 @@ void updateButtonLightProgram(struct aqualinkdata *aqdata, int value, int button light->currentValue = value; } +clight_detail *getProgramableLight(struct aqualinkdata *aqdata, int button) +{ + if ( isPLIGHT(aqdata->aqbuttons[button].special_mask) ) { + return (clight_detail *)aqdata->aqbuttons[button].special_mask_ptr; + } + return NULL; +} + +pump_detail *getPumpDetail(struct aqualinkdata *aqdata, int button) +{ + if ( isVS_PUMP(aqdata->aqbuttons[button].special_mask) ) { + return (pump_detail *)aqdata->aqbuttons[button].special_mask_ptr; + } + return NULL; +} #ifdef DO_NOT_COMPILE diff --git a/source/aq_panel.h b/source/aq_panel.h index ea06b09..09d2081 100644 --- a/source/aq_panel.h +++ b/source/aq_panel.h @@ -68,6 +68,10 @@ int convertPumpPercentToSpeed(pump_detail *pump, int value); // This is probable uint16_t getPanelSupport( char *rev_string, int rev_len); aqkey *addVirtualButton(struct aqualinkdata *aqdata, char *label, int vindex); + +clight_detail *getProgramableLight(struct aqualinkdata *aqdata, int button); +pump_detail *getPumpDetail(struct aqualinkdata *aqdata, int button); + //void panneltest(); #define isPDA_PANEL ((_aqconfig_.paneltype_mask & RSP_PDA) == RSP_PDA) diff --git a/source/aq_timer.c b/source/aq_timer.c index 5a315ae..162c4cf 100644 --- a/source/aq_timer.c +++ b/source/aq_timer.c @@ -114,19 +114,22 @@ void start_timer(struct aqualinkdata *aq_data, /*aqkey *button,*/ int deviceInde } } -#define WAIT_TIME_BEFORE_ON_CHECK 1000 // 1 second +#define WAIT_TIME_BEFORE_ON_CHECK 1000 +//#define WAIT_TIME_BEFORE_ON_CHECK 1000000 // 1 second void *timer_worker( void *ptr ) { struct timerthread *tmthread; tmthread = (struct timerthread *) ptr; int retval = 0; + int cnt=0; LOG(TIMR_LOG, LOG_NOTICE, "Start timer for '%s'\n",tmthread->button->name); // Add mask so we know timer is active tmthread->button->special_mask |= TIMER_ACTIVE; +/* #ifndef PRESTATE_ONOFF delay(WAIT_TIME_BEFORE_ON_CHECK); LOG(TIMR_LOG, LOG_DEBUG, "wait finished for button state '%s'\n",tmthread->button->name); @@ -141,6 +144,19 @@ void *timer_worker( void *ptr ) panel_device_request(tmthread->aq_data, ON_OFF, tmthread->deviceIndex, false, NET_TIMER); } } +*/ + + while (tmthread->button->led->state == OFF) { + LOG(TIMR_LOG, LOG_DEBUG, "waiting for button state '%s' to change\n",tmthread->button->name); + delay(WAIT_TIME_BEFORE_ON_CHECK); + if (cnt++ == 5 && !isPDA_PANEL) { + LOG(TIMR_LOG, LOG_NOTICE, "turning on '%s'\n",tmthread->button->name); + panel_device_request(tmthread->aq_data, ON_OFF, tmthread->deviceIndex, true, NET_TIMER); + } else if (cnt == 10) { + LOG(TIMR_LOG, LOG_ERR, "button state never turned on'%s'\n",tmthread->button->name); + break; + } + } pthread_mutex_lock(&tmthread->thread_mutex); @@ -163,12 +179,24 @@ void *timer_worker( void *ptr ) LOG(TIMR_LOG, LOG_NOTICE, "End timer for '%s'\n",tmthread->button->name); - if (tmthread->button->led->state != OFF) { + // We need to detect if we ended on time or were killed. + // If killed the device is probable off (or being set to off), so we should probably poll a few times before turning off. + // Either that of change ap_panel to not turn off device if timer is set. + + //LOG(TIMR_LOG, LOG_NOTICE, "End timer duration '%d'\n",tmthread->duration_min); + + // if duration_min is 0 we were killed, if not we got here on timeout, so turn off device. + + if (tmthread->duration_min != 0 && tmthread->button->led->state != OFF) { LOG(TIMR_LOG, LOG_INFO, "Timer waking turning '%s' off\n",tmthread->button->name); panel_device_request(tmthread->aq_data, ON_OFF, tmthread->deviceIndex, false, NET_TIMER); - } else { + } else if (tmthread->button->led->state == OFF) { LOG(TIMR_LOG, LOG_INFO, "Timer waking '%s' is already off\n",tmthread->button->name); } + + if (tmthread->button->led->state != OFF) { + // Need to wait + } // remove mask so we know timer is dead tmthread->button->special_mask &= ~ TIMER_ACTIVE; diff --git a/source/aqualink.h b/source/aqualink.h index 3c9810f..22a4e51 100644 --- a/source/aqualink.h +++ b/source/aqualink.h @@ -94,6 +94,7 @@ typedef struct aqualinkkey unsigned char rssd_code; int dz_idx; uint8_t special_mask; + void *special_mask_ptr; } aqkey; // special_mask for above aqualinkkey structure. @@ -128,6 +129,7 @@ typedef enum action_type { ON_OFF, TIMER, LIGHT_MODE, + LIGHT_BRIGHTNESS, DATE_TIME } action_type; @@ -216,7 +218,8 @@ typedef enum clight_type { LC_SPARE_1, LC_SPARE_2, LC_SPARE_3, - LC_DIMMER, + 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; @@ -225,7 +228,8 @@ typedef enum { NET_API, NET_WS, NET_DZMQTT, - NET_TIMER // Not used yet, need to change aq_timer.c + NET_TIMER, // Not used yet, need to change aq_timer.c + UNACTION_TIMER } request_source; typedef struct clightd diff --git a/source/aqualinkd.c b/source/aqualinkd.c index 15a4e47..083473a 100644 --- a/source/aqualinkd.c +++ b/source/aqualinkd.c @@ -355,6 +355,9 @@ void action_delayed_request() LOG(AQUA_LOG,LOG_NOTICE, "Changing spa heater setpoint by %d\n", _aqualink_data.unactioned.value); aq_programmer(AQ_ADD_RSSADAPTER_SPA_HEATER_TEMP, sval, &_aqualink_data); } + else if (_aqualink_data.unactioned.type == LIGHT_MODE) { + panel_device_request(&_aqualink_data, LIGHT_MODE, _aqualink_data.unactioned.id, _aqualink_data.unactioned.value, UNACTION_TIMER); + } else { LOG(AQUA_LOG,LOG_ERR, "Unknown request of type %d\n", _aqualink_data.unactioned.type); @@ -496,6 +499,10 @@ int startup(char *self, char *cfgFile) } } else if (isPDA_PANEL) { if ( (_aqconfig_.device_id >= 0x60 && _aqconfig_.device_id <= 0x63) || _aqconfig_.device_id == 0x33 ) { + if ( _aqconfig_.device_id == 0x33 ) { + LOG(AQUA_LOG,LOG_NOTICE, "Enabeling iAqualink protocol.\n"); + _aqconfig_.enable_iaqualink = true; + } // We are good } else { LOG(AQUA_LOG,LOG_ERR, "Device ID 0x%02hhx does not match PDA panel, please check config!\n", _aqconfig_.device_id); @@ -572,6 +579,9 @@ int startup(char *self, char *cfgFile) LOG(AQUA_LOG,LOG_NOTICE, "Config rssa_device_id = 0x%02hhx\n", _aqconfig_.rssa_device_id); #if defined AQ_ONETOUCH || defined AQ_IAQTOUCH LOG(AQUA_LOG,LOG_NOTICE, "Config extra_device_id = 0x%02hhx\n", _aqconfig_.extended_device_id); + if (_aqconfig_.enable_iaqualink) { + LOG(AQUA_LOG,LOG_NOTICE, "Config enable_iaqualink = %s\n", bool2text(_aqconfig_.enable_iaqualink)); + } LOG(AQUA_LOG,LOG_NOTICE, "Config extra_device_prog = %s\n", bool2text(_aqconfig_.extended_device_id_programming)); #endif LOG(AQUA_LOG,LOG_NOTICE, "Config serial_port = %s\n", _aqconfig_.serial_port); diff --git a/source/color_lights.c b/source/color_lights.c index 4714e5a..4cab45e 100644 --- a/source/color_lights.c +++ b/source/color_lights.c @@ -123,9 +123,12 @@ const char *_color_light_options[NUMBER_LIGHT_COLOR_TYPES][LIGHT_COLOR_OPTIONS] "50%", // 0xb2 (simulator) = 178 dec same as (0x99 + 25) "75%", // 0xcb (simulator) = 203 dec "100%" // 0xe4 = 228 dec - } + }, + {/* Dimmer with full range */} }; +// DON'T FORGET TO CHANGE #define DIMMER_LIGHT_INDEX 10 in color_lights.h + /* @@ -198,11 +201,19 @@ bool isShowMode(const char *mode) void set_currentlight_value(clight_detail *light, int index) { + // Dimmer 2 has different values (range 1 to 100) + if (light->lightType == LC_DIMMER2) { + if (index < 0 || index > 100) + light->currentValue = 0; + else + light->currentValue = index; + } else { // We want to leave the last color, so if 0 don't do anything, but set to 0 if bad value - if (index < 0 || index > LIGHT_COLOR_OPTIONS) - light->currentValue = 0; - else if (index > 0 && index < LIGHT_COLOR_OPTIONS) - light->currentValue = index; + if (index < 0 || index > LIGHT_COLOR_OPTIONS) + light->currentValue = 0; + else if (index > 0 && index < LIGHT_COLOR_OPTIONS) + light->currentValue = index; + } } int build_color_lights_js(struct aqualinkdata *aqdata, char* buffer, int size) diff --git a/source/color_lights.h b/source/color_lights.h index eee2723..70c91b3 100644 --- a/source/color_lights.h +++ b/source/color_lights.h @@ -13,6 +13,8 @@ #define RSSD_COLOR_LIGHT_OFFSET 64 #define RSSD_DIMMER_LIGHT_OFFSET 128 +//#define DIMMER_LIGHT_TYPE_INDEX 10 + /* // color light modes (Aqualink program, Jandy, Jandy LED, SAm/SAL, Color Logic, Intellibrite) typedef enum clight_type { diff --git a/source/config.c b/source/config.c index 8afb4a4..028b04e 100644 --- a/source/config.c +++ b/source/config.c @@ -698,9 +698,11 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) { LOG(AQUA_LOG,LOG_ERR, "Config error, unknown light mode '%s'\n",type); } else { aqdata->lights[aqdata->num_lights].button = &aqdata->aqbuttons[num]; - aqdata->lights[aqdata->num_lights].lightType = type; - aqdata->num_lights++; + aqdata->lights[aqdata->num_lights].lightType = type; aqdata->aqbuttons[num].special_mask |= PROGRAM_LIGHT; + aqdata->aqbuttons[num].special_mask_ptr = &aqdata->lights[aqdata->num_lights]; + + aqdata->num_lights++; } } else { LOG(AQUA_LOG,LOG_ERR, "Config error, (colored|programmable) Lights limited to %d, ignoring %s'\n",MAX_LIGHTS,param); @@ -809,6 +811,7 @@ pump_detail *getPumpFromButtonID(struct aqualinkdata *aqdata, aqkey *button) if (aqdata->num_pumps < MAX_PUMPS) { //printf ("Creating pump %d\n",button); button->special_mask |= VS_PUMP; + button->special_mask_ptr = (void*)&aqdata->pumps[aqdata->num_pumps]; aqdata->pumps[aqdata->num_pumps].button = button; aqdata->pumps[aqdata->num_pumps].pumpType = PT_UNKNOWN; aqdata->pumps[aqdata->num_pumps].rpm = TEMP_UNKNOWN; diff --git a/source/hassio.c b/source/hassio.c index 3932596..b34af2e 100644 --- a/source/hassio.c +++ b/source/hassio.c @@ -135,6 +135,26 @@ const char *HASSIO_VSP_DISCOVER = "{" "\"retain\": false" "}"; + +const char *HASSIO_DIMMER_DISCOVER = "{" + "\"device\": {" HASS_DEVICE "}," + "\"availability\": {" HASS_AVAILABILITY "}," + "\"type\": \"light\"," + "\"unique_id\": \"aqualinkd_%s\"," // Aux_5 + "\"name\": \"%s\"," // Dimmer_name + "\"state_topic\": \"%s/%s\"," // aqualinkd,Aux_5 + "\"command_topic\": \"%s/%s/set\"," // aqualinkd,Aux_5 + "\"json_attributes_topic\": \"%s/%s/delay\"," // aqualinkd,Aux_5 + "\"json_attributes_template\": \"{{ {'delay': value|int} | tojson }}\"," + "\"payload_on\": \"1\"," + "\"payload_off\": \"0\"," + "\"brightness_command_topic\": \"%s/%s%s/set\"," // aqualinkd,Aux_5,/brightness + "\"brightness_state_topic\": \"%s/%s%s\"," // aqualinkd/Aux_5,/brightness + "\"brightness_scale\": 100," + "\"qos\": 1," + "\"retain\": false" +"}"; + // Need to add timer attributes to the switches, once figure out how to use in homeassistant // ie aqualinkd/Filter_Pump/timer/duration @@ -371,7 +391,20 @@ void publish_mqtt_hassio_discover(struct aqualinkdata *aqdata, struct mg_connect _aqconfig_.mqtt_aq_topic,aqdata->aqbuttons[i].name, (_aqconfig_.convert_mqtt_temp?HASSIO_CONVERT_CLIMATE_TOF:HASSIO_NO_CONVERT_CLIMATE)); sprintf(topic, "%s/climate/aqualinkd/aqualinkd_%s/config", _aqconfig_.mqtt_hass_discover_topic, aqdata->aqbuttons[i].name); - send_mqtt(nc, topic, msg); + send_mqtt(nc, topic, msg); + } else if ( isPLIGHT(aqdata->aqbuttons[i].special_mask) && ((clight_detail *)aqdata->aqbuttons[i].special_mask_ptr)->lightType == LC_DIMMER2 ) { + // Dimmer + sprintf(msg,HASSIO_DIMMER_DISCOVER, + _aqconfig_.mqtt_aq_topic, + aqdata->aqbuttons[i].name, + aqdata->aqbuttons[i].label, + _aqconfig_.mqtt_aq_topic,aqdata->aqbuttons[i].name, + _aqconfig_.mqtt_aq_topic,aqdata->aqbuttons[i].name, + _aqconfig_.mqtt_aq_topic,aqdata->aqbuttons[i].name, + _aqconfig_.mqtt_aq_topic,aqdata->aqbuttons[i].name,LIGHT_DIMMER_VALUE_TOPIC, + _aqconfig_.mqtt_aq_topic,aqdata->aqbuttons[i].name,LIGHT_DIMMER_VALUE_TOPIC); + sprintf(topic, "%s/light/aqualinkd/aqualinkd_%s/config", _aqconfig_.mqtt_hass_discover_topic, aqdata->aqbuttons[i].name); + send_mqtt(nc, topic, msg); } else { // Switches //sprintf(msg,"{\"type\": \"switch\",\"unique_id\": \"%s\",\"name\": \"%s\",\"state_topic\": \"aqualinkd/%s\",\"command_topic\": \"aqualinkd/%s/set\",\"json_attributes_topic\": \"aqualinkd/%s/delay\",\"json_attributes_topic\": \"aqualinkd/%s/delay\",\"json_attributes_template\": \"{{ {'delay': value|int} | tojson }}\",\"payload_on\": \"1\",\"payload_off\": \"0\",\"qos\": 1,\"retain\": false}" , diff --git a/source/iaqualink.c b/source/iaqualink.c index 60e836b..5146f84 100644 --- a/source/iaqualink.c +++ b/source/iaqualink.c @@ -39,6 +39,11 @@ unsigned char _std_cmd[2]; int _iaqua_q_length = 0; bool _aqua_last_cmdfrom_queue = false; + +unsigned char _cmd_readyCommand[] = {0x3f, 0x20}; +unsigned char _fullcmd[] = {0x00, 0x24, 0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + bool push_iaqualink_cmd(unsigned char *cmd, int length) { if (_iaqua_q_length >= IAQUA_QLEN ) { LOG(IAQL_LOG,LOG_ERR, "Queue overflow, last command ignored!\n"); @@ -49,7 +54,7 @@ bool push_iaqualink_cmd(unsigned char *cmd, int length) { _iqaua_queue[_iaqua_q_length].length = length; _iaqua_q_length++; - LOG(IAQL_LOG, LOG_NOTICE, "Queue cmd, size %d, queu length=%d\n",length, _iaqua_q_length); + LOG(IAQL_LOG, LOG_INFO, "Queue cmd, size %d, queu length=%d\n",length, _iaqua_q_length); //LOG(IAQL_LOG,LOG_DEBUG, "Added to message queue, position %d 0x%02hhx|0x%02hhx|0x%02hhx|0x%02hhx\n",_rssa_q_length-1,_rssa_queue[_rssa_q_length-1][0],_rssa_queue[_rssa_q_length-1][1],_rssa_queue[_rssa_q_length-1][2],_rssa_queue[_rssa_q_length-1][3]); return true; @@ -86,6 +91,8 @@ int get_iaqualink_cmd(unsigned char source_message_type, unsigned char **dest_me _aqua_last_cmdfrom_queue = true; } else { LOG(IAQL_LOG,LOG_WARNING,"Next command in queue is too large, ignoring\n"); + LOG(IAQL_LOG,LOG_ERR,"Re sending get prepare frame\n"); + *dest_message = _cmd_readyCommand; } } @@ -182,25 +189,25 @@ void lastchecksum(unsigned char *packet, int length){ switch (packet[PKT_CMD]){ case 0x70: if (last70checksum != packet[length-3] && last70checksum != 0x00) { - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); - LOG(IAQL_LOG, LOG_NOTICE,"******* CHECKSUM CHANGED for 0x70 *******\n"); - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"******* CHECKSUM CHANGED for 0x70 *******\n"); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); } last70checksum = packet[length-3]; break; case 0x71: if (last71checksum != packet[length-3] && last71checksum != 0x00) { - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); - LOG(IAQL_LOG, LOG_NOTICE,"******* CHECKSUM CHANGED for 0x71 *******\n"); - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"******* CHECKSUM CHANGED for 0x71 *******\n"); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); } last71checksum = packet[length-3]; break; case 0x72: if (last72checksum != packet[length-3] && last72checksum != 0x00) { - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); - LOG(IAQL_LOG, LOG_NOTICE,"******* CHECKSUM CHANGED for 0x72 *******\n"); - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"******* CHECKSUM CHANGED for 0x72 *******\n"); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); } last72checksum = packet[length-3]; break; @@ -214,6 +221,7 @@ void lastchecksum(unsigned char *packet, int length){ All taken from panel Yg, but only heater setpoints seem to work. Only setpoints seem to work, + Can't get to work on T2 panel RPM to 2750 Bit 6 = 0x5e Bit 10 * 256 + Bit 11 @@ -223,6 +231,8 @@ HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0a|0xbe|0x00|0x00|0x00| RPM to 2995 HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0b|0xb3|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xcb|0x10|0x03| + + Can't get to work on T2 panel SWG 50% Byte 6 = 0x19 Byte 7 = 50% @@ -233,11 +243,13 @@ SWG 51% Byte 7 = 51% HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x33|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x0f|0x10|0x03| +Works on T2 Spa Setpoint 102 Byte 6 = 0x06 Byte 8 = 0x66=102 HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x06|0x00|0x66|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x16|0x10|0x03| +Works on T2 Pool Setpoint 72 Byte 6 = 0x05 Byte 8 = 0x48=72 @@ -245,8 +257,6 @@ HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x05|0x00|0x48|0x00|0x00|0x00|0x00|0x00|0x00| */ -unsigned char _cmd_readyCommand[] = {0x3f, 0x20}; -unsigned char _fullcmd[] = {0x00, 0x24, 0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; void set_iaqualink_aux_state(aqkey *button, bool isON) { @@ -259,6 +269,8 @@ void set_iaqualink_aux_state(aqkey *button, bool isON) { LOG(IAQL_LOG, LOG_ERR, "Couldn't find iaqualink keycode for button %s\n",button->label); } + // reset + _fullcmd[4] = 0x00; } void set_iaqualink_heater_setpoint(int value, bool isPool) { @@ -275,6 +287,24 @@ void set_iaqualink_heater_setpoint(int value, bool isPool) { push_iaqualink_cmd(_cmd_readyCommand, 2); push_iaqualink_cmd(_fullcmd, 19); + + // reset + _fullcmd[4] = 0x00; + _fullcmd[6] = 0x00; +} + +void iAqSetButtonState(struct aqualinkdata *aq_data, int index, const unsigned char byte) +{ + if ( aq_data->aqbuttons[index].led->state != OFF && byte == 0x00) { + aq_data->aqbuttons[index].led->state = OFF; + LOG(IAQL_LOG, LOG_INFO, "Set %s off\n",aq_data->aqbuttons[index].label); + } else if ( aq_data->aqbuttons[index].led->state != ON && byte == 0x01) { + aq_data->aqbuttons[index].led->state = ON; + LOG(IAQL_LOG, LOG_INFO, "Set %s on\n",aq_data->aqbuttons[index].label); + } else if ( aq_data->aqbuttons[index].led->state != ENABLE && byte == 0x03) { + aq_data->aqbuttons[index].led->state = ENABLE; + LOG(IAQL_LOG, LOG_INFO, "Set %s enabled\n",aq_data->aqbuttons[index].label); + } } /* @@ -287,7 +317,7 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu { if (packet[PKT_CMD] == CMD_IAQ_MAIN_STATUS) { - logPacket(IAQL_LOG, LOG_NOTICE, packet, length, true); + logPacket(IAQL_LOG, LOG_INFO, packet, length, true); int startIndex = 4 + 1; int numberBytes = packet[4]; int offsetIndex = startIndex + numberBytes; @@ -314,12 +344,15 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu if (byteType == 0) { label = "Filter Pump "; + if (isPDA_PANEL) { iAqSetButtonState(aq_data, 0, byte); } } else if (byteType == 1) { - label = "Pool Heater "; // 0x01=on&heating, 0x03=ena + label = "Pool Heater "; // 0x00 off 0x01=on&heating, 0x03=enabled + if (isPDA_PANEL) { iAqSetButtonState(aq_data, aq_data->pool_heater_index , byte); } } else if (byteType == 2) { label = "Spa "; } else if (byteType == 3) { label = "Spa Heater "; // 0x01=on&heating, 0x03=ena + if (isPDA_PANEL) { iAqSetButtonState(aq_data, aq_data->spa_heater_index , byte); } } else if (byteType == 6) { label = "Pool Htr setpoint"; } else if (byteType == 8 || byteType == 9) {// 8 usually, also get 9 & 14 (different spa/heater modes not sorted out yet. 14 sometimes blank as well) @@ -338,9 +371,9 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu else label = " "; - LOG(IAQL_LOG, LOG_NOTICE, "%-17s = %3d | index=%d type=(%0.2d 0x%02hhx) value=0x%02hhx offset=%d\n", label, byte, i, byteType, byteType, byte, (offsetIndex + i)); + LOG(IAQL_LOG, LOG_INFO, "%-17s = %3d | index=%d type=(%0.2d 0x%02hhx) value=0x%02hhx offset=%d\n", label, byte, i, byteType, byteType, byte, (offsetIndex + i)); } - LOG(IAQL_LOG, LOG_NOTICE, "Status from other protocols Pump %s, Spa %s, SWG %d, PumpRPM %d, PoolSP=%d, SpaSP=%d, WaterTemp=%d, AirTemp=%d\n", + LOG(IAQL_LOG, LOG_INFO, "Status from other protocols Pump %s, Spa %s, SWG %d, PumpRPM %d, PoolSP=%d, SpaSP=%d, WaterTemp=%d, AirTemp=%d\n", aq_data->aqbuttons[0].led->state == OFF ? "Off" : "On ", aq_data->aqbuttons[1].led->state == OFF ? "Off" : "On ", aq_data->swg_percent, @@ -352,13 +385,14 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu } else if (packet[PKT_CMD] == CMD_IAQ_1TOUCH_STATUS) { - logPacket(IAQL_LOG, LOG_NOTICE, packet, length, true); + logPacket(IAQL_LOG, LOG_INFO, packet, length, true); int numLabels = packet[4]; int start = numLabels + 4 + 1; if (numLabels == 1) { - LOG(IAQL_LOG, LOG_NOTICE, "**** !!! haven't decoded above packet yet !!! *****\n"); + // This just seem to list a ton of pump (names) + LOG(IAQL_LOG, LOG_INFO, "**** !!! haven't decoded above packet yet !!! *****\n"); return false; } @@ -367,14 +401,14 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu int status = packet[start]; int length = packet[start + 1]; int byteType = packet[5 + i]; - LOG(IAQL_LOG, LOG_NOTICE, "%-15.*s = %s | index %d type=(%0.2d 0x%02hhx) status=0x%02hhx start=%d length=%d\n", length, &packet[start + 2], (status == 0x00 ? "Off" : "On "), i, byteType, byteType, status, start, length); + LOG(IAQL_LOG, LOG_INFO, "%-15.*s = %s | index %d type=(%0.2d 0x%02hhx) status=0x%02hhx start=%d length=%d\n", length, &packet[start + 2], (status == 0x00 ? "Off" : "On "), i, byteType, byteType, status, start, length); // Check against virtual onetouch buttons. for (int bi=aq_data->virtual_button_start ; bi < aq_data->total_buttons ; bi++) { if (rsm_strcmp((char *)&packet[start + 2], aq_data->aqbuttons[bi].label) == 0) { - //LOG(IAQL_LOG, LOG_NOTICE, "Status for %s is %s\n",aq_data->aqbuttons[bi].label,(status == 0x00 ? "Off" : "On ")); + //LOG(IAQL_LOG, LOG_INFO, "Status for %s is %s\n",aq_data->aqbuttons[bi].label,(status == 0x00 ? "Off" : "On ")); // == means doesn;t match, RS 1=on 0=off / LED enum 1=off 0=on if (aq_data->aqbuttons[bi].led->state == status) { - LOG(IAQL_LOG, LOG_NOTICE, "Updated Status for %s is %s\n",aq_data->aqbuttons[bi].label,(status == 0x00 ? "Off" : "On ")); + LOG(IAQL_LOG, LOG_INFO, "Updated Status for %s is %s\n",aq_data->aqbuttons[bi].label,(status == 0x00 ? "Off" : "On ")); aq_data->aqbuttons[bi].led->state = (status == 0x00 ? OFF:ON); aq_data->updated = true; } @@ -385,7 +419,7 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu } else if (packet[PKT_CMD] == CMD_IAQ_AUX_STATUS) { - logPacket(IAQL_LOG, LOG_NOTICE, packet, length, true); + logPacket(IAQL_LOG, LOG_INFO, packet, length, true); // Look at notes in iaqualink.c for how this packet is made up // Since this is so similar to above CMD_IAQ_1TOUCH_STATUS, we should look at using same logic for both. int start = packet[4]; @@ -397,17 +431,17 @@ bool process_iAqualinkStatusPacket(unsigned char *packet, int length, struct aqu int labellen = packet[status + 4]; if (labelstart + labellen < length) { - LOG(IAQL_LOG, LOG_NOTICE, "%-15.*s = %s | bit1=0x%02hhx bit2=0x%02hhx bit3=0x%02hhx bit4=0x%02hhx\n", labellen, &packet[labelstart], (packet[status] == 0x00 ? "Off" : "On "), packet[status], packet[status + 1], packet[status + 2], packet[status + 3]); + LOG(IAQL_LOG, LOG_INFO, "%-15.*s = %s | bit1=0x%02hhx bit2=0x%02hhx bit3=0x%02hhx bit4=0x%02hhx\n", labellen, &packet[labelstart], (packet[status] == 0x00 ? "Off" : "On "), packet[status], packet[status + 1], packet[status + 2], packet[status + 3]); } if (isPDA_PANEL) { for (int bi=2 ; bi < aq_data->total_buttons ; bi++) { if (rsm_strcmp((char *)&packet[labelstart], aq_data->aqbuttons[bi].label) == 0) { if (aq_data->aqbuttons[bi].led->state == packet[status]) { - LOG(IAQL_LOG, LOG_NOTICE, "Updated Status for %s is %s\n",aq_data->aqbuttons[bi].label,(packet[status] == 0x00 ? "Off" : "On ")); + LOG(IAQL_LOG, LOG_INFO, "Updated Status for %s is %s\n",aq_data->aqbuttons[bi].label,(packet[status] == 0x00 ? "Off" : "On ")); aq_data->aqbuttons[bi].led->state = (packet[status] == 0x00 ? OFF:ON); aq_data->updated = true; } - //LOG(IAQL_LOG, LOG_NOTICE, "Match %s to %.*s state(aqd=%d pnl=%d)\n",aq_data->aqbuttons[bi].label, labellen, (char *)&packet[labelstart], aq_data->aqbuttons[bi].led->state, packet[status]); + //LOG(IAQL_LOG, LOG_INFO, "Match %s to %.*s state(aqd=%d pnl=%d)\n",aq_data->aqbuttons[bi].label, labellen, (char *)&packet[labelstart], aq_data->aqbuttons[bi].led->state, packet[status]); } } } @@ -437,19 +471,27 @@ bool process_iaqualink_packet(unsigned char *packet, int length, struct aqualink static int cnt = 0; //static unsigned char ID = 0; //static cur_swg = 0; + static unsigned char sendid = 0x00; if (packet[PKT_CMD] == 0x53) { cnt++; if (cnt == 20) { cnt=0; +/* + sendid=sendid==0x18?0x60:0x18; + _fullcmd[4] = sendid; + push_iaqualink_cmd(_cmd_readyCommand, 2); + push_iaqualink_cmd(_fullcmd, 19); + _fullcmd[4] = 0x00; +*/ push_iaqualink_cmd(cmd_getMainstatus, 2); push_iaqualink_cmd(cmd_getTouchstatus, 2); push_iaqualink_cmd(cmd_getAuxstatus, 2); /* - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); - LOG(IAQL_LOG, LOG_NOTICE,"********** Send %d 0x%02hhx ************\n",ID,ID); - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"********** Send %d 0x%02hhx ************\n",ID,ID); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); _fullcmd[4] = ID++; push_iaqualink_cmd(_cmd_readyCommand, 2); @@ -478,13 +520,13 @@ bool process_iaqualink_packet(unsigned char *packet, int length, struct aqualink //push_iaqualink_cmd(cmd_getAuxstatus, 2); /* if (aq_data->swg_percent != cur_swg && cur_swg != 0) { - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); - LOG(IAQL_LOG, LOG_NOTICE,"********** SWG Changed to %d ************\n",aq_data->swg_percent); - LOG(IAQL_LOG, LOG_NOTICE,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); + LOG(IAQL_LOG, LOG_INFO,"********** SWG Changed to %d ************\n",aq_data->swg_percent); + LOG(IAQL_LOG, LOG_INFO,"*****************************************\n"); exit(0); } cur_swg = aq_data->swg_percent; - LOG(IAQL_LOG, LOG_NOTICE,"******* QUEUE SWG Comand of %d | 0x%02hhx *************\n",ID,ID); + LOG(IAQL_LOG, LOG_INFO,"******* QUEUE SWG Comand of %d | 0x%02hhx *************\n",ID,ID); ID++;*/ } @@ -524,7 +566,7 @@ void send_iaqualink_ack(int rs_fd, unsigned char *packet_buffer) */ if (packet_buffer[PKT_CMD] == CMD_PROBE) { - LOG(IAQL_LOG, LOG_NOTICE, "Got probe on '0x%02hhx' 2nd iAqualink Protocol\n", packet_buffer[PKT_DEST]); + LOG(IAQL_LOG, LOG_INFO, "Got probe on '0x%02hhx' 2nd iAqualink Protocol\n", packet_buffer[PKT_DEST]); send_extended_ack(rs_fd, packet_buffer[PKT_CMD], 0x00); } else if (packet_buffer[PKT_CMD] == 0x53) @@ -534,22 +576,22 @@ void send_iaqualink_ack(int rs_fd, unsigned char *packet_buffer) if (cnt == 10) { //cnt = 5; - LOG(IAQL_LOG, LOG_NOTICE, "Sent accept next packet Comand\n"); + LOG(IAQL_LOG, LOG_INFO, "Sent accept next packet Comand\n"); send_extended_ack(rs_fd, 0x3f, 0x20); } if (cnt == 20) { - LOG(IAQL_LOG, LOG_NOTICE, "Sending get status\n"); + LOG(IAQL_LOG, LOG_INFO, "Sending get status\n"); send_extended_ack(rs_fd, 0x3f, 0x08); } else if (cnt == 22) { - LOG(IAQL_LOG, LOG_NOTICE, "Sending get other status\n"); + LOG(IAQL_LOG, LOG_INFO, "Sending get other status\n"); send_extended_ack(rs_fd, 0x3f, 0x10); } else if (cnt == 24) { - LOG(IAQL_LOG, LOG_NOTICE, "Sending get aux button status\n"); + LOG(IAQL_LOG, LOG_INFO, "Sending get aux button status\n"); send_extended_ack(rs_fd, 0x3f, 0x18); } else @@ -576,7 +618,7 @@ void send_iaqualink_ack(int rs_fd, unsigned char *packet_buffer) //pb3[4] = id++; //swg[5] = ++id; - LOG(IAQL_LOG, LOG_NOTICE, "*** Sending SWG dec=%d hex=0x%02hhx\n", swg[5], swg[5]); + LOG(IAQL_LOG, LOG_INFO, "*** Sending SWG dec=%d hex=0x%02hhx\n", swg[5], swg[5]); // send_packet(rs_fd, pb2, 25); send_jandy_command(rs_fd, swg, 19); } @@ -588,199 +630,3 @@ void send_iaqualink_ack(int rs_fd, unsigned char *packet_buffer) } #endif -/* ----- -Retrieve poll 0x53 -Reply ack w/ command 0x01|0x3f|0x20. (0x20 command) -Retrieve 0x73 command Same ID iAqualink -Reply iAQ pButton ( turn something on / set something) - -Retrieve poll 0x53 -Reply ack w/ command 0x01|0x3f|0x08. (0x08 command) -Retrieve 0x70 command on AqualinkTouch ID -Reply iAQ pButton (status / last part of frame is board cpu) --- Byte 4 = offset. --- Byte 21 look like spa heat 0x00=off, 0x03=enabled --- offest+ 8 spa setpoint --- offset+ 10 air temp --- offest+ 13 pool temp --- offset+ 14 SWG% ????? --- Byte 27 looks like air temp --- Byte 28 air temp???? --- Byte 30 pool temp --- Byte 34 looks like SWG% --- after byte 0xff is board - -Retrieve poll 0x53 -Reply ack w/ command 0x01|0x3f|0x10. (0x10 command) -Retrieve 0x71 command on AqualinkTouch ID -Reply iAQ pButton (not sure) - Byte 4 & 5 seems to indicate a different sub type - 0x71|0x01|0x19 = status about pool / spa / speed 1,2,3,4 / pool & spa heat - 0x71|0x01|0x1a = no idea - 0x71|0x01|0x17 = Pump numbers (doesn't seem to have any status, just pump names) - - 0x71|0x06|0x01 = Touch like spa mode / all off - 0x71|0x07|0x01 = Same as above. but more trailing packets. - -Retrieve poll 0x53 -Reply ack w/ command 0x3f 0x18. (0x18 is command) -Retrieve 0x72 command on AqualinkTouch ID -Get a massive packet Aux status - ----- - -Retrieve poll 0x53 -Reply ack w/ command 0x01|0x3f|0x20. (0x20 command) -Retrieve 0x72 command -Reply iAQ pButton (turn something on / set something). Below are examples. - -RPM to 2750 -Bit 10 * 256 + Bit 11 -Bit 6 & 7 probably pump index. - HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0a|0xbe|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xd5|0x10|0x03| - -RPM to 2995 - HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0b|0xb3|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xcb|0x10|0x03| - -SWG 50% -Byte 7 = 50% - HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x32|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x0e|0x10|0x03| - -SWG 51% -Byte 7 = 51% - HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x33|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x0f|0x10|0x03| - ---------- - -Send command 0x18 to 0xa1 returns below to 0x31. Looks like status of aux devices. -Retrieve poll 0x53 -Reply ack w/ command 0x3f 0x18. (0x18 is command) -Get a massive packet back, of aux status - -Filter pump does not effect the below. -Heater on/off does not effect below. -HEater setpoints does not effect. -Only Aux on/off seem to effect the status. - -4th bit tells you where to start, - after start 4 bits are status - last bit of status tell you chars in label. - after label repeat start 4 bits. - -For Aux1 10th bit 0=off 1=on 11 to 14 15 to 19=name - Aux2 19th - Aux3 28 - Aux4 37 - -In Below Aux 3 color light / Aux 4 dimmer / Aux 5 color light (different type to aux3) - -Aux 1 off / Aux 3 on - HEX: 0x10|0x02|0x31|0x72|0x05|0x01|0x02|0x03|0x04|0x05|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x01|0x07|0x02|0x03|0x04|0x41|0x75|0x78|0x33|0x00|0x01|0x01|0x00|0x04|0x41|0x75|0x78|0x34|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0xd5|0x10|0x03| -Dec | 16| 2| 49| 114| 5| 1| 2| 3| 4| 5| 0| 1| 0| 0| 4| 65| 117| 120| 49| 1| 1| 0| 0| 4| 65| 117| 120| 50| 1| 7| 2| 3| 4| 65| 117| 120| 51| 0| 1| 1| 0| 4| 65| 117| 120| 52| 0| 1| 0| 0| 4| 65| 117| 120| 53| 213| 16| 3 -Ascii | | | 1| r| | | | | | | | | | | | A| u| x| 1| | | | | | A| u| x| 2| | | | | | A| u| x| 3| | | | | | A| u| x| 4| | | | | | A| u| x| 5| | | - -Aux 1 on / Aux 3 on -| HEX: 0x10|0x02|0x31|0x72|0x05|0x01|0x02|0x03|0x04|0x05|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x01|0x07|0x02|0x03|0x04|0x41|0x75|0x78|0x33|0x00|0x01|0x01|0x00|0x04|0x41|0x75|0x78|0x34|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0xd6|0x10|0x03| -Dec | 16| 2| 49| 114| 5| 1| 2| 3| 4| 5| 1| 1| 0| 0| 4| 65| 117| 120| 49| 1| 1| 0| 0| 4| 65| 117| 120| 50| 1| 7| 2| 3| 4| 65| 117| 120| 51| 0| 1| 1| 0| 4| 65| 117| 120| 52| 0| 1| 0| 0| 4| 65| 117| 120| 53| 214| 16| 3 -Ascii | | | 1| r| | | | | | | | | | | | A| u| x| 1| | | | | | A| u| x| 2| | | | | | A| u| x| 3| | | | | | A| u| x| 4| | | | | | A| u| x| 5| | | - -Aux 1 off Aux3 to different light color -Hex |0x10|0x02|0x31|0x72|0x05|0x01|0x02|0x03|0x04|0x05|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x00|0x07|0x02|0x03|0x04|0x41|0x75|0x78|0x33|0x00|0x01|0x01|0x00|0x04|0x41|0x75|0x78|0x34|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0xd4|0x10|0x03| -Dec | 16| 2| 49| 114| 5| 1| 2| 3| 4| 5| 0| 1| 0| 0| 4| 65| 117| 120| 49| 1| 1| 0| 0| 4| 65| 117| 120| 50| 0| 7| 2| 3| 4| 65| 117| 120| 51| 0| 1| 1| 0| 4| 65| 117| 120| 52| 0| 1| 0| 0| 4| 65| 117| 120| 53| 212| 16| 3 -Ascii | | | 1| r| | | | | | | | | | | | A| u| x| 1| | | | | | A| u| x| 2| | | | | | A| u| x| 3| | | | | | A| u| x| 4| | | | | | A| u| x| 5| | | - - - -RS16 panel. - HEX: 0x10|0x02|0x31|0x72|0x0f|0x01|0x02|0x03|0x04|0x05|0x06|0x07|0x08|0x09|0x0a|0x0b|0x0c|0x0d|0x0e|0x0f|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x33|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x34|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x36|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x37|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x31|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x32|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x33|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x34|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x35|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x36|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x37|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x38|0x77|0x10|0x03| -Dec | 16| 2| 49| 114| 15| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15| 0| 1| 0| 0| 4| 65| 117| 120| 49| 1| 1| 0| 0| 4| 65| 117| 120| 50| 1| 1| 0| 0| 4| 65| 117| 120| 51| 1| 1| 0| 0| 4| 65| 117| 120| 52| 1| 1| 0| 0| 4| 65| 117| 120| 53| 1| 1| 0| 0| 4| 65| 117| 120| 54| 1| 1| 0| 0| 4| 65| 117| 120| 55| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 49| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 50| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 51| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 52| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 53| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 54| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 55| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 56| 119| 16| 3 -Ascii | | | 1| r| | | | | | | | | | | | | | | | | | | | | | A| u| x| 1| | | | | | A| u| x| 2| | | | | | A| u| x| 3| | | | | | A| u| x| 4| | | | | | A| u| x| 5| | | | | | A| u| x| 6| | | | | | A| u| x| 7| | | | | | A| u| x| | B| 1| | | | | | A| u| x| | B| 2| | | | | | A| u| x| | B| 3| | | | | | A| u| x| | B| 4| | | | | | A| u| x| | B| 5| | | | | | A| u| x| | B| 6| | | | | | A| u| x| | B| 7| | | | | | A| u| x| | B| 8| w| | - -Hex |0x10|0x02|0x31|0x72| - -*/ - -/* Startup sequences - -RS16 combo -Debug: RS Serial: Read Jandy packet To 0xa1 of type Probe | HEX: 0x10|0x02|0xa1|0x00|0xb3|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x61' | HEX: 0x10|0x02|0xa1|0x61|0x00|0x00|0x00|0x01|0x00|0x1d|0x32|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x61|0x00|0x74|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x50' | HEX: 0x10|0x02|0xa1|0x50|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x23|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x50|0x00|0x63|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x51' | HEX: 0x10|0x02|0xa1|0x51|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x00|0xa2|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x51|0x00|0x64|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x59' | HEX: 0x10|0x02|0xa1|0x59|0x00|0x0c|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x59|0x00|0x6c|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x52' | HEX: 0x10|0x02|0xa1|0x52|0x00|0x05|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x52|0x00|0x65|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type iAqalnk Poll | HEX: 0x10|0x02|0xa1|0x53|0x06|0x10|0x03| - -RS8 Combo rev T.2 -Debug: RS Serial: Read Jandy packet To 0xa1 of type Probe | HEX: 0x10|0x02|0xa1|0x00|0xb3|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x61' | HEX: 0x10|0x02|0xa1|0x61|0x00|0x00|0x00|0x01|0x00|0x1d|0x32|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x61|0x00|0x74|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x50' | HEX: 0x10|0x02|0xa1|0x50|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x23|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x50|0x00|0x63|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x51' | HEX: 0x10|0x02|0xa1|0x51|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x00|0xa2|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x51|0x00|0x64|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x59' | HEX: 0x10|0x02|0xa1|0x59|0x00|0x0c|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x59|0x00|0x6c|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x52' | HEX: 0x10|0x02|0xa1|0x52|0x00|0x05|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x52|0x00|0x65|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type iAqalnk Poll | HEX: 0x10|0x02|0xa1|0x53|0x06|0x10|0x03| - -RS4 rev Yg -Notice: Serial Log:Read Jandy packet To 0xa3 of type Probe | HEX: 0x10|0x02|0xa3|0x00|0xb5|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x61' | HEX: 0x10|0x02|0xa3|0x61|0x00|0x00|0x00|0x04|0x00|0x27|0x41|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x61|0x00|0x74|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x50' | HEX: 0x10|0x02|0xa3|0x50|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x25|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x50|0x00|0x63|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x51' | HEX: 0x10|0x02|0xa3|0x51|0x00|0x06|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x51|0x00|0x64|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x59' | HEX: 0x10|0x02|0xa3|0x59|0x00|0x0e|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x59|0x00|0x6c|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x52' | HEX: 0x10|0x02|0xa3|0x52|0x00|0x07|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x52|0x00|0x65|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x53' | HEX: 0x10|0x02|0xa3|0x53|0x08|0x10|0x03| -Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x3f|0x00|0x52|0x10|0x03| - -RS6 rev T2 RS8 (home) -Debug: RS Serial: Read Jandy packet To 0xa1 of type Probe | HEX: 0x10|0x02|0xa1|0x00|0xb3|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x61' | HEX: 0x10|0x02|0xa1|0x61|0x00|0x00|0x00|0x01|0x00|0x1d|0x32|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x61|0x00|0x74|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x50' | HEX: 0x10|0x02|0xa1|0x50|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x23|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x50|0x00|0x63|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x51' | HEX: 0x10|0x02|0xa1|0x51|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x00|0xa2|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x51|0x00|0x64|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x59' | HEX: 0x10|0x02|0xa1|0x59|0x01|0x0d|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x59|0x00|0x6c|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x52' | HEX: 0x10|0x02|0xa1|0x52|0x03|0x08|0x10|0x03| -Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x52|0x00|0x65|0x10|0x03| -Debug: RS Serial: Read Jandy packet To 0xa1 of type iAqalnk Poll | HEX: 0x10|0x02|0xa1|0x53|0x06|0x10|0x03| -*/ - - -/* - - -0x10|0x02|0x31|0x72|0x0f|0x01|0x02|0x03|0x04|0x05|0x06|0x07|0x08|0x09|0x0a|0x0b|0x0c|0x0d|0x0e|0x0f|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x33|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x34|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x36|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x37|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x31|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x32|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x33|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x34|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x35|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x36|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x37|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x38|0x70|0x10|0x03| - - -Only panel (RS8) -Air index 3 type 15 (pump off) -Air index 3 type 14 (pump off) -Air index 3 type 8 (pump on) -Water index 5 type 15 (pump on) -Temp2 ndex 8 type 20 -always 1 | index=4 type=(15 0x0f) - -Comb0 -Spa setpoint index 8 type 14 -Air index 8 type 26 -*/ diff --git a/source/iaqualink.h b/source/iaqualink.h index add64f1..4cda702 100644 --- a/source/iaqualink.h +++ b/source/iaqualink.h @@ -106,4 +106,273 @@ Below get's sent to AqualinkTouch with iAqualink is enabled. End of message is board cpu and panel type. Read Jandy packet To 0x33 of type Unknown '0x70' | HEX: 0x10|0x02|0x33|0x70|0x0d|0x00|0x01|0x02|0x03|0x05|0x06|0x07|0x0e|0x0f|0x1a|0x1d|0x20|0x21|0x00|0x00|0x00|0x00|0x00|0x48|0x00|0x66|0x00|0x50|0x00|0x00|0x00|0xff|0x42|0x30|0x33|0x31|0x36|0x38|0x32|0x33|0x20|0x52|0x53|0x2d|0x34|0x20|0x43|0x6f|0x6d|0x62|0x6f|0x00|0x00|0x4b|0x10|0x03| +*/ + +/* +---- +Retrieve poll 0x53 +Reply ack w/ command 0x01|0x3f|0x20. (0x20 command) +Retrieve 0x73 command Same ID iAqualink +Reply iAQ pButton ( turn something on / set something) + +Retrieve poll 0x53 +Reply ack w/ command 0x01|0x3f|0x08. (0x08 command) +Retrieve 0x70 command on AqualinkTouch ID +Reply iAQ pButton (status / last part of frame is board cpu) +-- Byte 4 = offset. +-- Byte 21 look like spa heat 0x00=off, 0x03=enabled +-- offest+ 8 spa setpoint +-- offset+ 10 air temp +-- offest+ 13 pool temp +-- offset+ 14 SWG% ????? +-- Byte 27 looks like air temp +-- Byte 28 air temp???? +-- Byte 30 pool temp +-- Byte 34 looks like SWG% +-- after byte 0xff is board + +Retrieve poll 0x53 +Reply ack w/ command 0x01|0x3f|0x10. (0x10 command) +Retrieve 0x71 command on AqualinkTouch ID +Reply iAQ pButton (not sure) + Byte 4 & 5 seems to indicate a different sub type + 0x71|0x01|0x19 = status about pool / spa / speed 1,2,3,4 / pool & spa heat + 0x71|0x01|0x1a = no idea + 0x71|0x01|0x17 = Pump numbers (doesn't seem to have any status, just pump names) + + 0x71|0x06|0x01 = Touch like spa mode / all off + 0x71|0x07|0x01 = Same as above. but more trailing packets. + +Retrieve poll 0x53 +Reply ack w/ command 0x3f 0x18. (0x18 is command) +Retrieve 0x72 command on AqualinkTouch ID +Get a massive packet Aux status + +---- + +Retrieve poll 0x53 +Reply ack w/ command 0x01|0x3f|0x20. (0x20 command) +Retrieve 0x72 command +Reply iAQ pButton (turn something on / set something). Below are examples. + +RPM to 2750 +Bit 10 * 256 + Bit 11 +Bit 6 & 7 probably pump index. + HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0a|0xbe|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xd5|0x10|0x03| + +RPM to 2995 + HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0b|0xb3|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xcb|0x10|0x03| + +SWG 50% +Byte 7 = 50% + HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x32|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x0e|0x10|0x03| + +SWG 51% +Byte 7 = 51% + HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x33|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x0f|0x10|0x03| + +--------- + +Send command 0x18 to 0xa1 returns below to 0x31. Looks like status of aux devices. +Retrieve poll 0x53 +Reply ack w/ command 0x3f 0x18. (0x18 is command) +Get a massive packet back, of aux status + +Filter pump does not effect the below. +Heater on/off does not effect below. +HEater setpoints does not effect. +Only Aux on/off seem to effect the status. + +4th bit tells you where to start, + after start 4 bits are status + last bit of status tell you chars in label. + after label repeat start 4 bits. + +For Aux1 10th bit 0=off 1=on 11 to 14 15 to 19=name + Aux2 19th + Aux3 28 + Aux4 37 + +In Below Aux 3 color light / Aux 4 dimmer / Aux 5 color light (different type to aux3) + +Aux 1 off / Aux 3 on + HEX: 0x10|0x02|0x31|0x72|0x05|0x01|0x02|0x03|0x04|0x05|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x01|0x07|0x02|0x03|0x04|0x41|0x75|0x78|0x33|0x00|0x01|0x01|0x00|0x04|0x41|0x75|0x78|0x34|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0xd5|0x10|0x03| +Dec | 16| 2| 49| 114| 5| 1| 2| 3| 4| 5| 0| 1| 0| 0| 4| 65| 117| 120| 49| 1| 1| 0| 0| 4| 65| 117| 120| 50| 1| 7| 2| 3| 4| 65| 117| 120| 51| 0| 1| 1| 0| 4| 65| 117| 120| 52| 0| 1| 0| 0| 4| 65| 117| 120| 53| 213| 16| 3 +Ascii | | | 1| r| | | | | | | | | | | | A| u| x| 1| | | | | | A| u| x| 2| | | | | | A| u| x| 3| | | | | | A| u| x| 4| | | | | | A| u| x| 5| | | + +Aux 1 on / Aux 3 on +| HEX: 0x10|0x02|0x31|0x72|0x05|0x01|0x02|0x03|0x04|0x05|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x01|0x07|0x02|0x03|0x04|0x41|0x75|0x78|0x33|0x00|0x01|0x01|0x00|0x04|0x41|0x75|0x78|0x34|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0xd6|0x10|0x03| +Dec | 16| 2| 49| 114| 5| 1| 2| 3| 4| 5| 1| 1| 0| 0| 4| 65| 117| 120| 49| 1| 1| 0| 0| 4| 65| 117| 120| 50| 1| 7| 2| 3| 4| 65| 117| 120| 51| 0| 1| 1| 0| 4| 65| 117| 120| 52| 0| 1| 0| 0| 4| 65| 117| 120| 53| 214| 16| 3 +Ascii | | | 1| r| | | | | | | | | | | | A| u| x| 1| | | | | | A| u| x| 2| | | | | | A| u| x| 3| | | | | | A| u| x| 4| | | | | | A| u| x| 5| | | + +Aux 1 off Aux3 to different light color +Hex |0x10|0x02|0x31|0x72|0x05|0x01|0x02|0x03|0x04|0x05|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x00|0x07|0x02|0x03|0x04|0x41|0x75|0x78|0x33|0x00|0x01|0x01|0x00|0x04|0x41|0x75|0x78|0x34|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0xd4|0x10|0x03| +Dec | 16| 2| 49| 114| 5| 1| 2| 3| 4| 5| 0| 1| 0| 0| 4| 65| 117| 120| 49| 1| 1| 0| 0| 4| 65| 117| 120| 50| 0| 7| 2| 3| 4| 65| 117| 120| 51| 0| 1| 1| 0| 4| 65| 117| 120| 52| 0| 1| 0| 0| 4| 65| 117| 120| 53| 212| 16| 3 +Ascii | | | 1| r| | | | | | | | | | | | A| u| x| 1| | | | | | A| u| x| 2| | | | | | A| u| x| 3| | | | | | A| u| x| 4| | | | | | A| u| x| 5| | | + + + +RS16 panel. + HEX: 0x10|0x02|0x31|0x72|0x0f|0x01|0x02|0x03|0x04|0x05|0x06|0x07|0x08|0x09|0x0a|0x0b|0x0c|0x0d|0x0e|0x0f|0x00|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x33|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x34|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x36|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x37|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x31|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x32|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x33|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x34|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x35|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x36|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x37|0x01|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x38|0x77|0x10|0x03| +Dec | 16| 2| 49| 114| 15| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15| 0| 1| 0| 0| 4| 65| 117| 120| 49| 1| 1| 0| 0| 4| 65| 117| 120| 50| 1| 1| 0| 0| 4| 65| 117| 120| 51| 1| 1| 0| 0| 4| 65| 117| 120| 52| 1| 1| 0| 0| 4| 65| 117| 120| 53| 1| 1| 0| 0| 4| 65| 117| 120| 54| 1| 1| 0| 0| 4| 65| 117| 120| 55| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 49| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 50| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 51| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 52| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 53| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 54| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 55| 1| 1| 0| 0| 6| 65| 117| 120| 32| 66| 56| 119| 16| 3 +Ascii | | | 1| r| | | | | | | | | | | | | | | | | | | | | | A| u| x| 1| | | | | | A| u| x| 2| | | | | | A| u| x| 3| | | | | | A| u| x| 4| | | | | | A| u| x| 5| | | | | | A| u| x| 6| | | | | | A| u| x| 7| | | | | | A| u| x| | B| 1| | | | | | A| u| x| | B| 2| | | | | | A| u| x| | B| 3| | | | | | A| u| x| | B| 4| | | | | | A| u| x| | B| 5| | | | | | A| u| x| | B| 6| | | | | | A| u| x| | B| 7| | | | | | A| u| x| | B| 8| w| | + +Hex |0x10|0x02|0x31|0x72| + +*/ + +/* Startup sequences + +RS16 combo +Debug: RS Serial: Read Jandy packet To 0xa1 of type Probe | HEX: 0x10|0x02|0xa1|0x00|0xb3|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x61' | HEX: 0x10|0x02|0xa1|0x61|0x00|0x00|0x00|0x01|0x00|0x1d|0x32|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x61|0x00|0x74|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x50' | HEX: 0x10|0x02|0xa1|0x50|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x23|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x50|0x00|0x63|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x51' | HEX: 0x10|0x02|0xa1|0x51|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x00|0xa2|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x51|0x00|0x64|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x59' | HEX: 0x10|0x02|0xa1|0x59|0x00|0x0c|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x59|0x00|0x6c|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x52' | HEX: 0x10|0x02|0xa1|0x52|0x00|0x05|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x52|0x00|0x65|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type iAqalnk Poll | HEX: 0x10|0x02|0xa1|0x53|0x06|0x10|0x03| + +RS8 Combo rev T.2 +Debug: RS Serial: Read Jandy packet To 0xa1 of type Probe | HEX: 0x10|0x02|0xa1|0x00|0xb3|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x61' | HEX: 0x10|0x02|0xa1|0x61|0x00|0x00|0x00|0x01|0x00|0x1d|0x32|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x61|0x00|0x74|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x50' | HEX: 0x10|0x02|0xa1|0x50|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x23|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x50|0x00|0x63|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x51' | HEX: 0x10|0x02|0xa1|0x51|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x00|0xa2|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x51|0x00|0x64|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x59' | HEX: 0x10|0x02|0xa1|0x59|0x00|0x0c|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x59|0x00|0x6c|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x52' | HEX: 0x10|0x02|0xa1|0x52|0x00|0x05|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x52|0x00|0x65|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type iAqalnk Poll | HEX: 0x10|0x02|0xa1|0x53|0x06|0x10|0x03| + +RS4 rev Yg +Notice: Serial Log:Read Jandy packet To 0xa3 of type Probe | HEX: 0x10|0x02|0xa3|0x00|0xb5|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x61' | HEX: 0x10|0x02|0xa3|0x61|0x00|0x00|0x00|0x04|0x00|0x27|0x41|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x61|0x00|0x74|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x50' | HEX: 0x10|0x02|0xa3|0x50|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x25|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x50|0x00|0x63|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x51' | HEX: 0x10|0x02|0xa3|0x51|0x00|0x06|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x51|0x00|0x64|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x59' | HEX: 0x10|0x02|0xa3|0x59|0x00|0x0e|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x59|0x00|0x6c|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x52' | HEX: 0x10|0x02|0xa3|0x52|0x00|0x07|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x52|0x00|0x65|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0xa3 of type Unknown '0x53' | HEX: 0x10|0x02|0xa3|0x53|0x08|0x10|0x03| +Notice: Serial Log:Read Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x3f|0x00|0x52|0x10|0x03| + +RS6 rev T2 RS8 (home) +Debug: RS Serial: Read Jandy packet To 0xa1 of type Probe | HEX: 0x10|0x02|0xa1|0x00|0xb3|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x61' | HEX: 0x10|0x02|0xa1|0x61|0x00|0x00|0x00|0x01|0x00|0x1d|0x32|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x61|0x00|0x74|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x50' | HEX: 0x10|0x02|0xa1|0x50|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x20|0x00|0x23|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x50|0x00|0x63|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x51' | HEX: 0x10|0x02|0xa1|0x51|0x31|0x42|0x41|0x36|0x32|0x38|0x32|0x35|0x42|0x37|0x43|0x36|0x39|0x41|0x34|0x43|0x00|0xa2|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x51|0x00|0x64|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x59' | HEX: 0x10|0x02|0xa1|0x59|0x01|0x0d|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x59|0x00|0x6c|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type Unknown '0x52' | HEX: 0x10|0x02|0xa1|0x52|0x03|0x08|0x10|0x03| +Debug: RS Serial: Write Jandy packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x52|0x00|0x65|0x10|0x03| +Debug: RS Serial: Read Jandy packet To 0xa1 of type iAqalnk Poll | HEX: 0x10|0x02|0xa1|0x53|0x06|0x10|0x03| +*/ + + +/* + + +0x10|0x02|0x31|0x72|0x0f|0x01|0x02|0x03|0x04|0x05|0x06|0x07|0x08|0x09|0x0a|0x0b|0x0c|0x0d|0x0e|0x0f|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x31|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x32|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x33|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x34|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x35|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x36|0x01|0x01|0x00|0x00|0x04|0x41|0x75|0x78|0x37|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x31|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x32|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x33|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x34|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x35|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x36|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x37|0x00|0x01|0x00|0x00|0x06|0x41|0x75|0x78|0x20|0x42|0x38|0x70|0x10|0x03| + + +Only panel (RS8) +Air index 3 type 15 (pump off) +Air index 3 type 14 (pump off) +Air index 3 type 8 (pump on) +Water index 5 type 15 (pump on) +Temp2 ndex 8 type 20 +always 1 | index=4 type=(15 0x0f) + +Comb0 +Spa setpoint index 8 type 14 +Air index 8 type 26 +*/ + + + +/* + +Pump RPM + +All taken from panel Yg, but only heater setpoints seem to work. +Only setpoints seem to work, + +RPM to 2750 +Bit 6 = 0x5e +Bit 10 * 256 + Bit 11 +Bit 7 or 9 probably pump index. +HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0a|0xbe|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xd5|0x10|0x03| + +RPM to 2995 +HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x0b|0xb3|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xcb|0x10|0x03| + + +Below is setting RPM to 2505 + +packet To 0xa3 of type iAqalnk Poll | HEX: 0x10|0x02|0xa3|0x53|0x08|0x10|0x03| +packet To 0x00 of type Ack w/ Command | HEX: 0x10|0x02|0x00|0x01|0x3f|0x20|0x72|0x10|0x03| +packet To 0x33 of type iAq Poll | HEX: 0x10|0x02|0x33|0x30|0x75|0x10|0x03| +packet To 0xa3 of type Unknown '0x73' | HEX: 0x10|0x02|0xa3|0x73|0x28|0x10|0x03| +packet To 0x00 of type iAqualnk sendCmd | HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x5e|0x04|0x00|0x01|0x09|0xc9|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xdf|0x10|0x03| +packet To 0x33 of type iAq Poll | HEX: 0x10|0x02|0x33|0x30|0x75|0x10|0x03| +packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| +packet To 0x33 of type iAq 1Tch status | HEX: 0x10|0x02|0x33|0x71|0x07|0x01|0x02|0x03|0x04|0x05|0x0f|0x12|0x00|0x07|0x41|0x6c|0x6c|0x20|0x4f|0x46|0x46|0x00|0x08|0x53|0x70|0x61|0x20|0x4d|0x6f|0x64|0x65|0x00|0x0a|0x43|0x6c|0x65|0x61|0x6e|0x20|0x4d|0x6f|0x64|0x65|0x00|0x08|0x42|0x75|0x62|0x62|0x6c|0x65|0x72|0x73|0x00|0x0a|0x57|0x61|0x74|0x65|0x72|0x66|0x61|0x6c|0x6c|0x31|0x04|0x09|0xc9|0x0d|0x7a|0x06|0xa4|0x0a|0xbe|0x08|0xca|0x08|0xca|0x0a|0xbe|0x0a|0xbe|0x05|0xdc|0x04|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x6a|0x10|0x03| +All OFF = Off | index 0 type=(01 0x01) status=0x00 start=12 length=7 +Spa Mode = Off | index 1 type=(02 0x02) status=0x00 start=21 length=8 +Clean Mode = Off | index 2 type=(03 0x03) status=0x00 start=31 length=10 +Bubblers = Off | index 3 type=(04 0x04) status=0x00 start=43 length=8 +Waterfall1 = Off | index 4 type=(05 0x05) status=0x00 start=53 length=10 +*** RPM is in the next bytes from iAq 1Tch status. But can't tell how to pull them since SWG is also here as well. **** + +*/ + +/* +SWG + +SWG 50% +Byte 6 = 0x19 +Byte 7 = 50% +Byte 9 & 10 ???? +HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x32|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x0e|0x10|0x03| + +SWG 51% +Byte 7 = 51% +HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x33|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x0f|0x10|0x03| + + +Below is set SWG to 35 + +packet To 0xa3 of type iAqalnk Poll | HEX: 0x10|0x02|0xa3|0x53|0x08|0x10|0x03| +packet To 0x00 of type Ack w/ Command | HEX: 0x10|0x02|0x00|0x01|0x3f|0x20|0x72|0x10|0x03| +packet To 0x33 of type iAq Poll | HEX: 0x10|0x02|0x33|0x30|0x75|0x10|0x03| +packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| +packet To 0xa3 of type Unknown '0x73' | HEX: 0x10|0x02|0xa3|0x73|0x28|0x10|0x03| +packet To 0x00 of type iAqualnk sendCmd | HEX: 0x10|0x02|0x00|0x24|0x73|0x01|0x19|0x23|0x00|0x18|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0xff|0x10|0x03| +packet To 0x33 of type iAq Poll | HEX: 0x10|0x02|0x33|0x30|0x75|0x10|0x03| +packet To 0x00 of type Ack | HEX: 0x10|0x02|0x00|0x01|0x00|0x00|0x13|0x10|0x03| +packet To 0x33 of type iAq 1Tch status | HEX: 0x10|0x02|0x33|0x71|0x07|0x01|0x02|0x03|0x04|0x05|0x12|0x20|0x00|0x07|0x41|0x6c|0x6c|0x20|0x4f|0x46|0x46|0x00|0x08|0x53|0x70|0x61|0x20|0x4d|0x6f|0x64|0x65|0x00|0x0a|0x43|0x6c|0x65|0x61|0x6e|0x20|0x4d|0x6f|0x64|0x65|0x00|0x08|0x42|0x75|0x62|0x62|0x6c|0x65|0x72|0x73|0x00|0x0a|0x57|0x61|0x74|0x65|0x72|0x66|0x61|0x6c|0x6c|0x31|0x04|0x01|0x00|0x00|0x00|0x00|0x00|0x00|0x00|0x23|0x00|0x00|0x18|0x00|0x00|0x01|0x00|0xd3|0x10|0x03| +All OFF = Off | index 0 type=(01 0x01) status=0x00 start=12 length=7 +Spa Mode = Off | index 1 type=(02 0x02) status=0x00 start=21 length=8 +Clean Mode = Off | index 2 type=(03 0x03) status=0x00 start=31 length=10 +Bubblers = Off | index 3 type=(04 0x04) status=0x00 start=43 length=8 +Waterfall1 = Off | index 4 type=(05 0x05) status=0x00 start=53 length=10 +*** SWG is in the next bytes from iAq 1Tch status. But can't tell how to pull them since RPM is also here as well. **** + */ \ No newline at end of file diff --git a/source/json_messages.c b/source/json_messages.c index c8dafa3..a334c31 100644 --- a/source/json_messages.c +++ b/source/json_messages.c @@ -252,12 +252,13 @@ char *get_aux_information(aqkey *button, struct aqualinkdata *aqdata, char *buff //printf("Button %s is VSP\n", button->name); for (i=0; i < aqdata->num_pumps; i++) { if (button == aqdata->pumps[i].button) { - length += sprintf(buffer, ",\"type_ext\":\"switch_vsp\",\"Pump_RPM\":\"%d\",\"Pump_GPM\":\"%d\",\"Pump_Watts\":\"%d\",\"Pump_Type\":\"%s\",\"Pump_Status\":\"%d\"", + length += sprintf(buffer, ",\"type_ext\":\"switch_vsp\",\"Pump_RPM\":\"%d\",\"Pump_GPM\":\"%d\",\"Pump_Watts\":\"%d\",\"Pump_Type\":\"%s\",\"Pump_Status\":\"%d\",\"Pump_Speed\":\"%d\"", aqdata->pumps[i].rpm, aqdata->pumps[i].gpm, aqdata->pumps[i].watts, (aqdata->pumps[i].pumpType==VFPUMP?"vfPump":(aqdata->pumps[i].pumpType==VSPUMP?"vsPump":"ePump")), - getPumpStatus(i, aqdata)); + getPumpStatus(i, aqdata), + getPumpSpeedAsPercent(&aqdata->pumps[i])); return buffer; } @@ -268,7 +269,17 @@ char *get_aux_information(aqkey *button, struct aqualinkdata *aqdata, char *buff //printf("Button %s is ProgramableLight\n", button->name); for (i=0; i < aqdata->num_lights; i++) { if (button == aqdata->lights[i].button) { - length += sprintf(buffer, ",\"type_ext\": \"switch_program\", \"Light_Type\":\"%d\"", aqdata->lights[i].lightType); + if (aqdata->lights[i].lightType == LC_DIMMER2) { + length += sprintf(buffer, ",\"type_ext\": \"light_dimmer\", \"Light_Type\":\"%d\", \"Light_Program\":\"%d\", \"Program_Name\":\"%d%%\" ", + aqdata->lights[i].lightType, + aqdata->lights[i].currentValue, + aqdata->lights[i].currentValue); + } else { + length += sprintf(buffer, ",\"type_ext\": \"switch_program\", \"Light_Type\":\"%d\", \"Light_Program\":\"%d\", \"Program_Name\":\"%s\" ", + aqdata->lights[i].lightType, + aqdata->lights[i].currentValue, + light_mode_name(aqdata->lights[i].lightType, aqdata->lights[i].currentValue, ALLBUTTON)); + } return buffer; } } @@ -294,6 +305,7 @@ int build_device_JSON(struct aqualinkdata *aqdata, char* buffer, int size, bool bool homekit_f = (homekit && ( aqdata->temp_units==FAHRENHEIT || aqdata->temp_units == UNKNOWN) ); length += sprintf(buffer+length, "{\"type\": \"devices\""); + length += sprintf(buffer+length, ",\"aqualinkd_version\":\"%s\"",AQUALINKD_VERSION);//"09/01/16 THU", length += sprintf(buffer+length, ",\"date\":\"%s\"",aqdata->date );//"09/01/16 THU", length += sprintf(buffer+length, ",\"time\":\"%s\"",aqdata->time );//"1:16 PM", if ( aqdata->temp_units == FAHRENHEIT ) @@ -718,7 +730,11 @@ printf("Pump Type %d\n",aqdata->pumps[i].pumpType); length += sprintf(buffer+length, ",\"light_program\":{" ); for (i=0; i < aqdata->num_lights; i++) { + if (aqdata->lights[i].lightType == LC_DIMMER2) { + length += sprintf(buffer+length, "\"%s\": \"%d%%\",", aqdata->lights[i].button->name, aqdata->lights[i].currentValue ); + } else { length += sprintf(buffer+length, "\"%s\": \"%s\",", aqdata->lights[i].button->name, light_mode_name(aqdata->lights[i].lightType, aqdata->lights[i].currentValue, RSSADAPTER) ); + } } if (buffer[length-1] == ',') length--; diff --git a/source/net_services.c b/source/net_services.c index d3d51fe..93830ba 100644 --- a/source/net_services.c +++ b/source/net_services.c @@ -956,7 +956,21 @@ void mqtt_broadcast_aqualinkstate(struct mg_connection *nc) send_mqtt_aux_msg(nc, _aqualink_data->lights[i].button->name, LIGHT_PROGRAM_TOPIC, _aqualink_data->lights[i].currentValue); sprintf(topic, "%s%s/name", _aqualink_data->lights[i].button->name, LIGHT_PROGRAM_TOPIC); - send_mqtt_string_msg(nc, topic, light_mode_name(_aqualink_data->lights[i].lightType, _aqualink_data->lights[i].currentValue, ALLBUTTON)); + if (_aqualink_data->lights[i].lightType == LC_DIMMER2) { + char message[30]; + sprintf(message, "%d%%", _aqualink_data->lights[i].currentValue); + send_mqtt_string_msg(nc, topic, message); + } else { + send_mqtt_string_msg(nc, topic, light_mode_name(_aqualink_data->lights[i].lightType, _aqualink_data->lights[i].currentValue, ALLBUTTON)); + } + /* + if (_aqualink_data->lights[i].lightType == LC_DIMMER) { + sprintf(topic, "%s%s", _aqualink_data->lights[i].button->name, LIGHT_DIMMER_VALUE_TOPIC); + send_mqtt_int_msg(nc, topic, _aqualink_data->lights[i].currentValue * 25); + } else*/ if (_aqualink_data->lights[i].lightType == LC_DIMMER2) { + sprintf(topic, "%s%s", _aqualink_data->lights[i].button->name, LIGHT_DIMMER_VALUE_TOPIC); + send_mqtt_int_msg(nc, topic, _aqualink_data->lights[i].currentValue); + } } } } @@ -1272,6 +1286,22 @@ uriAtype action_URI(request_source from, const char *URI, int uri_length, float LOG(NET_LOG,LOG_WARNING, "%s: Didn't find device that matched URI '%.*s'\n",actionName[from], uri_length, URI); rtn = uBad; } + } else if ((ri3 != NULL && (strncasecmp(ri2, "brightness", 10) == 0) && (strncasecmp(ri3, "set", 3) == 0))) { + found = false; + for (i=0; i < _aqualink_data->total_buttons; i++) { + if (strncmp(ri1, _aqualink_data->aqbuttons[i].name, strlen(_aqualink_data->aqbuttons[i].name)) == 0 || + strncmp(ri1, _aqualink_data->aqbuttons[i].label, strlen(_aqualink_data->aqbuttons[i].label)) == 0) + { + found = true; + panel_device_request(_aqualink_data, LIGHT_BRIGHTNESS, i, value, from); + break; + } + } + if(!found) { + *rtnmsg = NO_PLIGHT_DEVICE; + LOG(NET_LOG,LOG_WARNING, "%s: Didn't find device that matched URI '%.*s'\n",actionName[from], uri_length, URI); + rtn = uBad; + } // Action a pump RPM/GPM message } else if ((ri3 != NULL && ((strncasecmp(ri2, "RPM", 3) == 0) || (strncasecmp(ri2, "GPM", 3) == 0) || (strncasecmp(ri2, "Speed", 5) == 0) || (strncasecmp(ri2, "VSP", 3) == 0)) && (strncasecmp(ri3, "set", 3) == 0))) { found = false; diff --git a/source/serialadapter.c b/source/serialadapter.c index f343169..bee8f0b 100644 --- a/source/serialadapter.c +++ b/source/serialadapter.c @@ -138,7 +138,8 @@ void set_aqualink_rssadapter_aux_extended_state(const aqkey *button, const unsig LOG(RSSA_LOG,LOG_DEBUG, "Sending 0x%02hhx to %s\n",state, button->label); - rssadapter_device_state(button->rssd_code, state); + rssadapter_device_state(button->rssd_code, state); // Set state + rssadapter_device_state(button->rssd_code, 0x00); // 0x00 meand Get curent state (for color lights the return state is 0) } void set_aqualink_rssadapter_aux_state(const aqkey *button, bool turnOn) @@ -146,7 +147,12 @@ void set_aqualink_rssadapter_aux_state(const aqkey *button, bool turnOn) LOG(RSSA_LOG,LOG_DEBUG, "Turning button %s %s\n",button->label,(turnOn?"On":"Off")); rssadapter_device_state( button->rssd_code, (turnOn?RS_SA_ON:RS_SA_OFF) ); + + // NOTE. If we turn off AUX1 and get this return HEX: 0x10|0x02|0x48|0x13|0x02|0x00|0x0e|0x15|0x92|0x10|0x03| + // The 0x0e means some from of oiption is set (ie cleaner). Maybe try to turn cleaner off instead 0x15 is aux1 1x10 is cleaner. } + + /* void set_aqualink_rssadapter_aux_state(int buttonIndex, bool turnOn) { @@ -352,19 +358,19 @@ bool process_rssadapter_packet(unsigned char *packet, int length, struct aqualin aq_data->lights[i].button->rssd_code == packet[7] ) { // CHANGE TO DEBUG BEFORE RELEASE - if (aq_data->lights[i].lightType != LC_DIMMER) { - LOG(RSSA_LOG,LOG_DEBUG,"ColorLight '%s' is %s 0x%02hhx value name '%s'\n", + if (aq_data->lights[i].lightType == LC_DIMMER || aq_data->lights[i].lightType == LC_DIMMER2) { + LOG(RSSA_LOG,LOG_DEBUG,"DimmerLight '%s' is %s 0x%02hhx value '%d'%%\n", aq_data->lights[i].button->label, packet[6]==0x00?"OFF":"ON", packet[6], - packet[6]==0x00?"--":light_mode_name( aq_data->lights[i].lightType,(packet[6] - RSSD_COLOR_LIGHT_OFFSET), RSSADAPTER) ); - } else if (aq_data->lights[i].lightType == LC_DIMMER) { - LOG(RSSA_LOG,LOG_DEBUG,"DimmerLight '%s' is %s 0x%02hhx value '%d'%%\n", + packet[6]==0x00?0:(packet[6] - RSSD_DIMMER_LIGHT_OFFSET)); + }else{ + LOG(RSSA_LOG,LOG_DEBUG,"ColorLight '%s' is %s 0x%02hhx value name '%s'\n", aq_data->lights[i].button->label, packet[6]==0x00?"OFF":"ON", packet[6], - packet[6]==0x00?0:(packet[6] - RSSD_DIMMER_LIGHT_OFFSET)); - } + packet[6]==0x00?"--":light_mode_name( aq_data->lights[i].lightType,(packet[6] - RSSD_COLOR_LIGHT_OFFSET), RSSADAPTER) ); + } aq_data->lights[i].RSSDstate = (packet[6]==0x00?OFF:ON); #ifdef CLIGHT_PANEL_FIX @@ -377,13 +383,24 @@ bool process_rssadapter_packet(unsigned char *packet, int length, struct aqualin aq_data->lights[i].button->led->state==OFF?"OFF":"ON"); } aq_data->lights[i].button->led->state = aq_data->lights[i].RSSDstate; -#endif - // Set the color index. (packet[6] - RSSD_COLOR_LIGHT_OFFSET)-1 - if (aq_data->lights[i].lightType != LC_DIMMER) { +#endif + switch(aq_data->lights[i].lightType) { + case LC_DIMMER: + set_currentlight_value(&aq_data->lights[i], (packet[6] - RSSD_DIMMER_LIGHT_OFFSET) / 25); + break; + case LC_DIMMER2: + set_currentlight_value(&aq_data->lights[i], (packet[6] - RSSD_DIMMER_LIGHT_OFFSET)); + break; + default: + set_currentlight_value(&aq_data->lights[i], (packet[6] - RSSD_COLOR_LIGHT_OFFSET)); + break; + } + /* + if (aq_data->lights[i].lightType != LC_DIMMER ) { set_currentlight_value(&aq_data->lights[i], (packet[6] - RSSD_COLOR_LIGHT_OFFSET)); } else if (aq_data->lights[i].lightType == LC_DIMMER) { set_currentlight_value(&aq_data->lights[i], (packet[6] - RSSD_DIMMER_LIGHT_OFFSET) / 25); - } + }*/ } } diff --git a/source/version.h b/source/version.h index 57772a2..8a7da6c 100644 --- a/source/version.h +++ b/source/version.h @@ -2,4 +2,6 @@ #define AQUALINKD_NAME "Aqualink Daemon" #define AQUALINKD_SHORT_NAME "AqualinkD" -#define AQUALINKD_VERSION "2.4.1 (Dev 0.2)" + +// Use Magor . Minor . Patch +#define AQUALINKD_VERSION "2.5.0 (Dev 0.1)" diff --git a/web/controller.html b/web/controller.html index b032f35..6532a4c 100644 --- a/web/controller.html +++ b/web/controller.html @@ -640,6 +640,7 @@ document.getElementById('vspswitch_options').classList.remove("hide"); document.getElementById('timer_options').classList.remove("hide"); document.getElementById('scheduler_options').classList.remove("hide"); + document.getElementById('dimmerlight_options').classList.remove("hide"); //document.getElementById('simulator_iframe').classList.remove("hide"); setColors(); load_background(); @@ -915,7 +916,8 @@ subdiv.setAttribute('id', id + '_status'); subdiv.textContent = formatSatus(status); div.appendChild(subdiv); - if (type == "switch" && (subtype != "switch_program" && subtype != "switch_vsp" && subtype != "switch_timer") ) { + if (type == "switch" && (subtype != "switch_program" && subtype != "switch_vsp" && + subtype != "switch_timer" && subtype != "light_dimmer") ) { //if (type == "switch" && subtype != "switch_program" ) { div.setAttribute('onclick', "switchTileState('" + id + "')"); //console.log("add onclick switchtilestate to "+id); @@ -957,6 +959,7 @@ send_setpoint(id); } + /* function setTileValue(id, value) { var ext = ''; @@ -1028,7 +1031,8 @@ function setTileOnText(id, text) { try { - if (document.getElementById(id).getAttribute('status') == 'on') { + var tile = document.getElementById(id); + if (tile.getAttribute('status') == 'on' || tile.getAttribute('status') == 'enabled') { document.getElementById(id + '_status').innerHTML = text; } else { //console.log("Tile "+id+" status is '"+document.getElementById(id).getAttribute('status')+"' not setting text to '"+text+"'"); @@ -1227,7 +1231,7 @@ add_tile(object.id, object.name, object.state, 'switch', ext_type, 'hk/' + img + '-off.png', 'hk/' + img + '-on.png'); setTileOn(object.id, object.status, null); - if (typeof object.type_ext !== 'undefined' && object.type_ext == 'switch_program') { + if (typeof object.type_ext !== 'undefined' && (object.type_ext == 'switch_program' || object.type_ext == 'light_dimmer')) { if (typeof object.Light_Type !== 'undefined') { document.getElementById(object.id).setAttribute('lighttype', object.Light_Type); } @@ -1276,6 +1280,7 @@ document.getElementById('vspswitch_options').style.display = 'none'; document.getElementById('timer_options').style.display = 'none'; document.getElementById('scheduler_options').style.display = 'none'; + document.getElementById('dimmerlight_options').style.display = 'none'; //document.getElementById('simulator_iframe').style.display = 'none'; } else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_program') { active_option = document.getElementById('pswitch_options'); @@ -1284,6 +1289,16 @@ document.getElementById('vspswitch_options').style.display = 'none'; document.getElementById('timer_options').style.display = 'none'; document.getElementById('scheduler_options').style.display = 'none'; + document.getElementById('dimmerlight_options').style.display = 'none'; + //document.getElementById('simulator_iframe').style.display = 'none'; + } else if (id != null && document.getElementById(id).getAttribute('type') == 'light_dimmer') { + active_option = document.getElementById('dimmerlight_options'); + document.getElementById('thermostat_options').style.display = 'none'; + document.getElementById('swg_options').style.display = 'none'; + document.getElementById('vspswitch_options').style.display = 'none'; + document.getElementById('timer_options').style.display = 'none'; + document.getElementById('scheduler_options').style.display = 'none'; + document.getElementById('dimmerlight_options').style.display = 'none'; //document.getElementById('simulator_iframe').style.display = 'none'; } else if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_swg') { active_option = document.getElementById('swg_options'); @@ -1292,6 +1307,7 @@ document.getElementById('vspswitch_options').style.display = 'none'; document.getElementById('timer_options').style.display = 'none'; document.getElementById('scheduler_options').style.display = 'none'; + document.getElementById('dimmerlight_options').style.display = 'none'; //document.getElementById('simulator_iframe').style.display = 'none'; } else if (id != null && document.getElementById(id).getAttribute('type') == 'setpoint_freeze') { active_option = document.getElementById('swg_options'); @@ -1300,6 +1316,7 @@ document.getElementById('vspswitch_options').style.display = 'none'; document.getElementById('timer_options').style.display = 'none'; document.getElementById('scheduler_options').style.display = 'none'; + document.getElementById('dimmerlight_options').style.display = 'none'; //document.getElementById('simulator_iframe').style.display = 'none'; } else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_vsp') { active_option = document.getElementById('vspswitch_options'); @@ -1308,6 +1325,7 @@ document.getElementById('swg_options').style.display = 'none'; document.getElementById('timer_options').style.display = 'none'; document.getElementById('scheduler_options').style.display = 'none'; + document.getElementById('dimmerlight_options').style.display = 'none'; //document.getElementById('simulator_iframe').style.display = 'none'; } else if (id != null && document.getElementById(id).getAttribute('type') == 'switch_timer') { active_option = document.getElementById('timer_options'); @@ -1316,6 +1334,7 @@ document.getElementById('swg_options').style.display = 'none'; document.getElementById('vspswitch_options').style.display = 'none'; document.getElementById('scheduler_options').style.display = 'none'; + document.getElementById('dimmerlight_options').style.display = 'none'; //document.getElementById('simulator_iframe').style.display = 'none'; } else if (id != null && document.getElementById(id).getAttribute('type') == 'scheduler') { active_option = document.getElementById('scheduler_options'); @@ -1324,6 +1343,7 @@ document.getElementById('swg_options').style.display = 'none'; document.getElementById('vspswitch_options').style.display = 'none'; document.getElementById('timer_options').style.display = 'none'; + document.getElementById('dimmerlight_options').style.display = 'none'; //document.getElementById('simulator_iframe').style.display = 'none'; } /*else if (id != null && document.getElementById(id).getAttribute('type') == 'simulator') { active_option = document.getElementById('simulator_iframe'); @@ -1361,6 +1381,8 @@ document.getElementById("timer_options").click(); else if (document.getElementById('scheduler_options').style.display == 'flex') document.getElementById("scheduler_options").click(); + else if (document.getElementById('dimmerlight_options').style.display == 'flex') + document.getElementById("dimmerlight_options").click(); } document.getElementById('thermostat_options').style.display = 'none'; document.getElementById('swg_options').style.display = 'none'; @@ -1368,6 +1390,7 @@ document.getElementById('vspswitch_options').style.display = 'none'; document.getElementById('timer_options').style.display = 'none'; document.getElementById('scheduler_options').style.display = 'none'; + document.getElementById('dimmerlight_options').style.display = 'none'; //document.getElementById('simulator_iframe').style.display = 'none'; document.getElementById('wrapper').classList.remove("opaque"); return; @@ -1388,6 +1411,7 @@ var tm_ext; var oswitch; var vsp_slider_changed = false; + var dimmer_slider_changed = false; if (type == 'setpoint_swg') { slider = document.getElementById("swg_option_slider_range"); slider_output = document.getElementById("swg_option_slider_text_value"); @@ -1424,6 +1448,14 @@ close_button = document.getElementById("scheduler_options_close"); //} else if (type == 'simulator') { // close_button = document.getElementById("simulator_iframe_close"); + } else if (type == 'light_dimmer') { + slider = document.getElementById("dimmeroption_slider_range"); + slider_output = document.getElementById("dimmeroption_slider_text_value"); + tm_slider = document.getElementById("dimmer_timer_slider_range"); + tm_slider_output = document.getElementById("dimmer_timer_slider_text_value"); + title = document.getElementById("dimmerswitch_option_title"); + close_button = document.getElementById("dimmerswitch_option_close"); + ext = "%"; } else { slider = document.getElementById("option_slider_range"); slider_output = document.getElementById("option_slider_text_value"); @@ -1472,6 +1504,11 @@ slider.step = 5; ext = ' RPM'; } + } else if (type == 'light_dimmer') { + slider.min = 0; + slider.max = 100; + slider.step = 1; + ext = ' %'; } if (type == 'scheduler') { @@ -1479,6 +1516,7 @@ } else if (type == 'simulator') { // title.innerHTML = "Simulator"; } else { + //console.log("Set "+id+" to "+document.getElementById(id + '_name').innerHTML); title.innerHTML = document.getElementById(id + '_name').innerHTML; } @@ -1532,6 +1570,24 @@ oswitch.onclick = function() { oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off"); } + } else if (type == 'light_dimmer') { + slider.value = sp_value; + oswitch = document.getElementById("dimmeroption_switch"); + oswitch.checked = tile_state; + var oswitch_output = document.getElementById("dimmeroption_switch_text_value"); + slider_output.innerHTML = slider.value + ext; + oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off"); + slider.oninput = function() { + dimmer_slider_changed = true; + slider_output.innerHTML = this.value + ext; + if (this.value <= 0 && oswitch.checked == true) { + oswitch.checked = false; + oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off"); + } else if (oswitch.checked != true) { + oswitch.checked = true; + oswitch_output.innerHTML = ((oswitch.checked) ? "On" : "Off"); + } + } } else if (type == 'switch_timer') { oswitch = document.getElementById("timer_switch"); oswitch.checked = tile_state; @@ -1630,6 +1686,12 @@ // if (state == (tile.getAttribute('status') == 'off')) // Only bother with this if we didn;t set the light mode. setTileState(id, state); } + } else if (type == 'light_dimmer') { + var value = slider.value; + if (state == (tile.getAttribute('status') == 'off')) + setTileState(id, state); + if (sp_value != slider.value && dimmer_slider_changed == true) + setThermostatSetpoint(id, slider.value) } else if (type == 'setpoint_swg') { //console.log ("Boost attribute = "+tile.getAttribute('boost')); //console.log ("state = "+state); @@ -2162,26 +2224,32 @@ } for (var obj in data.timers) { setTileOnText(obj.toString(),"On (timer)"); + //console.log("TIMER "+obj.toString()); } for (var obj in data.timer_durations) { setTileOnText(obj.toString(),"Timer "+toHoursAndMinutes(data.timer_durations[obj])); + //console.log("TIMER "+obj.toString()+" duration "+data.timer_durations[obj]); } for (var obj in data.light_program) { if (data.light_program[obj] != "") { var light_mode = data.light_program[obj]; - - // If aqualinkd probrammed light, need to get convert int to text index, if not value is text + // If aqualinkd programmed light, need to convert int to text index, if not value is text try { - var light_type = document.getElementById(obj.toString()).getAttribute('lighttype') + var light_type = document.getElementById(obj.toString()).getAttribute('lighttype'); if (light_type == 0) { var light_mode = _light_program[light_type][parseInt(data.light_program[obj])-1]; if (light_mode.endsWith(" - Show")) light_mode = light_mode.slice(0, -7); + //console.log("light program -- "+light_mode); + } else if (light_type == 10 || light_type == 11) { + // Fo Dimmer Lights. + document.getElementById(obj.toString()).setAttribute('setpoint', parseInt(light_mode)); } } catch (e) {} setTileOnText(obj.toString(),light_mode); + // Below is only needed for full dimmer } } @@ -2430,6 +2498,8 @@ message.uri = id+"/percent/set"; else if (type == "switch_vsp") message.uri = id+"/RPM/set"; + else if (type == "light_dimmer") + message.uri = id+"/brightness/set"; else message.uri = id+"/setpoint/set"; //console.log("Send value back "+temperature.parameter+" "+temperature.value); @@ -2543,6 +2613,7 @@ +
+ + + + + +