mirror of https://github.com/sfeakes/AqualinkD.git
Updates 3.0.3 dev
parent
44363a981d
commit
0536e00fc3
|
|
@ -0,0 +1,35 @@
|
|||
# Legal Disclaimer & Interoperability Notice
|
||||
|
||||
This document outlines the legal status and usage terms for the **AqualinkD** project.
|
||||
|
||||
---
|
||||
|
||||
## 1. Project Status
|
||||
**AqualinkD** is an independent, open-source software project. It is **not** affiliated with, authorized by, sponsored by, or endorsed by:
|
||||
* **Zodiac Pool Systems** or **Jandy®**
|
||||
* **Pentair®** (including Pentair Water Pool and Spa, Inc.)
|
||||
* Any of their parent companies, subsidiaries, or related brands.
|
||||
|
||||
## 2. Reverse Engineering & Interoperability
|
||||
AqualinkD has been developed for the sole purpose of achieving **hardware interoperability**.
|
||||
* **Clean Room Implementation:** This project does not contain, use, or redistribute any proprietary source code or binary firmware belonging to Jandy or Pentair.
|
||||
* **Protocol Implementation:** The communication methods used by this software (including modifications to the standard Modbus protocol over RS485) are a "method of operation" implemented through independent observation of unencrypted signal sequences.
|
||||
* **Legal Precedent:** This work is protected under the principles of **Fair Use** for interoperability (consistent with legal standards established in *Sega v. Accolade* and *Google v. Oracle*). Under 17 U.S.C. § 102(b), copyright protection does not extend to the ideas, systems, or methods of operation defined by a communication protocol.
|
||||
|
||||
## 3. Trademarks
|
||||
All product names, logos, and brands mentioned (such as Jandy®, Aqualink®, Pentair®, IntelliTouch®, or EasyTouch®) are the property of their respective owners. Their use within this project is for **nominative purposes only**—specifically to identify the pool equipment with which this software is compatible. This usage does not imply any affiliation with or endorsement by the trademark holders.
|
||||
|
||||
## 4. DMCA & Security
|
||||
AqualinkD does **not** bypass or circumvent any digital rights management (DRM) or effective technological protection measures. The hardware signals being interfaced are unencrypted and transmitted via standard serial communication. This software is intended for use on the owner's private home network.
|
||||
|
||||
## 5. Risk & Warranty Disclaimer
|
||||
**USE AT YOUR OWN RISK.**
|
||||
Interfacing with high-voltage pool equipment and RS485 data buses involves inherent risks. By using this software, you acknowledge and agree that:
|
||||
* This software is provided **"as is"**, without warranty of any kind, express or implied.
|
||||
* The developers are not responsible for any damage to pool equipment, RS485 hardware, or Raspberry Pi/computing devices.
|
||||
* Use of third-party software may **void your manufacturer's warranty**.
|
||||
* The developers are not liable for any injury or property damage resulting from the use or misuse of this software.
|
||||
|
||||
---
|
||||
|
||||
*For further information on the project's goals or to contribute, please refer to the [README.md](README.md).*
|
||||
|
|
@ -0,0 +1,975 @@
|
|||
# Jandy RS485 Protocol Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the Jandy RS485 serial communication protocol used by Aqualink control systems to communicate with various pool and spa equipment on the RS485 network. This protocol is reverse-engineered from the AqualinkD project's source code analysis.
|
||||
|
||||
The RS485 protocol is used by the following Jandy/Pentair systems:
|
||||
- Aqualink RS8, RS12, RS16 (and variants)
|
||||
- Aquapure (SWG - Salt Water Chlorinator) systems
|
||||
- Jandy ePumps (variable speed pumps)
|
||||
- JXi and LX Heaters
|
||||
- Chemical feeder and analyzer systems
|
||||
- Heat pumps
|
||||
- Color control lights
|
||||
- iAqualinkTouch panels
|
||||
- OneTouch keypads
|
||||
- AllButton simulators
|
||||
- Remote control adapters
|
||||
|
||||
---
|
||||
|
||||
## Physical Layer
|
||||
|
||||
### Serial Port Configuration
|
||||
|
||||
- **Baud Rate**: 9600 bps
|
||||
- **Data Bits**: 8
|
||||
- **Stop Bits**: 1
|
||||
- **Parity**: None
|
||||
- **Flow Control**: None (hardware or software)
|
||||
- **Serial Standard**: RS485
|
||||
- **Bus Topology**: Multi-drop (up to multiple devices on single RS485 bus)
|
||||
|
||||
### Serial Port Initialization
|
||||
|
||||
From `aq_serial.c`:
|
||||
|
||||
```c
|
||||
// Open with non-blocking mode and no controlling terminal
|
||||
_RS485_fds = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
|
||||
|
||||
// Configure for 8N1, 9600 baud
|
||||
cfsetispeed(&tty, B9600);
|
||||
cfsetospeed(&tty, B9600);
|
||||
tty.c_cflag &= ~PARENB; // No parity
|
||||
tty.c_cflag &= ~CSTOPB; // 1 stop bit
|
||||
tty.c_cflag |= CS8; // 8 data bits
|
||||
tty.c_cflag &= ~CRTSCTS; // No hardware flow control
|
||||
```
|
||||
|
||||
### Port Modes
|
||||
|
||||
- **Non-blocking I/O**: Used to prevent blocking on Data Carrier Detect (DCD)
|
||||
- **Raw Mode**: No canonical processing, no echo
|
||||
- **Read Timeout**: Configurable via `VMIN=0` and `VTIME=10` (1 second timeout)
|
||||
- **Low Latency Mode**: Can be set via `ASYNC_LOW_LATENCY` ioctl for FTDI adapters
|
||||
|
||||
---
|
||||
|
||||
## Protocol Overview
|
||||
|
||||
### Two Supported Protocols
|
||||
|
||||
The AqualinkD system supports two main protocols:
|
||||
|
||||
1. **Jandy Protocol** (DLE/STX/ETX based)
|
||||
2. **Pentair Protocol** (PP1/PP2/PP3/PP4 header based)
|
||||
|
||||
This document focuses on the **Jandy Protocol**.
|
||||
|
||||
---
|
||||
|
||||
## Frame Structure - Jandy Protocol
|
||||
|
||||
### Basic Packet Format
|
||||
|
||||
The Jandy protocol uses a simple framing schema with delimiters and checksums:
|
||||
|
||||
```
|
||||
[DLE] [STX] [DEST] [CMD] [DATA...] [CHECKSUM] [DLE] [ETX]
|
||||
1 2 3 4 5-N N+1 N+2 N+3
|
||||
```
|
||||
|
||||
Where:
|
||||
- **DLE**: Data Link Escape (0x10) - frame start marker
|
||||
- **STX**: Start of Text (0x02) - indicates start of frame
|
||||
- **DEST**: Destination device ID (0x00 = master/controller)
|
||||
- **CMD**: Command byte indicating packet type
|
||||
- **DATA**: Variable length payload (0 to many bytes)
|
||||
- **CHECKSUM**: Single byte checksum (sum of DEST through last DATA byte, masked to 8 bits)
|
||||
- **DLE**: Data Link Escape (0x10) - frame end marker
|
||||
- **ETX**: End of Text (0x03) - indicates end of frame
|
||||
|
||||
---
|
||||
|
||||
## Frame Structure - Pentair Protocol
|
||||
|
||||
### Basic Packet Format
|
||||
|
||||
The Pentair protocol uses a different frame structure:
|
||||
|
||||
```
|
||||
[PP1] [PP2] [PP3] [PP4] [FROM] [DEST] [CMD] [LENGTH] [DATA...] [CHKSUM_HI] [CHKSUM_LO]
|
||||
1 2 3 4 5 6 7 8 9-N N+1 N+2
|
||||
```
|
||||
|
||||
Where:
|
||||
- **NUL**: Null byte (0x00) - padding
|
||||
- **PP1**: Protocol Marker 1 (0xFF) - Pentair frame start
|
||||
- **PP2**: Protocol Marker 2 (0x00) - part of header
|
||||
- **PP3**: Protocol Marker 3 (0xFF) - part of header
|
||||
- **PP4**: Protocol Marker 4 (0xA5) - completes 4-byte header
|
||||
- **FROM**: Source device ID
|
||||
- **DEST**: Destination device ID (0x10 = master)
|
||||
- **CMD**: Command byte (0x01=Speed, 0x04=RemoteCtl, 0x06=Power, 0x07=Status)
|
||||
- **LENGTH**: Data length (number of data bytes following)
|
||||
- **DATA**: Variable length payload
|
||||
- **CHKSUM_HI**: 16-bit checksum high byte (sum of CMD through last DATA byte)
|
||||
- **CHKSUM_LO**: 16-bit checksum low byte
|
||||
|
||||
The Pentair protocol is used primarily by Pentair IntelliFlo and variable speed pumps (device IDs 0x60-0x6F).
|
||||
|
||||
---
|
||||
|
||||
## Jandy Protocol
|
||||
|
||||
### Important Note on DLE Escaping
|
||||
|
||||
If the value 0x10 (DLE) appears in the data portion of the packet (after STX and before the final DLE), it must be escaped by inserting a NUL byte (0x00) after it. The parser must skip these escape sequences.
|
||||
|
||||
### Frame Delimiters - Definitions
|
||||
|
||||
| Constant | Value | Name |
|
||||
|----------|-------|------|
|
||||
| DLE | 0x10 | Data Link Escape |
|
||||
| STX | 0x02 | Start of Text |
|
||||
| ETX | 0x03 | End of Text |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Packet Constants and Offsets
|
||||
|
||||
### Standard Packet Offsets
|
||||
|
||||
Within the data portion (after STX):
|
||||
|
||||
| Offset | Field | Description |
|
||||
|--------|-------|-------------|
|
||||
| 0-1 | Header | DLE (0x10) + STX (0x02) when counting from packet start |
|
||||
| 2 | PKT_DEST | Destination device ID (0x00 = master) |
|
||||
| 3 | PKT_CMD | Command type |
|
||||
| 4+ | PKT_DATA | Command-specific data |
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Device IDs
|
||||
|
||||
### Master/Controller
|
||||
|
||||
| Device | ID Range | Hex | Notes |
|
||||
|--------|----------|-----|-------|
|
||||
| Master/Controller | 0x00 | 0x00 | Destination for all ACKs and responses |
|
||||
|
||||
### Control Panels/Keypads
|
||||
|
||||
| Device | ID Range | Decimal | Hex | Count | Notes |
|
||||
|--------|----------|---------|-----|-------|-------|
|
||||
| AllButton | 0x08-0x0B | 8-11 | 0x08-0x0B | 4 | Emulated keypad |
|
||||
| OneTouch | 0x40-0x43 | 64-67 | 0x40-0x43 | 4 | Physical keypad |
|
||||
| AqualinkTouch (iAqlnk Touch) | 0x30-0x33 | 48-51 | 0x30-0x33 | 4 | Touch panel |
|
||||
| iAqualink2 (Jandy Link) | 0xA0-0xA3 | 160-163 | 0xA0-0xA3 | 4 | Cloud interface |
|
||||
| PDA (AquaPalm) | 0x60-0x63 | 96-99 | 0x60-0x63 | 4 | Handheld remote |
|
||||
| RS Serial Adapter | 0x48-0x49 | 72-73 | 0x48-0x49 | 2 | Serial gateway |
|
||||
|
||||
### Equipment Devices
|
||||
|
||||
| Device | ID Range | Decimal | Hex | Count | Notes |
|
||||
|--------|----------|---------|-----|-------|-------|
|
||||
| Aquapure SWG | 0x50-0x53 | 80-83 | 0x50-0x53 | 4 | Salt chlorinator |
|
||||
| LX Heater | 0x38-0x3B | 56-59 | 0x38-0x3B | 4 | Heating system |
|
||||
| JXi Heater | 0x68-0x6B | 104-107 | 0x68-0x6B | 4 | Jandy JXi heater |
|
||||
| ePump Standard | 0x78-0x7B | 120-123 | 0x78-0x7B | 4 | Variable speed pump (standard range) |
|
||||
| ePump Extended | 0xE0-0xE3 | 224-227 | 0xE0-0xE3 | 4 | Variable speed pump (extended for panel rev W+) |
|
||||
| Heat Pump | 0x70-0x73 | 112-115 | 0x70-0x73 | 4 | Heat pump device |
|
||||
| Chemistry Feeder | 0x80-0x83 | 128-131 | 0x80-0x83 | 4 | Chemical feeder (ChemLink) |
|
||||
| Chemistry Analyzer | 0x84-0x87 | 132-135 | 0x84-0x87 | 4 | Chemical analyzer (TrueSense, guess) |
|
||||
| Jandy Lights | 0xF0-0xF4 | 240-244 | 0xF0-0xF4 | 5 | Colored light control |
|
||||
| Spa Remote | 0x20-0x23 | 32-35 | 0x20-0x23 | 4 | Remote control for spa |
|
||||
| Remote Power Center | 0x28-0x2B | 40-43 | 0x28-0x2B | 4 | Remote power management |
|
||||
| PC Dock | 0x58-0x5B | 88-91 | 0x58-0x5B | 4 | PC docking station |
|
||||
|
||||
---
|
||||
|
||||
## Command Types (CMD Byte)
|
||||
|
||||
### Core Commands
|
||||
|
||||
| Command | Value | Name | Direction | Description |
|
||||
|---------|-------|------|-----------|-------------|
|
||||
| CMD_PROBE | 0x00 | Probe | To Device | Polling/probe message |
|
||||
| CMD_ACK | 0x01 | Acknowledge | From Device | Acknowledgment response |
|
||||
| CMD_STATUS | 0x02 | Status | Bidirectional | Status information (display panels) |
|
||||
| CMD_MSG | 0x03 | Message | To Device | Display message (16 bytes) |
|
||||
| CMD_MSG_LONG | 0x04 | Long Message | To Device | Display message (128 bytes) |
|
||||
| CMD_MSG_LOOP_ST | 0x08 | Message Loop Start | From Device | Start message loop cycle |
|
||||
|
||||
### Checksum-Related Constants
|
||||
|
||||
| Constant | Value | Description |
|
||||
|----------|-------|-------------|
|
||||
| ACK_NORMAL | 0x80 | Normal ACK response |
|
||||
| ACK_SCREEN_BUSY_SCROLL | 0x81 | Screen busy, cache next message |
|
||||
| ACK_SCREEN_BUSY_BLOCK | 0x83 | Screen busy, don't send more |
|
||||
|
||||
Panel compatibility notes:
|
||||
- Some keypads use 0x00, others 0x80 (version/implementation dependent)
|
||||
- Using 0x80 for ACK may trigger CMD_MSG_LOOP_ST cycle
|
||||
|
||||
### Aquapure (SWG) Commands
|
||||
|
||||
| Command | Value | Name | Direction | Description |
|
||||
|---------|-------|------|-----------|-------------|
|
||||
| CMD_PERCENT | 0x11 | Set SWG % | To SWG | Set chlorine generation percentage (0-100, >100 = boost) |
|
||||
| CMD_PPM | 0x16 | PPM/Status | From SWG | Return PPM and device status |
|
||||
|
||||
Example: Set SWG to 75%:
|
||||
```
|
||||
[0x10, 0x02, 0x50, 0x11, 0x4B, checksum, 0x10, 0x03]
|
||||
↑ ↑ ↑
|
||||
SWG %SET 75 decimal
|
||||
```
|
||||
|
||||
### ePump Commands
|
||||
|
||||
| Command | Value | Name | Direction | Description |
|
||||
|---------|-------|------|-----------|-------------|
|
||||
| CMD_EPUMP_STATUS | 0x1F | Status Request | Bidirectional | Get/Set pump status (RPM, Watts, GPM) |
|
||||
| CMD_EPUMP_RPM | 0x44 | Set RPM | To Pump | Set pump speed (RPM mode) |
|
||||
| CMD_EPUMP_WATTS | 0x45 | Set Watts | To Pump | Set pump power (Watts mode) |
|
||||
|
||||
Response format from ePump (0x1F):
|
||||
```
|
||||
CMD=0x1F | Next CMD | Unused | Unused | Hi_Watts | Lo_Watts | Hi_RPM | Lo_RPM | ...
|
||||
Bytes: 4 5 6 7 8 9 10 11
|
||||
```
|
||||
|
||||
Calculation examples:
|
||||
- Watts = (Byte8 × 256) + Byte7
|
||||
- RPM = (Byte10 × 256) + Byte11
|
||||
|
||||
### Heater Commands
|
||||
|
||||
#### JXi Heater
|
||||
|
||||
| Command | Value | Name | Description |
|
||||
|---------|-------|------|-------------|
|
||||
| CMD_JXI_PING | 0x0C | Ping | Poll heater status |
|
||||
| CMD_JXI_STATUS | 0x0D | Status | Return heater status |
|
||||
|
||||
#### LX Heater
|
||||
|
||||
Similar to JXi but with different device ID range (0x38-0x3B).
|
||||
|
||||
### iAqualinkTouch Commands
|
||||
|
||||
| Command | Value | Name | Description |
|
||||
|---------|-------|------|-------------|
|
||||
| CMD_IAQ_PAGE_START | 0x23 | Page Start | Begin new menu page |
|
||||
| CMD_IAQ_PAGE_BUTTON | 0x24 | Button | Button definition for current page |
|
||||
| CMD_IAQ_PAGE_MSG | 0x25 | Page Message | Message content for page |
|
||||
| CMD_IAQ_TABLE_MSG | 0x26 | Table Message | Table data populate command |
|
||||
| CMD_IAQ_PAGE_END | 0x28 | Page End | End of page definition |
|
||||
| CMD_IAQ_STARTUP | 0x29 | Startup | Startup message |
|
||||
| CMD_IAQ_POLL | 0x30 | Poll | Ready to receive commands |
|
||||
| CMD_IAQ_CTRL_READY | 0x31 | Control Ready | Ready for big control command |
|
||||
| CMD_IAQ_PAGE_CONTINUE | 0x40 | Page Continue | Multiple pages continue cycle |
|
||||
| CMD_IAQ_MSG_LONG | 0x2C | Long Message | Display popup message |
|
||||
| CMD_IAQ_MAIN_STATUS | 0x70 | Main Status | Main screen status (large, 120+ bytes) |
|
||||
| CMD_IAQ_1TOUCH_STATUS | 0x71 | OneTouch Status | OneTouch emulation status |
|
||||
| CMD_IAQ_AUX_STATUS | 0x72 | Auxiliary Status | Auxiliary equipment status (large) |
|
||||
| CMD_IAQ_CMD_READY | 0x73 | Command Ready | Ready to receive command |
|
||||
| CMD_IAQ_TITLE_MESSAGE | 0x2D | Title Message | Product name/title message |
|
||||
|
||||
#### iAqualinkTouch Page IDs
|
||||
|
||||
These define different screen pages in the iAqualinkTouch interface:
|
||||
|
||||
| Page | ID | Purpose |
|
||||
|------|----|---------|
|
||||
| Home | 0x01 | Home screen |
|
||||
| Status | 0x5B | Status screen (or 0x2A alternate) |
|
||||
| Devices | 0x36 | Device control (or 0x35, 0x51 alternates) |
|
||||
| Set Temperature | 0x39 | Temperature setting |
|
||||
| Menu | 0x0F | Main menu |
|
||||
| Set VSP | 0x1E | Variable speed pump setup |
|
||||
| Set Time | 0x4B | Time setting |
|
||||
| Set Date | 0x4E | Date setting |
|
||||
| Set SWG | 0x30 | SWG setup |
|
||||
| Set Boost | 0x1D | Chlorine boost setting |
|
||||
| Set Quick Boost | 0x3F | Quick boost setting |
|
||||
| OneTouch | 0x4D | OneTouch page |
|
||||
| Color Light | 0x48 | Color light control |
|
||||
| System Setup | 0x14 | System setup (or 0x49, 0x4A alternates) |
|
||||
| VSP Setup | 0x2D | VSP detailed setup |
|
||||
| Freeze Protect | 0x11 | Freeze protection |
|
||||
| Label Aux | 0x32 | Auxiliary labeling |
|
||||
| Help | 0x0C | Help screen |
|
||||
| Service Mode | 0x5E | Service/timeout mode |
|
||||
|
||||
### PDA Commands
|
||||
|
||||
| Command | Value | Name |
|
||||
|---------|-------|------|
|
||||
| CMD_PDA_0x04 | 0x04 | Unknown (menu building?) |
|
||||
| CMD_PDA_0x05 | 0x05 | Unknown |
|
||||
| CMD_PDA_0x1B | 0x1B | Unknown |
|
||||
| CMD_PDA_HIGHLIGHT | 0x08 | Highlight line |
|
||||
| CMD_PDA_CLEAR | 0x09 | Clear display |
|
||||
| CMD_PDA_SHIFTLINES | 0x0F | Shift display lines |
|
||||
| CMD_PDA_HIGHLIGHTCHARS | 0x10 | Highlight characters |
|
||||
|
||||
### Serial Adapter Commands
|
||||
|
||||
| Command | Value | Name | Description |
|
||||
|---------|-------|------|-------------|
|
||||
| RSSA_DEV_STATUS | 0x13 | Device Status | Status or error response |
|
||||
| RSSA_DEV_READY | 0x07 | Device Ready | Ready to receive command |
|
||||
|
||||
---
|
||||
|
||||
## Checksum Calculation
|
||||
|
||||
### Jandy Protocol Checksum
|
||||
|
||||
The checksum is calculated by summing all bytes from DEST through the last DATA byte, then masking to 8 bits.
|
||||
|
||||
```c
|
||||
int generate_checksum(unsigned char* packet, int length)
|
||||
{
|
||||
int i, sum, n;
|
||||
n = length - 3; // Exclude DLE, ETX, and trailing NUL
|
||||
sum = 0;
|
||||
for (i = 0; i < n; i++)
|
||||
sum += (int) packet[i];
|
||||
return (sum & 0x0FF);
|
||||
}
|
||||
```
|
||||
|
||||
The checksum is placed at `packet[length-3]` (before the final DLE).
|
||||
|
||||
### Example Checksum Calculation
|
||||
|
||||
For packet: `[DLE, STX, 0x50, 0x11, 0x4B, CHKSUM, DLE, ETX]`
|
||||
|
||||
```
|
||||
sum = 0x50 + 0x11 + 0x4B = 0xAC
|
||||
checksum = 0xAC & 0xFF = 0xAC
|
||||
```
|
||||
|
||||
### Jandy Checksum Bug Workaround
|
||||
|
||||
There's a known bug in the Jandy OneTouch protocol where long messages (0x0a command) to OneTouch devices have incorrect checksums. The code detects this pattern:
|
||||
- packet[3] == 0x04
|
||||
- packet[4] == 0x03
|
||||
- packet[length-3] == 0x0a
|
||||
|
||||
In this case, the checksum is ignored (forced valid) with a warning log.
|
||||
|
||||
### Checksum Validation
|
||||
|
||||
```c
|
||||
bool check_jandy_checksum(unsigned char* packet, int length)
|
||||
{
|
||||
if (generate_checksum(packet, length) == packet[length-3])
|
||||
return true;
|
||||
|
||||
// Known bug workaround
|
||||
if (packet[3] == 0x04 && packet[4] == 0x03 && packet[length-3] == 0x0a)
|
||||
return true; // Forced valid with LOG warning
|
||||
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Aquapure (SWG) Protocol
|
||||
|
||||
### Overview
|
||||
|
||||
The Aquapure Salt Water Chlorinator communicates via the Jandy protocol to report its status and receive percentage/power commands.
|
||||
|
||||
### Device IDs: 0x50-0x53
|
||||
|
||||
Up to 4 Aquapure units can be independently controlled (though AqualinkD only supports one in v1.0).
|
||||
|
||||
### SWG Status Bytes
|
||||
|
||||
When the master sends a query to the SWG, the SWG responds with its operational status.
|
||||
|
||||
| Status | Value | Name | Description |
|
||||
|--------|-------|------|-------------|
|
||||
| SWG_STATUS_ON | 0x00 | Normal Operation | Generating chlorine |
|
||||
| SWG_STATUS_NO_FLOW | 0x01 | No Flow | Water not flowing through cell |
|
||||
| SWG_STATUS_LOW_SALT | 0x02 | Low Salt | Salt level too low |
|
||||
| SWG_STATUS_HI_SALT | 0x04 | High Salt | Salt level too high |
|
||||
| SWG_STATUS_CLEAN_CELL | 0x08 | Clean Cell | Cell cleaning cycle active |
|
||||
| SWG_STATUS_TURNING_OFF | 0x09 | Turning Off | Shutdown in progress |
|
||||
| SWG_STATUS_HIGH_CURRENT | 0x10 | High Current | Excessive current draw |
|
||||
| SWG_STATUS_LOW_VOLTS | 0x20 | Low Voltage | Insufficient voltage |
|
||||
| SWG_STATUS_LOW_TEMP | 0x40 | Low Temperature | Water temperature too low |
|
||||
| SWG_STATUS_CHECK_PCB | 0x80 | Check PCB | PCB/control board error |
|
||||
| SWG_STATUS_GENFAULT | 0xFD | General Fault | General fault state |
|
||||
| SWG_STATUS_UNKNOWN | 0xFE | Unknown | No status received |
|
||||
| SWG_STATUS_OFF | 0xFF | Off | Device off (AqualinkD internal state) |
|
||||
|
||||
### Example SWG Communication Flow
|
||||
|
||||
**Query SWG Status:**
|
||||
```
|
||||
Master → SWG: [DLE, STX, 0x50, 0x02, CHKSUM, DLE, ETX]
|
||||
↑ ↑
|
||||
SWG CMD_STATUS
|
||||
```
|
||||
|
||||
**SWG Response:**
|
||||
```
|
||||
SWG → Master: [DLE, STX, 0x00, 0x16, PPM_VAL, STATUS, CHKSUM, DLE, ETX]
|
||||
↑ ↑ ↑ ↑
|
||||
Master CMD_PPM PPM*100 Status byte
|
||||
```
|
||||
|
||||
Where:
|
||||
- PPM_VAL: Division factor for PPM (actual PPM = PPM_VAL × 100)
|
||||
- STATUS: One of the status values above
|
||||
- Example: `[DLE, STX, 0x00, 0x16, 0x0C, 0x00, CHKSUM, DLE, ETX]` means 1200 PPM, On
|
||||
|
||||
**Set SWG Percentage:**
|
||||
```
|
||||
Master → SWG: [DLE, STX, 0x50, 0x11, PERCENT, CHKSUM, DLE, ETX]
|
||||
↑ ↑ ↑
|
||||
SWG %SET 0-100 (>100 = boost mode)
|
||||
```
|
||||
|
||||
Example: Set to 75%:
|
||||
```
|
||||
[DLE, STX, 0x50, 0x11, 0x4B, CHKSUM, DLE, ETX] (0x4B = 75 decimal)
|
||||
```
|
||||
|
||||
**Boost Mode:**
|
||||
```
|
||||
Master → SWG: [DLE, STX, 0x50, 0x11, 0x65, CHKSUM, DLE, ETX] (0x65 = 101 decimal)
|
||||
```
|
||||
|
||||
### SWG Packet Examples
|
||||
|
||||
From actual systems (from protocol notes):
|
||||
|
||||
```
|
||||
AR %% | HEX: 0x10|0x02|0x50|0x11|0xff|0x72|0x10|0x03|
|
||||
In service/timeout: Set to 0xFF (all on in special mode)
|
||||
|
||||
SWG response: 0x10|0x02|0x00|0x16|0x0C|0x00|0x1E|0x10|0x03|
|
||||
Status = 0x00 (on), PPM = 0x0C (1200 PPM)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ePump (Variable Speed Pump) Protocol
|
||||
|
||||
### Overview
|
||||
|
||||
Jandy ePumps are variable-speed DC or AC motors that can operate in RPM or Watts mode. They communicate via the RS485 bus to report their current operational status and receive speed/power commands.
|
||||
|
||||
### Device IDs
|
||||
|
||||
- **Standard Range**: 0x78-0x7B (120-123 decimal)
|
||||
- **Extended Range**: 0xE0-0xE3 (224-227 decimal) - Panel revision W and later
|
||||
|
||||
### ePump Status and Control
|
||||
|
||||
#### Get/Set Watts
|
||||
|
||||
**Command**: CMD_EPUMP_WATTS (0x45)
|
||||
|
||||
```
|
||||
Master → Pump: [DLE, STX, 0x78, 0x45, 0x00, HI_WATTS, LO_WATTS, CHKSUM, DLE, ETX]
|
||||
↑ ↑ ↑ ↑
|
||||
Pump WATTS_CMD Reserved Watts value (16-bit)
|
||||
|
||||
Pump → Master: [DLE, STX, 0x00, 0x1F, 0x45, 0x00, HI_WATTS, LO_WATTS, ..., CHKSUM, DLE, ETX]
|
||||
↑ ↑ ↑
|
||||
Master STATUS (0x1F) Original CMD echoed
|
||||
```
|
||||
|
||||
Watts Calculation: `watts = (packet[8] × 256) + packet[7]`
|
||||
|
||||
**Example: Set to 1309 Watts**
|
||||
```
|
||||
1309 = 0x51D
|
||||
Hi_byte = 0x05 (1309 >> 8)
|
||||
Lo_byte = 0x1D (1309 & 0xFF)
|
||||
|
||||
Packet: [DLE, STX, 0x78, 0x45, 0x00, 0x05, 0x1D, CHKSUM, DLE, ETX]
|
||||
```
|
||||
|
||||
#### Get/Set RPM
|
||||
|
||||
**Command**: CMD_EPUMP_RPM (0x44)
|
||||
|
||||
Similar format to Watts but for RPM control:
|
||||
|
||||
```
|
||||
Master → Pump: [DLE, STX, 0x78, 0x44, 0x00, HI_RPM, LO_RPM, CHKSUM, DLE, ETX]
|
||||
Pump → Master: [DLE, STX, 0x00, 0x1F, 0x44, 0x00, HI_RPM, LO_RPM, ..., CHKSUM, DLE, ETX]
|
||||
```
|
||||
|
||||
RPM Calculation: `rpm = (packet[6] × 256) + packet[7]`
|
||||
|
||||
#### Status Response Structure
|
||||
|
||||
When pump responds with status (0x1F), the full packet contains:
|
||||
|
||||
| Offset | Field | Description |
|
||||
|--------|-------|-------------|
|
||||
| 0-1 | Header | DLE + STX |
|
||||
| 2 | DEST | 0x00 (Master) |
|
||||
| 3 | CMD | 0x1F (Status) |
|
||||
| 4 | Orig_CMD | Echo of original command (0x44, 0x45, etc.) |
|
||||
| 5 | Reserved | 0x00 |
|
||||
| 6-7 | WATTS_HI/LO | Current watts (16-bit) |
|
||||
| 8-9 | RPM_HI/LO | Current RPM (16-bit) |
|
||||
| 10+ | Other fields | Pressure, temperature, etc. (device dependent) |
|
||||
|
||||
---
|
||||
|
||||
## Heater Protocol
|
||||
|
||||
### JXi Heater (Jandy)
|
||||
|
||||
**Device IDs**: 0x68-0x6B (104-107 decimal)
|
||||
|
||||
#### Commands
|
||||
|
||||
| Command | Value | Description |
|
||||
|---------|-------|-------------|
|
||||
| CMD_JXI_PING | 0x0C | Ping/poll heater |
|
||||
| CMD_JXI_STATUS | 0x0D | Status response |
|
||||
|
||||
#### Status Indicators
|
||||
|
||||
From status packets (CMD_JXI_STATUS):
|
||||
- Byte 6 == 0x10: Error condition
|
||||
- Other values: Normal operational status
|
||||
|
||||
#### Example Packets
|
||||
|
||||
```c
|
||||
// From protocol notes in devices_jandy.c
|
||||
"LXi status | HEX: 0x10|0x02|0x00|0x0d|0x00|0x00|0x00|0x1f|0x10|0x03|"
|
||||
"LXi status | HEX: 0x10|0x02|0x00|0x0a|0x00|0x00|0x00|0x1f|0x10|0x03|"
|
||||
↑ ERROR if 0x10
|
||||
```
|
||||
|
||||
### LX Heater
|
||||
|
||||
**Device IDs**: 0x38-0x3B (56-59 decimal)
|
||||
|
||||
Similar protocol to JXi but with different device ID range.
|
||||
|
||||
---
|
||||
|
||||
## Chemical Control Protocol
|
||||
|
||||
### Chemistry Feeder (ChemLink)
|
||||
|
||||
**Device IDs**: 0x80-0x83 (128-131 decimal)
|
||||
|
||||
Chemistry feeders communicate to dispense specific chemicals or adjust chemical dosing levels.
|
||||
|
||||
### Chemistry Analyzer (TrueSense)
|
||||
|
||||
**Device IDs**: 0x84-0x87 (132-135 decimal) [GUESS - not fully documented in code]
|
||||
|
||||
These devices report chemical levels (pH, ORP, salt levels, etc.) back to the control system.
|
||||
|
||||
---
|
||||
|
||||
## Heat Pump Protocol
|
||||
|
||||
**Device IDs**: 0x70-0x73 (112-115 decimal)
|
||||
|
||||
Heat pumps can operate in heating or cooling mode and report their operational state (on/off, heating/cooling, error state, etc.) via the RS485 protocol.
|
||||
|
||||
---
|
||||
|
||||
## Light Control Protocol (Jandy Lights)
|
||||
|
||||
**Device IDs**: 0xF0-0xF4 (240-244 decimal)
|
||||
|
||||
Color-changing lights can be controlled to display different colors and brightness levels via RS485 commands.
|
||||
|
||||
---
|
||||
|
||||
## iAqualinkTouch Protocol
|
||||
|
||||
### Overview
|
||||
|
||||
The iAqualinkTouch is a more advanced control panel with a graphical display and touch interface, communicating via the Jandy RS485 protocol but with more complex message structures for GUI rendering.
|
||||
|
||||
### Device IDs: 0x30-0x33
|
||||
|
||||
### Key Protocol Features
|
||||
|
||||
1. **Paged Menus**: Screens are defined with multiple commands
|
||||
2. **Large Status Messages**: Status packets can be 120+ bytes (up to full packet buffer)
|
||||
3. **Button Definitions**: Dynamic button layout per page
|
||||
4. **Table Messages**: Structured data (equipment lists, parameters, etc.)
|
||||
|
||||
### Page Definition Flow
|
||||
|
||||
```
|
||||
Master → Touch: PAGE_START (0x23) - Begin new page
|
||||
Master → Touch: PAGE_BUTTON (0x24) - Define button
|
||||
Master → Touch: PAGE_MSG (0x25) - Add text/content
|
||||
Master → Touch: PAGE_CONTINUE (0x40) - More pages follow
|
||||
Master → Touch: PAGE_END (0x28) - Page complete
|
||||
```
|
||||
|
||||
### Status Messages
|
||||
|
||||
#### Main Status (0x70)
|
||||
Large packet (typically 100+ bytes) containing complete system status suitable for main equipment view.
|
||||
|
||||
#### OneTouch Status (0x71)
|
||||
Status suitable for OneTouch emulation mode.
|
||||
|
||||
#### AUX Status (0x72)
|
||||
Status for auxiliary equipment (pumps, heaters, etc.).
|
||||
|
||||
### Button Keys (Key Codes)
|
||||
|
||||
**Navigation Keys:**
|
||||
| Key | Value | Function |
|
||||
|-----|-------|----------|
|
||||
| HOME | 0x01 | Home page |
|
||||
| MENU | 0x02 | Menu |
|
||||
| ONETOUCH | 0x03 | OneTouch |
|
||||
| HELP | 0x04 | Help |
|
||||
| BACK | 0x05 | Back |
|
||||
| STATUS | 0x06 | Status |
|
||||
| PREV_PAGE | 0x20 | Previous page |
|
||||
| NEXT_PAGE | 0x21 | Next page |
|
||||
|
||||
**Grid Keys (Numbered 0x11-0x1F):**
|
||||
|
||||
The screen has a 3×5 grid of buttons:
|
||||
```
|
||||
Button Layout:
|
||||
Column 1 Column 2 Column 3
|
||||
Row 1: 0x11 Row 1: 0x16 Row 1: 0x1B (KEY01-KEY05 = Column 1)
|
||||
Row 2: 0x12 Row 2: 0x17 Row 2: 0x1C (KEY06-KEY10 = Column 2)
|
||||
Row 3: 0x13 Row 3: 0x18 Row 3: 0x1D (KEY11-KEY15 = Column 3)
|
||||
Row 4: 0x14 Row 4: 0x19 Row 4: 0x1E
|
||||
Row 5: 0x15 Row 5: 0x1A Row 5: 0x1F
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Control Panel Communication
|
||||
|
||||
### ACK (Acknowledgment) Responses
|
||||
|
||||
After receiving a command, devices must respond with an ACK to indicate successful receipt.
|
||||
|
||||
#### ACK Types
|
||||
|
||||
| Type | Value | Purpose |
|
||||
|------|-------|---------|
|
||||
| ACK_NORMAL | 0x80 | Normal acknowledgment |
|
||||
| ACK_SCREEN_BUSY_SCROLL | 0x81 | Screen busy but can cache next message |
|
||||
| ACK_SCREEN_BUSY_BLOCK | 0x83 | Screen busy, stop sending |
|
||||
|
||||
#### ACK Packet Structure
|
||||
|
||||
```c
|
||||
// From aq_serial.c - _send_ack()
|
||||
unsigned char ackPacket[] = { DLE, STX, DEV_MASTER, CMD_ACK, ack_type, command, checksum, DLE, ETX };
|
||||
```
|
||||
|
||||
Example - Send normal ACK:
|
||||
```
|
||||
[DLE, STX, 0x00, CMD_ACK, 0x80, 0x00, CHKSUM, DLE, ETX]
|
||||
↑ ↑
|
||||
ACK_NORMAL No command
|
||||
```
|
||||
|
||||
#### Special Case: DLE Escaping in ACK
|
||||
|
||||
If the command being acknowledged is DLE (0x10), the packet must be escaped:
|
||||
|
||||
```
|
||||
Original: [DLE, STX, 0x00, CMD_ACK, 0x80, 0x10, CHKSUM, DLE, ETX]
|
||||
Escaped : [DLE, STX, 0x00, CMD_ACK, 0x80, 0x10, 0x00, 0x10, DLE, ETX]
|
||||
↑ ↑ escape NUL + extra DLE
|
||||
```
|
||||
|
||||
### OneTouch Keypad Keys
|
||||
|
||||
OneTouch keypads communicate keypress events via specific key codes:
|
||||
|
||||
| Key | Value | Function |
|
||||
|-----|-------|----------|
|
||||
| UP | 0x06 | Up arrow |
|
||||
| DOWN | 0x05 | Down arrow |
|
||||
| SELECT | 0x04 | Select/OK |
|
||||
| PAGE_UP/SELECT_1 | 0x03 | Top button |
|
||||
| BACK/SELECT_2 | 0x02 | Middle button |
|
||||
| PAGE_DOWN/SELECT_3 | 0x01 | Bottom button |
|
||||
|
||||
From display lines, OneTouch can control equipment on/off or navigate menu:
|
||||
|
||||
```
|
||||
Keypress → Master: [DLE, STX, 0x00, key_code, details, CHKSUM, DLE, ETX]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Packet Reception and Parsing
|
||||
|
||||
### Packet Reception State Machine
|
||||
|
||||
From `get_packet()` in `aq_serial.c`:
|
||||
|
||||
1. **Wait for DLE**: First byte must be 0x10
|
||||
2. **Expect STX**: Next byte must be 0x02
|
||||
3. **Collect Payload**: Read bytes into buffer, tracking index
|
||||
4. **Handle Escaping**: If byte is DLE, check if followed by NUL (escape) or 0x03 (end)
|
||||
5. **Validate Checksum**: Verify calculated checksum matches packet
|
||||
6. **Return Success/Error**
|
||||
|
||||
### Error Codes
|
||||
|
||||
| Code | Symbol | Meaning |
|
||||
|------|--------|---------|
|
||||
| 0 | Success | Packet received and valid |
|
||||
| -1 | AQSERR_READ | Serial read error |
|
||||
| -2 | AQSERR_TIMEOUT | Read timeout |
|
||||
| -3 | AQSERR_CHKSUM | Checksum validation failed |
|
||||
| -4 | AQSERR_2LARGE | Packet exceeds max length |
|
||||
| -5 | AQSERR_2SMALL | Packet too short (<5 bytes) |
|
||||
|
||||
### Packet Receiving - Frame Format Detection
|
||||
|
||||
The parser automatically detects protocol type:
|
||||
|
||||
```c
|
||||
protocolType getProtocolType(const unsigned char* packet)
|
||||
{
|
||||
if (packet[0] == DLE) // 0x10
|
||||
return JANDY; // This is Jandy protocol
|
||||
else if (packet[0] == PP1) // 0xFF
|
||||
return PENTAIR; // This is Pentair protocol
|
||||
return P_UNKNOWN;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frame Delay and Timing
|
||||
|
||||
### Frame Delay Configuration
|
||||
|
||||
The system supports configurable delay between packet transmission and reception to prevent bus collisions:
|
||||
|
||||
```c
|
||||
_aqconfig_.frame_delay // Configurable delay in milliseconds
|
||||
```
|
||||
|
||||
When `frame_delay > 0`:
|
||||
- Track time of last serial read
|
||||
- Before sending packet, wait until minimum elapsed time since last read
|
||||
- Calculate minimum wait = `frame_delay` ms
|
||||
- Use `nanosleep()` for precise timing
|
||||
|
||||
### Example Timing
|
||||
|
||||
```
|
||||
Last Read: T=0ms
|
||||
Send Delay: frame_delay = 50ms
|
||||
Current Time: T=30ms
|
||||
Must wait: 20ms more before sending
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Known Issues & Quirks
|
||||
|
||||
### 1. Jandy OneTouch Long Message Checksum Bug
|
||||
|
||||
**Description**: Long messages (0x0A command) to OneTouch devices sometimes have invalid checksums.
|
||||
|
||||
**Detection Pattern**:
|
||||
```c
|
||||
if (packet[3] == 0x04 && packet[4] == 0x03 && packet[length-3] == 0x0a)
|
||||
// This is the known bug - force checksum valid
|
||||
```
|
||||
|
||||
**Workaround**: AqualinkD logs a debug message and accepts the packet anyway.
|
||||
|
||||
### 2. SWG Status Interpretation
|
||||
|
||||
**Issue**: The panel sometimes shows SWG status differently than the actual device status due to timing of when messages are received.
|
||||
|
||||
**Examples**:
|
||||
- "AQUAPURE" prefix is 8 characters in display (MSG_SWG_PCT_LEN)
|
||||
- "SALT" prefix is 4 characters (MSG_SWG_PPM_LEN)
|
||||
- Timeouts or missing ACKs can mark SWG as offline
|
||||
|
||||
### 3. Multiple SWG Support
|
||||
|
||||
**Current Limitation**: AqualinkD only supports one SWG device despite the protocol allowing up to 4 (IDs 0x50-0x53).
|
||||
|
||||
**Code Comment**:
|
||||
```c
|
||||
// Capture the SWG ID. We could have more than one, but for the moment
|
||||
// AqualinkD only supports one so we'll pick the first one.
|
||||
```
|
||||
|
||||
### 4. ePump Extended ID Range
|
||||
|
||||
**Note**: Newer panel revisions (Rev W and later) support additional ePump IDs in range 0xE0-0xE3 in addition to the standard 0x78-0x7B.
|
||||
|
||||
### 5. iAqualinkTouch Large Packets
|
||||
|
||||
**Issue**: iAqualinkTouch status packets (0x70, 0x71, 0x72) can exceed 128 bytes, requiring larger buffer.
|
||||
|
||||
**Solution**: Max packet length increased to 512 bytes, with warning log for packets over 128 bytes (except for those specific status commands).
|
||||
|
||||
---
|
||||
|
||||
## Pentair Protocol (Brief Overview)
|
||||
|
||||
For reference, the Pentair protocol is also supported:
|
||||
|
||||
### Pentair Packet Header
|
||||
|
||||
```
|
||||
[0xFF] [0x00] [0xFF] [0xA5] [FROM] [DEST] [CMD] [LENGTH] [DATA...] [CHKSUM_HI] [CHKSUM_LO]
|
||||
```
|
||||
|
||||
### Pentair Device IDs
|
||||
|
||||
- **Master**: 0x10
|
||||
- **Pumps**: 0x60-0x6F (96-111 decimal)
|
||||
|
||||
### Pentair Commands
|
||||
|
||||
| Command | Value | Description |
|
||||
|---------|-------|-------------|
|
||||
| PEN_CMD_SPEED | 0x01 | Set pump speed (RPM or GPM) |
|
||||
| PEN_CMD_REMOTECTL | 0x04 | Remote control |
|
||||
| PEN_CMD_POWER | 0x06 | Set pump power (ON/OFF) |
|
||||
| PEN_CMD_STATUS | 0x07 | Status request/response |
|
||||
|
||||
### Pentair Checksum
|
||||
|
||||
16-bit checksum calculated over data portion, stored as two bytes (high, low).
|
||||
|
||||
---
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Packet Logging
|
||||
|
||||
The system can log all RS485 packets in multiple formats:
|
||||
|
||||
- **Raw Byte Logging**: Individual bytes as received
|
||||
- **Formatted Logging**: Hex display with protocol interpretation
|
||||
- **Pretty Printing**: Human-readable descriptions
|
||||
|
||||
### Configuration Options (from _aqconfig_)
|
||||
|
||||
```c
|
||||
_aqconfig_.ftdi_low_latency // Enable low latency mode for FTDI adapters
|
||||
_aqconfig_.frame_delay // Delay between packets (milliseconds)
|
||||
_aqconfig_.log_protocol_packets // Log all packets to file
|
||||
_aqconfig_.log_raw_bytes // Log individual bytes received
|
||||
```
|
||||
|
||||
### Bit Shifting and Multi-Byte Values
|
||||
|
||||
When combining two bytes into a 16-bit value:
|
||||
|
||||
```c
|
||||
uint16_t value_16bit = (high_byte << 8) | low_byte
|
||||
= (high_byte * 256) + low_byte
|
||||
```
|
||||
|
||||
Example: RPM from bytes [0x0B, 0x82]:
|
||||
```
|
||||
RPM = (0x0B * 256) + 0x82 = 2816 + 130 = 2946 RPM
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Packet Capture Example
|
||||
|
||||
Real packets from the decoding directory (from repository):
|
||||
|
||||
```
|
||||
AR %% Set to 75%:
|
||||
HEX: 0x10|0x02|0x50|0x11|0x4B|0x72|0x10|0x03|
|
||||
|
||||
SWG Response PPM=1200, Status=ON:
|
||||
HEX: 0x10|0x02|0x00|0x16|0x0C|0x00|0x1E|0x10|0x03|
|
||||
|
||||
ePump Watts Response:
|
||||
HEX: 0x10|0x02|0x00|0x1f|0x45|0x00|0x05|0x1d|0x10|0x03|
|
||||
(Watts = 0x051D = 1309)
|
||||
|
||||
LXi Heater Status:
|
||||
HEX: 0x10|0x02|0x00|0x0d|0x00|0x00|0x00|0x1f|0x10|0x03|
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
### Source Files
|
||||
|
||||
Key files in the AqualinkD project that implement this protocol:
|
||||
|
||||
- `source/aq_serial.c` - Serial I/O and low-level protocol handling
|
||||
- `source/aq_serial.h` - Protocol definitions and constants
|
||||
- `source/devices_jandy.c` - Jandy device handling and packet processing
|
||||
- `source/devices_jandy.h` - Jandy device declarations
|
||||
- `source/devices_pentair.c` - Pentair protocol implementation
|
||||
- `source/rs_devices.h` - Device ID ranges and helper functions
|
||||
- `source/packetLogger.c` - Packet logging utilities
|
||||
|
||||
### Relevant Constants
|
||||
|
||||
See `aq_serial.h` for:
|
||||
- Frame delimiters (NUL, DLE, STX, ETX)
|
||||
- Command byte definitions (CMD_*)
|
||||
- ACK response types
|
||||
- Device ID ranges
|
||||
- Packet length limits
|
||||
- Error codes
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
The Jandy RS485 protocol is a mature, well-established protocol used across Jandy Aqualink pool control systems. While it has some quirks and undocumented messages, the AqualinkD project provides a solid open-source reference implementation.
|
||||
|
||||
The protocol supports:
|
||||
- Multiple device types (pumps, heaters, chemical control, lighting)
|
||||
- Multiple panel types (OneTouch, AqualinkTouch, PDA, AllButton emulation)
|
||||
- Reliable communication via checksums
|
||||
- Extensibility for new device types and panels
|
||||
|
||||
Future versions may add support for:
|
||||
- Multiple SWG devices simultaneously
|
||||
- Additional undocumented device types or commands
|
||||
- Protocol optimizations and performance improvements
|
||||
|
||||
---
|
||||
|
||||
37
README.md
37
README.md
|
|
@ -6,28 +6,35 @@ Binaries are supplied for Raspberry Pi both 32 & 64 bit OS, Has been, and can be
|
|||
|
||||
### It does not, and will never provide any layer of security. NEVER directly expose the device running this software to the outside world; only indirectly through the use of Home Automation hub's or other security measures. e.g. VPNs.
|
||||
|
||||
|
||||
## Donation
|
||||
---
|
||||
### Donation
|
||||
If you like this project, you can buy me a cup of coffee :)
|
||||
<br>
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SEGN9UNS38TXJ)
|
||||
<hr>
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SEGN9UNS38TXJ)
|
||||
|
||||
|
||||
|
||||
## AqualinkD new home
|
||||
---
|
||||
### AqualinkD new home
|
||||
AqualinkD has grown over the years and now has multiple repositories for software / hardware. We are brining them all together under one organization. [AqualinkD home page (under construction)](https://www.aqualinkd.com) -or- [AqualinkD organization](https://github.com/aqualinkd).<br>
|
||||
AqualinkD will always be open source and so will every associated repository. Nothing will change from that perspective. You will always be able to run this on cheap off the shelf hardware.
|
||||
|
||||
|
||||
## AqualinkD discussions
|
||||
---
|
||||
### Legal and Safety Disclaimer
|
||||
[Please read](https://github.com/aqualinkd/Disclaimer.md)
|
||||
|
||||
|
||||
---
|
||||
### AqualinkD discussions
|
||||
|
||||
* Please use github Discussions for questions (Link at top of page).
|
||||
https://github.com/aqualinkd/AqualinkD/discussions
|
||||
* For Bugs, please use issues link on top of page. ( please add AqualinkD version to posts )
|
||||
https://github.com/aqualinkd/AqualinkD/issues
|
||||
|
||||
## Please see Wiki for installation instructions
|
||||
---
|
||||
### Please see Wiki for installation instructions
|
||||
https://github.com/aqualinkd/AqualinkD/wiki
|
||||
|
||||
<!--
|
||||
|
|
@ -38,8 +45,8 @@ https://github.com/aqualinkd/AqualinkD/wiki/Upgrading-Jandy-Aqualink-PDA-to-RS-p
|
|||
Here's where I started to document what I know about the Jandy RS485 protocol.<br>
|
||||
https://github.com/aqualinkd/AqualinkD/wiki/Jandy-Aqualink-RS485-protocol
|
||||
-->
|
||||
|
||||
## AqualinkD built in WEB Interface(s).
|
||||
---
|
||||
### AqualinkD built in WEB Interface(s).
|
||||
|
||||
<table width="100%" border="0" cellpadding="20px">
|
||||
<tr><th width="50%">Default web interface</th><th wifth="50%">Simple web interface</img></th><tr>
|
||||
|
|
@ -134,19 +141,20 @@ NEED TO FIX NEXT THIS RELEASE.
|
|||
|
||||
Panel = RS-2/6 Dual will not have spa on auto config. (fine after saving config and restart).
|
||||
Need to fix SWG when it's set to 0, thinks it's off and can't change, if it states 0 need to be enable, if blank turn off.
|
||||
Need to look at sub panel (combined panels)
|
||||
Need to look at sub panel (combined panels)
|
||||
when serial port is wrong, can't edit config.
|
||||
-->
|
||||
|
||||
|
||||
# Updates in 3.0.3 (dev)
|
||||
* Fixed setting SWG for PDA v1.2
|
||||
|
||||
* Fixed bug with slider run times in web UI
|
||||
* Fixed bug with heater max min in web UI
|
||||
|
||||
# Updates in 3.0.2
|
||||
* Fixed bug with SWG being enabled if one is not present.
|
||||
* Fixed bug with light_programs ending in 'show' aqualinkd.conf
|
||||
|
||||
|
||||
# Updates in 3.0.1
|
||||
* UI Update for web config.
|
||||
* UI Now support for themes. (auto, dark, light -or- custom)
|
||||
|
|
@ -598,10 +606,11 @@ All non commercial projects can be run using our open source code under GPLv2 li
|
|||
See License.md for more details.
|
||||
|
||||
|
||||
|
||||
# Legal and Safety Disclaimer
|
||||
[Please read](https://github.com/aqualinkd/Disclaimer.md)
|
||||
|
||||
# Donation
|
||||
If you still like this project, please consider buying me a cup of coffee :)
|
||||
<br>
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SEGN9UNS38TXJ)
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SEGN9UNS38TXJ)
|
||||
|
||||
|
|
|
|||
|
|
@ -299,9 +299,8 @@ bool find_pda_menu_item(struct aqualinkdata *aqdata, char *menuText, int charlim
|
|||
int j;
|
||||
for(j=0; j < 20; j++) {
|
||||
send_pda_cmd(KEY_PDA_DOWN);
|
||||
//delay(500);
|
||||
//wait_for_empty_cmd_buffer();
|
||||
//waitForPDAMessageType(aqdata,CMD_PDA_HIGHLIGHT,2);
|
||||
// NSF MAYBE ADD THIS NEEd TO TEST EVERYTHING ON ALL VERSIONS FIRST.
|
||||
//waitForPDAMessages(aqdata, 1); // PDA needs another message sometimes (probably not using )
|
||||
waitForPDAMessageTypes(aqdata,CMD_PDA_HIGHLIGHT,CMD_MSG_LONG,8);
|
||||
//waitForMessage(aqdata, NULL, 1);
|
||||
index = (charlimit == 0)?pda_find_m_index(menuText):pda_find_m_index_case(menuText, charlimit);
|
||||
|
|
@ -991,6 +990,7 @@ void *set_aqualink_PDA_light_mode( void *ptr )
|
|||
} else { // set mode.
|
||||
if (strncasecmp(pda_m_line(3),"Light will turn", 15) == 0) {
|
||||
// If light is currently on, we will get this message, and need to clear it.
|
||||
waitForPDAMessages(aqdata, 5); // PDA needs another 5 messages. Otherwise, sometime it does not observed PDA SELECT
|
||||
send_pda_cmd(KEY_PDA_SELECT);
|
||||
waitForPDAMessageTypes(aqdata,CMD_PDA_HIGHLIGHT,CMD_PDA_HIGHLIGHTCHARS,15);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@
|
|||
"heater_slider_min": 36,
|
||||
"heater_slider_max": 104,
|
||||
"timer_slider_min": 0,
|
||||
"timer_slider_max": 120,
|
||||
"timer_slider_max": 240,
|
||||
"timer_slider_step": 1
|
||||
},
|
||||
"tile_thresholds": {
|
||||
|
|
|
|||
|
|
@ -2338,8 +2338,10 @@
|
|||
if (_temperature_units != 'c') { // Change to DegF
|
||||
//slider.min = 36;
|
||||
//slider.max = 104;
|
||||
slider.min = ((typeof heater_slider_min !== 'undefined')?heater_slider_min:36);
|
||||
slider.max = ((typeof heater_slider_max !== 'undefined')?heater_slider_max:104);
|
||||
//slider.min = ((typeof heater_slider_min !== 'undefined')?heater_slider_min:36);
|
||||
//slider.max = ((typeof heater_slider_max !== 'undefined')?heater_slider_max:104);
|
||||
slider.min = ((_config?.slider_range?.heater_slider_min)?_config.slider_range.heater_slider_min:0);
|
||||
slider.max = ((_config?.slider_range?.heater_slider_max)?_config.slider_range.heater_slider_max:104);
|
||||
slider.step = 1;
|
||||
} else { // Change to DegF
|
||||
slider.min = 0;
|
||||
|
|
@ -2475,9 +2477,14 @@
|
|||
}
|
||||
|
||||
if (typeof tm_slider !== 'undefined' && tm_slider != null) {
|
||||
tm_slider.min = ((typeof timer_slider_min !== 'undefined')?timer_slider_min:0);
|
||||
tm_slider.max = ((typeof timer_slider_max !== 'undefined')?timer_slider_max:360);
|
||||
tm_slider.step = ((typeof timer_slider_step !== 'undefined')?timer_slider_step:10);
|
||||
//tm_slider.min = ((typeof timer_slider_min !== 'undefined')?timer_slider_min:0);
|
||||
//tm_slider.max = ((typeof timer_slider_max !== 'undefined')?timer_slider_max:120);
|
||||
//tm_slider.step = ((typeof timer_slider_step !== 'undefined')?timer_slider_step:10);
|
||||
|
||||
tm_slider.min = ((_config?.slider_range?.timer_slider_min)?_config.slider_range.timer_slider_min:0);
|
||||
tm_slider.max = ((_config?.slider_range?.timer_slider_max)?_config.slider_range.timer_slider_max:360);
|
||||
tm_slider.step = ((_config?.slider_range?.timer_slider_step)?_config.slider_range.timer_slider_step:10);
|
||||
|
||||
tm_ext = ' runtime (min)';
|
||||
|
||||
tm_slider.value = tm_slider.min;
|
||||
|
|
|
|||
Loading…
Reference in New Issue