Jandy Infinite Water Colors: full iAqualink control (on/off, brightness, color mode, RGB)#526
Open
knap1930 wants to merge 35 commits into
Open
Jandy Infinite Water Colors: full iAqualink control (on/off, brightness, color mode, RGB)#526knap1930 wants to merge 35 commits into
knap1930 wants to merge 35 commits into
Conversation
…ite Water Colors light When enable_iaqualink=yes, LC_JANDYINFINATE now uses direct iAqualink commands instead of the slower AqualinkTouch UI-navigation path: - Color mode: new AQ_SET_IAQLINK_LIGHTCOLOR_MODE dispatches via set_iaqualink_light_colormode - Brightness: new AQ_SET_IAQLINK_LIGHT_BRIGHTNESS dispatches via set_iaqualink_light_brightness; value=0 turns the light off via set_iaqualink_aux_state; LC_JANDYINFINATE is now allowed through the brightness gate in programDeviceLightBrightness - RGB: new AQ_SET_IAQLINK_LIGHT_RGB dispatches via set_iaqualink_light_rgb (R/G/B packed as (r<<16)|(g<<8)|b); MQTT /rgb/set topic accepts "r,g,b" payloads; pre-parsed in action_mqtt_message before passing to action_URI MQTT discovery updated: LC_JANDYINFINATE now emits a brightness+RGB light entity (HASSIO_DIMMER_RGB_DISCOVER) instead of a plain switch, alongside the existing color-preset selector entity. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…olors light - Add brightness, red, green, blue fields to clight_detail - devices_jandy.c: store brightness from 0x31 response byte[38] matched by lightID - aq_panel.c: store RGB optimistically on send (hardware response bytes for RGB still TBD) - net_services.c: publish brightness to /brightness and RGB to /rgb when values change Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…NATE - LOG_NOTICE marker in set_iaqualink_light_brightness so you can correlate when the command fires vs. subsequent iAqualink status packet changes - In CMD_IAQ_AUX_STATUS handler: when a device entry matches an LC_JANDYINFINATE light label, dump the full raw entry bytes (+ 8 bytes after the label) at NOTICE level so we can see if brightness/RGB data trails each entry - Catch-all else branch logs any unknown iAqualink status packet command byte Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
bit4 (packet[status+3]) in CMD_IAQ_AUX_STATUS carries the current brightness (0-100) for LC_JANDYINFINATE lights. Store it in light->brightness and set is_dirty so net_services.c publishes the updated value to MQTT. Confirmed by hardware capture: 40% → 0x28, 90% → 0x5a. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ode byte Status+0 (bit1) is 0x06 for this light type rather than the expected 0x01 for on — it may carry the color mode. Logging all four bytes at NOTICE so the user can capture logs while cycling through color presets to identify the field. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cket Confirmed by hardware capture: packet[status+0] = color mode index (0=off, 1=Alpine White, 2=Sky Blue, …) packet[status+3] = brightness percent (0-100) Store both in clight_detail and set is_dirty to trigger MQTT publish. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rom 0x72 packet Hardware capture confirms: packet[status+0] = color mode index reported by the device 0x10 (16) = custom RGB color — device reports this when RGB command was used Add "Custom" at index 16 in the LC_JANDYINFINATE color array so the MQTT /program/name topic and HA color mode selector show "Custom" instead of an empty string when in custom RGB mode. RGB channel values (R/G/B) are NOT reported in the 0x72 status packet; the optimistic state stored at send time is the correct approach. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…B mode Helps locate where (if anywhere) the device reports back R/G/B values. Set a distinctive color, capture the log, and grep for the known byte values. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
logPacket exits early unless log level >= LOG_DEBUG_SERIAL; replace with a manual 16-bytes-per-row hex dump using LOG(IAQL_LOG, LOG_NOTICE) so the full packet appears in the notice log regardless of serial debug settings. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
RGB channel values are not reported back in the 0x72 status packet — confirmed by capturing full packet dumps across three different custom colors (red, green, blue) which produced identical packet bytes. Optimistic state (store at send time) is the correct approach. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… mode is encoded there Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pool Light is an aux device and doesn't appear in the 0x71 (1Touch) packet, so LED state was never being updated. packet[status+0]==0 means off, non-zero means on — update button->led->state from the 0x72 handler alongside the existing color mode and brightness updates. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three bugs fixed: 1. Remove hardcoded 'value = 3' debug leftover that overrode every color mode command to Cobalt Blue regardless of what was requested 2. Add iAqualink turn-on path for virtual button LC_JANDYINFINATE: USE_LAST_VALUE now uses AQ_SET_IAQLINK_LIGHTCOLOR_MODE with lastValue instead of falling through to the error "needs AqualinkTouch protocol" 3. Add iAqualink turn-off path for virtual button LC_JANDYINFINATE: value==0 now calls set_iaqualink_aux_state(button, false) instead of falling through to the same error Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CMD_IAQ_PAGE_BUTTON (0x24) packets written to master (dest 0x00) are the iAqualink command sends. Bypass the LOG_DEBUG_SERIAL early-exit guard and log them at NOTICE so they're visible without enabling serial debug logging. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two-part fix: 1. aq_serial.c send_packet: bypass the LOG_DEBUG_SERIAL gate so logPacketWrite is called for CMD_IAQ_PAGE_BUTTON (0x24) packets destined for master (0x00), which are the iAqualnk sendCmd packets 2. packetLogger.c _logPacket: bypass the early-exit and log at NOTICE level for the same packet type, so they appear in the normal notice log Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LOG_LARGEMSG silently drops messages if msg_level > getLogLevel(from). RSSD_LOG may be configured below NOTICE. Switch to IAQL_LOG for the iAqualnk sendCmd case so the level check passes against the right channel. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…htness save 1. aqualinkd.c: add LOG(IAQL_LOG, LOG_NOTICE) directly in the IAQUALNK case when a full (>2 byte) command is sent via send_jandy_command. This is a more reliable path than going through the packet-logger infrastructure (send_packet -> logPacketWrite -> _logPacket). 2. devices_jandy.c: restore the brightness update loop in processPacketFromJandyLight that was removed during RGB investigation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bypass the logging infrastructure entirely to confirm: 1. push_iaqualink_cmd: is the queue being populated when commands are sent? 2. caculate_ack_packet IAQUALNK case: is the dispatch case being reached, and what size does get_iaqualink_cmd return? These should appear on stderr regardless of log level configuration. Remove once the root cause is identified. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reverts the five commits that attempted to surface CMD_IAQ_PAGE_BUTTON (0x24) packets at NOTICE level. None of the approaches worked reliably: 056952d - packetLogger.c initial NOTICE changes f567753 - aq_serial.c gate bypass c14733b - packetLogger.c IAQL_LOG channel fix b46d2c0 - direct LOG in aqualinkd.c IAQUALNK dispatch f8bc4b9 - fprintf diagnostics Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LC_JANDYINFINATE lights are virtual buttons, which get rssd_code=NUL by default. iAqalnkDevID returns 0xFF for virtual buttons with NUL rssd_code because NUL doesn't match any RS_SA_* case in the switch. Fix: track the entry index in the 0x72 AUX status packet loop. The bytes at packet[5 + entryIndex] are the IAQ device codes for each entry (same layout as the 0x71 1TOUCH_STATUS packet). On first match, store the code in button->rssd_code. iAqalnkDevID already returns rssd_code directly for virtual buttons with a non-NUL rssd_code (line 119-121). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…x72) The full 0x72 hex dump was added to hunt for RGB values in the packet. That investigation concluded RGB is not reported back. The dump code was left in and is causing crashes when in custom RGB mode (new_mode == 0x10). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This reverts commit 5002a04.
…vice code iAqalnkDevID now checks clight_detail->lightID for virtual PROGRAM_LIGHT buttons with lightType LC_JANDYINFINATE, so the device code comes from the user-configured `virtual_button_XX_lightID` rather than returning 0xFF (which caused "Couldn't find iaqualink keycode" errors). Also adds set_iaqualink_jandyinfinate_onoff() which sends the correct command bytes for on/off ([6]=0xFF, [7]=0xFF/0x00) based on captured packets, replacing the two set_iaqualink_aux_state() calls in aq_panel.c that sent the wrong byte pattern for this light type. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
USE_LAST_VALUE path was calling AQ_SET_IAQLINK_LIGHTCOLOR_MODE with value=1, producing _fullcmd[6]=0x01 which doesn't match the panel's expected on/off command bytes ([6]=0xFF, [7]=0xFF for on). Now calls set_iaqualink_jandyinfinate_onoff(button, true) directly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Log the isON flag and _fullcmd bytes in set_iaqualink_jandyinfinate_onoff, and log entry into the value==0 branch in programDeviceLightMode, to diagnose why the OFF command sends ON bytes (0xff|0xff) instead of (0xff|0x00). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Brightness packets: [6]=0xFF (constant), [7]=percent (25=0x19, 50=0x32, 75=0x4b, 100=0x64). Was incorrectly writing value into [6] and leaving [7]=0. Also clear [7] after push to match on/off cleanup pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Color mode packets: [6]=mode_index, [7]=0x64 (100% brightness). Was setting [6]=value but leaving [7]=0. The mode index maps directly to the _color_light_options array (Caribbean Blue=4, Spring Green=5, etc). Also clear [7] after push. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
RGB commands use devID+2 (0x61 light → 0x63 RGB sub-device). R/G/B values at [6]/[7]/[8] were already correct from captures (red≈FF,21,0F; green≈00,FF,10; blue≈00,2C,FF). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add AQ_SET_IAQLINK_JANDYINFINATE_ONOFF program type and replace three direct calls to set_iaqualink_jandyinfinate_onoff() in aq_panel.c with aq_programmer(). Consistent with how brightness, color mode, and RGB are dispatched. Wire up ptypeName, programtypeDisplayName, and old-programmer error stub to match the pattern of the other iAQLink light types. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ght_onoff Move it next to the other light functions (colormode/brightness/rgb) in iaqualink.c and update declaration in iaqualink.h. Rename to match the consistent set_iaqualink_light_* naming pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both produce identical packets ([6]=0xFF, [7]=0x00), so the value==0 special-case in programDeviceLightBrightness is redundant. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ON/OFF are just special brightness values on the wire ([7]=0xFF=on, [7]=0x00=off). AQ_SET_IAQLINK_JANDYINFINATE_ONOFF now dispatches directly through set_iaqualink_light_brightness. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
knap1930
commented
Jun 5, 2026
| return; | ||
| } | ||
|
|
||
| // RGB command uses devID+2 (e.g. lightID=0x61 → RGB devID=0x63) |
Author
There was a problem hiding this comment.
I question if this is right or the best way to do this...
Collaborator
|
Thanks for this. Sorry it’s taken me so long to get to but there is a lot of changes and to some core areas of the code so needed to spend a lot of time going over it to make sure it doesn’t break other things. The lights have a few bugs in Jandy firmware so there is a lot of mess in the code to overcome those bugs. There are a new things I still need to validate but will be merging it soon. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes iAqualink direct control for the
LC_JANDYINFINATE(Jandy Infinite Water Colors) light type, replacing the previous stub that fell back toset_iaqualink_aux_state. All four command types are now wired up with correct packet byte layouts confirmed from hardware captures.[6]=0xFF, [7]=0xFF(on) /[7]=0x00(off) — dispatched viaAQ_SET_IAQLINK_JANDYINFINATE_ONOFF→set_iaqualink_light_brightness(0xFF/0x00)[6]=0xFF, [7]=percent(25=0x19, 50=0x32, 75=0x4b, 100=0x64) —set_iaqualink_light_brightness[6]=mode_index, [7]=0x64(100% brightness) —set_iaqualink_light_colormode; mode index maps directly to_color_light_options[LC_JANDYINFINATE][6]=R, [7]=G, [8]=B, using devID+2 (e.g. lightID=0x61 → RGB device=0x63) —set_iaqualink_light_rgbConfig required:
virtual_button_XX_lightID = 61(hex) inaqualinkd.confsoiAqalnkDevIDcan resolve the virtual button's device code.Changes
iaqualink.c/h— fourset_iaqualink_light_*functions with correct byte layouts;iAqalnkDevIDextended to returnlightIDfor LC_JANDYINFINATE virtual buttonsaq_programmer.h/c— newAQ_SET_IAQLINK_JANDYINFINATE_ONOFFprogram type; all iAQL light types wired into dispatch,ptypeName,programtypeDisplayName, and old-programmer error stubsaq_panel.c—programDeviceLightModeandprogramDeviceLightBrightnessuseaq_programmerfor all LC_JANDYINFINATE paths (no more direct iaqualink calls from panel layer)aqualink.h—LIGHT_RGBaction typeaq_mqtt.h—LIGHT_RGB_TOPICnet_services.c— subscribe to/rgb/set; parse"r,g,b"payloadmqtt_discovery.c— RGB-capable light discovery for LC_JANDYINFINATEcolor_lights.c— added"Custom"(0x10) mode for LC_JANDYINFINATETest plan
virtual_button_XX_lightID = 61set in config[7]=0xFF) and off ([7]=0x00)[7]=0x64<button>/rgb/setwith"r,g,b"payload sends to devID+2🤖 Generated with Claude Code