pyintellicenter 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyintellicenter-0.0.3/.gitignore +99 -0
- pyintellicenter-0.0.3/LICENSE +21 -0
- pyintellicenter-0.0.3/PKG-INFO +264 -0
- pyintellicenter-0.0.3/README.md +229 -0
- pyintellicenter-0.0.3/pyproject.toml +128 -0
- pyintellicenter-0.0.3/src/pyintellicenter/__init__.py +285 -0
- pyintellicenter-0.0.3/src/pyintellicenter/attributes/__init__.py +266 -0
- pyintellicenter-0.0.3/src/pyintellicenter/attributes/body.py +63 -0
- pyintellicenter-0.0.3/src/pyintellicenter/attributes/circuit.py +61 -0
- pyintellicenter-0.0.3/src/pyintellicenter/attributes/constants.py +146 -0
- pyintellicenter-0.0.3/src/pyintellicenter/attributes/equipment.py +147 -0
- pyintellicenter-0.0.3/src/pyintellicenter/attributes/misc.py +84 -0
- pyintellicenter-0.0.3/src/pyintellicenter/attributes/schedule.py +54 -0
- pyintellicenter-0.0.3/src/pyintellicenter/attributes/system.py +107 -0
- pyintellicenter-0.0.3/src/pyintellicenter/connection.py +367 -0
- pyintellicenter-0.0.3/src/pyintellicenter/controller.py +844 -0
- pyintellicenter-0.0.3/src/pyintellicenter/discovery.py +346 -0
- pyintellicenter-0.0.3/src/pyintellicenter/exceptions.py +80 -0
- pyintellicenter-0.0.3/src/pyintellicenter/model.py +333 -0
- pyintellicenter-0.0.3/src/pyintellicenter/types.py +53 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# PyInstaller
|
|
28
|
+
*.manifest
|
|
29
|
+
*.spec
|
|
30
|
+
|
|
31
|
+
# Installer logs
|
|
32
|
+
pip-log.txt
|
|
33
|
+
pip-delete-this-directory.txt
|
|
34
|
+
|
|
35
|
+
# Unit test / coverage reports
|
|
36
|
+
htmlcov/
|
|
37
|
+
.tox/
|
|
38
|
+
.nox/
|
|
39
|
+
.coverage
|
|
40
|
+
.coverage.*
|
|
41
|
+
.cache
|
|
42
|
+
nosetests.xml
|
|
43
|
+
coverage.xml
|
|
44
|
+
*.cover
|
|
45
|
+
*.py,cover
|
|
46
|
+
.hypothesis/
|
|
47
|
+
.pytest_cache/
|
|
48
|
+
pytest_cache/
|
|
49
|
+
|
|
50
|
+
# Translations
|
|
51
|
+
*.mo
|
|
52
|
+
*.pot
|
|
53
|
+
|
|
54
|
+
# Environments
|
|
55
|
+
.env
|
|
56
|
+
.venv
|
|
57
|
+
env/
|
|
58
|
+
venv/
|
|
59
|
+
ENV/
|
|
60
|
+
env.bak/
|
|
61
|
+
venv.bak/
|
|
62
|
+
|
|
63
|
+
# Spyder project settings
|
|
64
|
+
.spyderproject
|
|
65
|
+
.spyproject
|
|
66
|
+
|
|
67
|
+
# Rope project settings
|
|
68
|
+
.ropeproject
|
|
69
|
+
|
|
70
|
+
# mkdocs documentation
|
|
71
|
+
/site
|
|
72
|
+
|
|
73
|
+
# mypy
|
|
74
|
+
.mypy_cache/
|
|
75
|
+
.dmypy.json
|
|
76
|
+
dmypy.json
|
|
77
|
+
|
|
78
|
+
# Pyre type checker
|
|
79
|
+
.pyre/
|
|
80
|
+
|
|
81
|
+
# pytype static type analyzer
|
|
82
|
+
.pytype/
|
|
83
|
+
|
|
84
|
+
# Cython debug symbols
|
|
85
|
+
cython_debug/
|
|
86
|
+
|
|
87
|
+
# IDE
|
|
88
|
+
.idea/
|
|
89
|
+
.vscode/
|
|
90
|
+
*.swp
|
|
91
|
+
*.swo
|
|
92
|
+
*~
|
|
93
|
+
|
|
94
|
+
# OS
|
|
95
|
+
.DS_Store
|
|
96
|
+
Thumbs.db
|
|
97
|
+
|
|
98
|
+
# Project specific
|
|
99
|
+
*.log
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 joyfulhouse
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyintellicenter
|
|
3
|
+
Version: 0.0.3
|
|
4
|
+
Summary: Python library for Pentair IntelliCenter pool control systems
|
|
5
|
+
Project-URL: Homepage, https://github.com/joyfulhouse/pyintellicenter
|
|
6
|
+
Project-URL: Documentation, https://github.com/joyfulhouse/pyintellicenter#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/joyfulhouse/pyintellicenter.git
|
|
8
|
+
Project-URL: Issues, https://github.com/joyfulhouse/pyintellicenter/issues
|
|
9
|
+
Author-email: joyfulhouse <joyfulhouse@users.noreply.github.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: asyncio,automation,home-assistant,intellicenter,pentair,pool
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Framework :: AsyncIO
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Home Automation
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.13
|
|
24
|
+
Requires-Dist: orjson>=3.11.4
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: mypy>=1.18.2; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=9.0.1; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.14.6; extra == 'dev'
|
|
31
|
+
Requires-Dist: zeroconf>=0.136.2; extra == 'dev'
|
|
32
|
+
Provides-Extra: discovery
|
|
33
|
+
Requires-Dist: zeroconf>=0.136.2; extra == 'discovery'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# pyintellicenter
|
|
37
|
+
|
|
38
|
+
[](https://pypi.org/project/pyintellicenter/)
|
|
39
|
+
[](https://pypi.org/project/pyintellicenter/)
|
|
40
|
+
[](https://github.com/joyfulhouse/pyintellicenter/actions/workflows/test.yml)
|
|
41
|
+
[](https://opensource.org/licenses/MIT)
|
|
42
|
+
|
|
43
|
+
Python library for communicating with Pentair IntelliCenter pool control systems over local network.
|
|
44
|
+
|
|
45
|
+
> ⚠️ **Alpha Release**: This library is in early development. API may change between versions.
|
|
46
|
+
|
|
47
|
+
## Features
|
|
48
|
+
|
|
49
|
+
- **Local Communication**: Direct TCP connection to IntelliCenter (no cloud required)
|
|
50
|
+
- **Real-time Updates**: Push-based notifications via NotifyList protocol
|
|
51
|
+
- **Async/Await**: Built on Python asyncio for efficient I/O
|
|
52
|
+
- **Type Annotations**: Full type hints for IDE support and static analysis
|
|
53
|
+
- **Robust Connection Handling**: Automatic reconnection with exponential backoff
|
|
54
|
+
- **Resilient**: Circuit breaker pattern, connection metrics, comprehensive error handling
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install pyintellicenter
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or install from GitHub:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install git+https://github.com/joyfulhouse/pyintellicenter.git
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Requirements
|
|
69
|
+
|
|
70
|
+
- Python 3.11+
|
|
71
|
+
- Pentair IntelliCenter controller (i5P, i7P, i9P, or i10P)
|
|
72
|
+
- Local network access to IntelliCenter (TCP port 6681)
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
import asyncio
|
|
78
|
+
from pyintellicenter import ModelController, PoolModel, ConnectionHandler
|
|
79
|
+
|
|
80
|
+
async def main():
|
|
81
|
+
# Create a model to hold equipment state
|
|
82
|
+
model = PoolModel()
|
|
83
|
+
|
|
84
|
+
# Create controller connected to your IntelliCenter
|
|
85
|
+
controller = ModelController("192.168.1.100", model)
|
|
86
|
+
|
|
87
|
+
# Use ConnectionHandler for automatic reconnection
|
|
88
|
+
handler = ConnectionHandler(controller)
|
|
89
|
+
await handler.start()
|
|
90
|
+
|
|
91
|
+
# Access system information
|
|
92
|
+
print(f"Connected to: {controller.systemInfo.propName}")
|
|
93
|
+
print(f"Software version: {controller.systemInfo.swVersion}")
|
|
94
|
+
|
|
95
|
+
# List all equipment
|
|
96
|
+
for obj in model:
|
|
97
|
+
print(f"{obj.sname} ({obj.objtype}): {obj.status}")
|
|
98
|
+
|
|
99
|
+
# Control equipment
|
|
100
|
+
pool = model.getByType("BODY", "POOL")[0]
|
|
101
|
+
controller.requestChanges(pool.objnam, {"STATUS": "ON"})
|
|
102
|
+
|
|
103
|
+
asyncio.run(main())
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Architecture
|
|
107
|
+
|
|
108
|
+
The library is organized in layers:
|
|
109
|
+
|
|
110
|
+
### Protocol Layer (`protocol.py`)
|
|
111
|
+
- `ICProtocol`: Low-level asyncio protocol handling TCP communication
|
|
112
|
+
- JSON message framing (messages terminated with `\r\n`)
|
|
113
|
+
- Flow control (one request at a time)
|
|
114
|
+
- Keepalive queries for connection health
|
|
115
|
+
|
|
116
|
+
### Controller Layer (`controller.py`)
|
|
117
|
+
- `BaseController`: Basic connection and command handling
|
|
118
|
+
- `ModelController`: State management with PoolModel
|
|
119
|
+
- `ConnectionHandler`: Automatic reconnection with exponential backoff
|
|
120
|
+
- `SystemInfo`: System metadata (version, units, unique ID)
|
|
121
|
+
- `ConnectionMetrics`: Request/response statistics
|
|
122
|
+
|
|
123
|
+
### Model Layer (`model.py`)
|
|
124
|
+
- `PoolModel`: Collection of pool equipment objects
|
|
125
|
+
- `PoolObject`: Individual equipment item (pump, light, heater, etc.)
|
|
126
|
+
|
|
127
|
+
### Attributes (`attributes.py`)
|
|
128
|
+
- Type and attribute constants for all equipment types
|
|
129
|
+
- `BODY_TYPE`, `PUMP_TYPE`, `CIRCUIT_TYPE`, etc.
|
|
130
|
+
- `STATUS_ATTR`, `SNAME_ATTR`, `OBJTYP_ATTR`, etc.
|
|
131
|
+
|
|
132
|
+
## API Reference
|
|
133
|
+
|
|
134
|
+
### ModelController
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
controller = ModelController(
|
|
138
|
+
host="192.168.1.100", # IntelliCenter IP address
|
|
139
|
+
model=PoolModel(), # Model to populate
|
|
140
|
+
port=6681, # TCP port (default: 6681)
|
|
141
|
+
keepalive_interval=90, # Keepalive query interval in seconds
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Start connection and populate model
|
|
145
|
+
await controller.start()
|
|
146
|
+
|
|
147
|
+
# Send changes to equipment
|
|
148
|
+
controller.requestChanges(objnam, {"STATUS": "ON"})
|
|
149
|
+
|
|
150
|
+
# Access system info
|
|
151
|
+
info = controller.systemInfo
|
|
152
|
+
print(info.propName, info.swVersion, info.usesMetric)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### ConnectionHandler
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
handler = ConnectionHandler(
|
|
159
|
+
controller,
|
|
160
|
+
timeBetweenReconnects=30, # Initial reconnect delay (seconds)
|
|
161
|
+
disconnectDebounceTime=15, # Grace period before marking disconnected
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Start with automatic reconnection
|
|
165
|
+
await handler.start()
|
|
166
|
+
|
|
167
|
+
# Stop and cleanup
|
|
168
|
+
handler.stop()
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### PoolModel
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
model = PoolModel()
|
|
175
|
+
|
|
176
|
+
# Iterate all objects
|
|
177
|
+
for obj in model:
|
|
178
|
+
print(obj.sname)
|
|
179
|
+
|
|
180
|
+
# Get by type
|
|
181
|
+
bodies = model.getByType("BODY")
|
|
182
|
+
pool = model.getByType("BODY", "POOL")[0]
|
|
183
|
+
pumps = model.getByType("PUMP")
|
|
184
|
+
|
|
185
|
+
# Get by object name
|
|
186
|
+
obj = model["POOL1"]
|
|
187
|
+
|
|
188
|
+
# Get children of an object
|
|
189
|
+
children = model.getChildren(panel)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### PoolObject
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
obj = model["PUMP1"]
|
|
196
|
+
|
|
197
|
+
# Properties
|
|
198
|
+
obj.objnam # Object name (e.g., "PUMP1")
|
|
199
|
+
obj.sname # Friendly name (e.g., "Pool Pump")
|
|
200
|
+
obj.objtype # Object type (e.g., "PUMP")
|
|
201
|
+
obj.subtype # Subtype (e.g., "VSF")
|
|
202
|
+
obj.status # Current status
|
|
203
|
+
|
|
204
|
+
# Check type
|
|
205
|
+
obj.isALight # Is this a light?
|
|
206
|
+
obj.isALightShow # Is this a light show?
|
|
207
|
+
obj.isFeatured # Is this featured?
|
|
208
|
+
obj.supportColorEffects # Supports color effects?
|
|
209
|
+
|
|
210
|
+
# Access attributes
|
|
211
|
+
rpm = obj["RPM"]
|
|
212
|
+
power = obj["PWR"]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Equipment Types
|
|
216
|
+
|
|
217
|
+
| Type | Description | Common Subtypes |
|
|
218
|
+
|------|-------------|-----------------|
|
|
219
|
+
| `BODY` | Body of water | `POOL`, `SPA` |
|
|
220
|
+
| `PUMP` | Pump | `SPEED`, `FLOW`, `VSF` |
|
|
221
|
+
| `CIRCUIT` | Circuit/Feature | `LIGHT`, `INTELLI`, `GLOW`, `DIMMER` |
|
|
222
|
+
| `HEATER` | Heater | `GENERIC`, `SOLAR`, `ULTRA` |
|
|
223
|
+
| `CHEM` | Chemistry | `ICHLOR`, `ICHEM` |
|
|
224
|
+
| `SENSE` | Sensor | `POOL`, `AIR`, `SOLAR` |
|
|
225
|
+
| `SCHED` | Schedule | - |
|
|
226
|
+
|
|
227
|
+
## Connection Behavior
|
|
228
|
+
|
|
229
|
+
The library implements robust connection handling:
|
|
230
|
+
|
|
231
|
+
1. **Initial Connection**: Connects and fetches system info + all equipment
|
|
232
|
+
2. **Keepalive**: Sends lightweight queries every 90 seconds (configurable)
|
|
233
|
+
3. **Push Updates**: Receives real-time NotifyList updates from IntelliCenter
|
|
234
|
+
4. **Reconnection**: Exponential backoff starting at 30 seconds (configurable)
|
|
235
|
+
5. **Circuit Breaker**: Pauses after 5 consecutive failures
|
|
236
|
+
|
|
237
|
+
## Development
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Clone repository
|
|
241
|
+
git clone https://github.com/joyfulhouse/pyintellicenter.git
|
|
242
|
+
cd pyintellicenter
|
|
243
|
+
|
|
244
|
+
# Install with dev dependencies
|
|
245
|
+
pip install -e ".[dev]"
|
|
246
|
+
|
|
247
|
+
# Run tests
|
|
248
|
+
pytest
|
|
249
|
+
|
|
250
|
+
# Run linting
|
|
251
|
+
ruff check src tests
|
|
252
|
+
ruff format src tests
|
|
253
|
+
|
|
254
|
+
# Run type checking
|
|
255
|
+
mypy src
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## License
|
|
259
|
+
|
|
260
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
261
|
+
|
|
262
|
+
## Related Projects
|
|
263
|
+
|
|
264
|
+
- [intellicenter](https://github.com/joyfulhouse/intellicenter) - Home Assistant integration using this library
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# pyintellicenter
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/pyintellicenter/)
|
|
4
|
+
[](https://pypi.org/project/pyintellicenter/)
|
|
5
|
+
[](https://github.com/joyfulhouse/pyintellicenter/actions/workflows/test.yml)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
Python library for communicating with Pentair IntelliCenter pool control systems over local network.
|
|
9
|
+
|
|
10
|
+
> ⚠️ **Alpha Release**: This library is in early development. API may change between versions.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Local Communication**: Direct TCP connection to IntelliCenter (no cloud required)
|
|
15
|
+
- **Real-time Updates**: Push-based notifications via NotifyList protocol
|
|
16
|
+
- **Async/Await**: Built on Python asyncio for efficient I/O
|
|
17
|
+
- **Type Annotations**: Full type hints for IDE support and static analysis
|
|
18
|
+
- **Robust Connection Handling**: Automatic reconnection with exponential backoff
|
|
19
|
+
- **Resilient**: Circuit breaker pattern, connection metrics, comprehensive error handling
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install pyintellicenter
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or install from GitHub:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install git+https://github.com/joyfulhouse/pyintellicenter.git
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Requirements
|
|
34
|
+
|
|
35
|
+
- Python 3.11+
|
|
36
|
+
- Pentair IntelliCenter controller (i5P, i7P, i9P, or i10P)
|
|
37
|
+
- Local network access to IntelliCenter (TCP port 6681)
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import asyncio
|
|
43
|
+
from pyintellicenter import ModelController, PoolModel, ConnectionHandler
|
|
44
|
+
|
|
45
|
+
async def main():
|
|
46
|
+
# Create a model to hold equipment state
|
|
47
|
+
model = PoolModel()
|
|
48
|
+
|
|
49
|
+
# Create controller connected to your IntelliCenter
|
|
50
|
+
controller = ModelController("192.168.1.100", model)
|
|
51
|
+
|
|
52
|
+
# Use ConnectionHandler for automatic reconnection
|
|
53
|
+
handler = ConnectionHandler(controller)
|
|
54
|
+
await handler.start()
|
|
55
|
+
|
|
56
|
+
# Access system information
|
|
57
|
+
print(f"Connected to: {controller.systemInfo.propName}")
|
|
58
|
+
print(f"Software version: {controller.systemInfo.swVersion}")
|
|
59
|
+
|
|
60
|
+
# List all equipment
|
|
61
|
+
for obj in model:
|
|
62
|
+
print(f"{obj.sname} ({obj.objtype}): {obj.status}")
|
|
63
|
+
|
|
64
|
+
# Control equipment
|
|
65
|
+
pool = model.getByType("BODY", "POOL")[0]
|
|
66
|
+
controller.requestChanges(pool.objnam, {"STATUS": "ON"})
|
|
67
|
+
|
|
68
|
+
asyncio.run(main())
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Architecture
|
|
72
|
+
|
|
73
|
+
The library is organized in layers:
|
|
74
|
+
|
|
75
|
+
### Protocol Layer (`protocol.py`)
|
|
76
|
+
- `ICProtocol`: Low-level asyncio protocol handling TCP communication
|
|
77
|
+
- JSON message framing (messages terminated with `\r\n`)
|
|
78
|
+
- Flow control (one request at a time)
|
|
79
|
+
- Keepalive queries for connection health
|
|
80
|
+
|
|
81
|
+
### Controller Layer (`controller.py`)
|
|
82
|
+
- `BaseController`: Basic connection and command handling
|
|
83
|
+
- `ModelController`: State management with PoolModel
|
|
84
|
+
- `ConnectionHandler`: Automatic reconnection with exponential backoff
|
|
85
|
+
- `SystemInfo`: System metadata (version, units, unique ID)
|
|
86
|
+
- `ConnectionMetrics`: Request/response statistics
|
|
87
|
+
|
|
88
|
+
### Model Layer (`model.py`)
|
|
89
|
+
- `PoolModel`: Collection of pool equipment objects
|
|
90
|
+
- `PoolObject`: Individual equipment item (pump, light, heater, etc.)
|
|
91
|
+
|
|
92
|
+
### Attributes (`attributes.py`)
|
|
93
|
+
- Type and attribute constants for all equipment types
|
|
94
|
+
- `BODY_TYPE`, `PUMP_TYPE`, `CIRCUIT_TYPE`, etc.
|
|
95
|
+
- `STATUS_ATTR`, `SNAME_ATTR`, `OBJTYP_ATTR`, etc.
|
|
96
|
+
|
|
97
|
+
## API Reference
|
|
98
|
+
|
|
99
|
+
### ModelController
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
controller = ModelController(
|
|
103
|
+
host="192.168.1.100", # IntelliCenter IP address
|
|
104
|
+
model=PoolModel(), # Model to populate
|
|
105
|
+
port=6681, # TCP port (default: 6681)
|
|
106
|
+
keepalive_interval=90, # Keepalive query interval in seconds
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Start connection and populate model
|
|
110
|
+
await controller.start()
|
|
111
|
+
|
|
112
|
+
# Send changes to equipment
|
|
113
|
+
controller.requestChanges(objnam, {"STATUS": "ON"})
|
|
114
|
+
|
|
115
|
+
# Access system info
|
|
116
|
+
info = controller.systemInfo
|
|
117
|
+
print(info.propName, info.swVersion, info.usesMetric)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### ConnectionHandler
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
handler = ConnectionHandler(
|
|
124
|
+
controller,
|
|
125
|
+
timeBetweenReconnects=30, # Initial reconnect delay (seconds)
|
|
126
|
+
disconnectDebounceTime=15, # Grace period before marking disconnected
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Start with automatic reconnection
|
|
130
|
+
await handler.start()
|
|
131
|
+
|
|
132
|
+
# Stop and cleanup
|
|
133
|
+
handler.stop()
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### PoolModel
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
model = PoolModel()
|
|
140
|
+
|
|
141
|
+
# Iterate all objects
|
|
142
|
+
for obj in model:
|
|
143
|
+
print(obj.sname)
|
|
144
|
+
|
|
145
|
+
# Get by type
|
|
146
|
+
bodies = model.getByType("BODY")
|
|
147
|
+
pool = model.getByType("BODY", "POOL")[0]
|
|
148
|
+
pumps = model.getByType("PUMP")
|
|
149
|
+
|
|
150
|
+
# Get by object name
|
|
151
|
+
obj = model["POOL1"]
|
|
152
|
+
|
|
153
|
+
# Get children of an object
|
|
154
|
+
children = model.getChildren(panel)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### PoolObject
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
obj = model["PUMP1"]
|
|
161
|
+
|
|
162
|
+
# Properties
|
|
163
|
+
obj.objnam # Object name (e.g., "PUMP1")
|
|
164
|
+
obj.sname # Friendly name (e.g., "Pool Pump")
|
|
165
|
+
obj.objtype # Object type (e.g., "PUMP")
|
|
166
|
+
obj.subtype # Subtype (e.g., "VSF")
|
|
167
|
+
obj.status # Current status
|
|
168
|
+
|
|
169
|
+
# Check type
|
|
170
|
+
obj.isALight # Is this a light?
|
|
171
|
+
obj.isALightShow # Is this a light show?
|
|
172
|
+
obj.isFeatured # Is this featured?
|
|
173
|
+
obj.supportColorEffects # Supports color effects?
|
|
174
|
+
|
|
175
|
+
# Access attributes
|
|
176
|
+
rpm = obj["RPM"]
|
|
177
|
+
power = obj["PWR"]
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Equipment Types
|
|
181
|
+
|
|
182
|
+
| Type | Description | Common Subtypes |
|
|
183
|
+
|------|-------------|-----------------|
|
|
184
|
+
| `BODY` | Body of water | `POOL`, `SPA` |
|
|
185
|
+
| `PUMP` | Pump | `SPEED`, `FLOW`, `VSF` |
|
|
186
|
+
| `CIRCUIT` | Circuit/Feature | `LIGHT`, `INTELLI`, `GLOW`, `DIMMER` |
|
|
187
|
+
| `HEATER` | Heater | `GENERIC`, `SOLAR`, `ULTRA` |
|
|
188
|
+
| `CHEM` | Chemistry | `ICHLOR`, `ICHEM` |
|
|
189
|
+
| `SENSE` | Sensor | `POOL`, `AIR`, `SOLAR` |
|
|
190
|
+
| `SCHED` | Schedule | - |
|
|
191
|
+
|
|
192
|
+
## Connection Behavior
|
|
193
|
+
|
|
194
|
+
The library implements robust connection handling:
|
|
195
|
+
|
|
196
|
+
1. **Initial Connection**: Connects and fetches system info + all equipment
|
|
197
|
+
2. **Keepalive**: Sends lightweight queries every 90 seconds (configurable)
|
|
198
|
+
3. **Push Updates**: Receives real-time NotifyList updates from IntelliCenter
|
|
199
|
+
4. **Reconnection**: Exponential backoff starting at 30 seconds (configurable)
|
|
200
|
+
5. **Circuit Breaker**: Pauses after 5 consecutive failures
|
|
201
|
+
|
|
202
|
+
## Development
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Clone repository
|
|
206
|
+
git clone https://github.com/joyfulhouse/pyintellicenter.git
|
|
207
|
+
cd pyintellicenter
|
|
208
|
+
|
|
209
|
+
# Install with dev dependencies
|
|
210
|
+
pip install -e ".[dev]"
|
|
211
|
+
|
|
212
|
+
# Run tests
|
|
213
|
+
pytest
|
|
214
|
+
|
|
215
|
+
# Run linting
|
|
216
|
+
ruff check src tests
|
|
217
|
+
ruff format src tests
|
|
218
|
+
|
|
219
|
+
# Run type checking
|
|
220
|
+
mypy src
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
226
|
+
|
|
227
|
+
## Related Projects
|
|
228
|
+
|
|
229
|
+
- [intellicenter](https://github.com/joyfulhouse/intellicenter) - Home Assistant integration using this library
|