nwp500-python 1.0.0__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.
- nwp500_python-1.0.0/.coveragerc +28 -0
- nwp500_python-1.0.0/.github/copilot-instructions.md +44 -0
- nwp500_python-1.0.0/.github/workflows/ci.yml +84 -0
- nwp500_python-1.0.0/.github/workflows/release.yml +85 -0
- nwp500_python-1.0.0/.gitignore +57 -0
- nwp500_python-1.0.0/.readthedocs.yml +27 -0
- nwp500_python-1.0.0/AUTHORS.rst +5 -0
- nwp500_python-1.0.0/CHANGELOG.rst +268 -0
- nwp500_python-1.0.0/CONTRIBUTING.rst +297 -0
- nwp500_python-1.0.0/LICENSE.txt +21 -0
- nwp500_python-1.0.0/Makefile +69 -0
- nwp500_python-1.0.0/PKG-INFO +249 -0
- nwp500_python-1.0.0/README.rst +212 -0
- nwp500_python-1.0.0/RELEASE.md +330 -0
- nwp500_python-1.0.0/docs/API_CLIENT.rst +541 -0
- nwp500_python-1.0.0/docs/API_REFERENCE.rst +31 -0
- nwp500_python-1.0.0/docs/AUTHENTICATION.rst +605 -0
- nwp500_python-1.0.0/docs/COMMAND_QUEUE.rst +315 -0
- nwp500_python-1.0.0/docs/DEVELOPMENT.rst +344 -0
- nwp500_python-1.0.0/docs/DEVICE_STATUS_FIELDS.rst +534 -0
- nwp500_python-1.0.0/docs/ENERGY_MONITORING.rst +300 -0
- nwp500_python-1.0.0/docs/ERROR_CODES.rst +345 -0
- nwp500_python-1.0.0/docs/EVENT_EMITTER.rst +691 -0
- nwp500_python-1.0.0/docs/MQTT_CLIENT.rst +964 -0
- nwp500_python-1.0.0/docs/MQTT_MESSAGES.rst +378 -0
- nwp500_python-1.0.0/docs/Makefile +29 -0
- nwp500_python-1.0.0/docs/_static/.gitignore +1 -0
- nwp500_python-1.0.0/docs/authors.rst +2 -0
- nwp500_python-1.0.0/docs/changelog.rst +2 -0
- nwp500_python-1.0.0/docs/conf.py +292 -0
- nwp500_python-1.0.0/docs/contributing.rst +1 -0
- nwp500_python-1.0.0/docs/index.rst +361 -0
- nwp500_python-1.0.0/docs/license.rst +7 -0
- nwp500_python-1.0.0/docs/openapi.yaml +529 -0
- nwp500_python-1.0.0/docs/readme.rst +2 -0
- nwp500_python-1.0.0/docs/requirements.txt +6 -0
- nwp500_python-1.0.0/examples/.ruff.toml +4 -0
- nwp500_python-1.0.0/examples/README.md +110 -0
- nwp500_python-1.0.0/examples/api_client_example.py +254 -0
- nwp500_python-1.0.0/examples/auth_constructor_example.py +40 -0
- nwp500_python-1.0.0/examples/authenticate.py +107 -0
- nwp500_python-1.0.0/examples/combined_callbacks.py +164 -0
- nwp500_python-1.0.0/examples/command_queue_demo.py +198 -0
- nwp500_python-1.0.0/examples/device_feature_callback.py +244 -0
- nwp500_python-1.0.0/examples/device_status_callback.py +235 -0
- nwp500_python-1.0.0/examples/device_status_callback_debug.py +199 -0
- nwp500_python-1.0.0/examples/energy_usage_example.py +157 -0
- nwp500_python-1.0.0/examples/event_emitter_demo.py +269 -0
- nwp500_python-1.0.0/examples/improved_auth_pattern.py +64 -0
- nwp500_python-1.0.0/examples/mask.py +64 -0
- nwp500_python-1.0.0/examples/mqtt_client_example.py +231 -0
- nwp500_python-1.0.0/examples/periodic_device_info.py +150 -0
- nwp500_python-1.0.0/examples/periodic_requests.py +238 -0
- nwp500_python-1.0.0/examples/reconnection_demo.py +140 -0
- nwp500_python-1.0.0/examples/simple_periodic_info.py +66 -0
- nwp500_python-1.0.0/examples/simple_periodic_status.py +66 -0
- nwp500_python-1.0.0/examples/test_api_client.py +262 -0
- nwp500_python-1.0.0/examples/test_mqtt_connection.py +100 -0
- nwp500_python-1.0.0/examples/test_mqtt_messaging.py +273 -0
- nwp500_python-1.0.0/examples/test_periodic_minimal.py +88 -0
- nwp500_python-1.0.0/pyproject.toml +95 -0
- nwp500_python-1.0.0/setup.cfg +84 -0
- nwp500_python-1.0.0/setup.py +22 -0
- nwp500_python-1.0.0/src/nwp500/__init__.py +102 -0
- nwp500_python-1.0.0/src/nwp500/api_client.py +373 -0
- nwp500_python-1.0.0/src/nwp500/auth.py +502 -0
- nwp500_python-1.0.0/src/nwp500/config.py +9 -0
- nwp500_python-1.0.0/src/nwp500/constants.py +12 -0
- nwp500_python-1.0.0/src/nwp500/events.py +361 -0
- nwp500_python-1.0.0/src/nwp500/models.py +650 -0
- nwp500_python-1.0.0/src/nwp500/mqtt_client.py +1654 -0
- nwp500_python-1.0.0/src/nwp500/skeleton.py +152 -0
- nwp500_python-1.0.0/src/nwp500_python.egg-info/PKG-INFO +249 -0
- nwp500_python-1.0.0/src/nwp500_python.egg-info/SOURCES.txt +82 -0
- nwp500_python-1.0.0/src/nwp500_python.egg-info/dependency_links.txt +1 -0
- nwp500_python-1.0.0/src/nwp500_python.egg-info/not-zip-safe +1 -0
- nwp500_python-1.0.0/src/nwp500_python.egg-info/requires.txt +15 -0
- nwp500_python-1.0.0/src/nwp500_python.egg-info/top_level.txt +1 -0
- nwp500_python-1.0.0/tests/conftest.py +10 -0
- nwp500_python-1.0.0/tests/test_command_queue.py +84 -0
- nwp500_python-1.0.0/tests/test_events.py +329 -0
- nwp500_python-1.0.0/tests/test_skeleton.py +25 -0
- nwp500_python-1.0.0/tox.ini +104 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# .coveragerc to control coverage.py
|
|
2
|
+
[run]
|
|
3
|
+
branch = True
|
|
4
|
+
source = nwp500
|
|
5
|
+
# omit = bad_file.py
|
|
6
|
+
|
|
7
|
+
[paths]
|
|
8
|
+
source =
|
|
9
|
+
src/
|
|
10
|
+
*/site-packages/
|
|
11
|
+
|
|
12
|
+
[report]
|
|
13
|
+
# Regexes for lines to exclude from consideration
|
|
14
|
+
exclude_lines =
|
|
15
|
+
# Have to re-enable the standard pragma
|
|
16
|
+
pragma: no cover
|
|
17
|
+
|
|
18
|
+
# Don't complain about missing debug-only code:
|
|
19
|
+
def __repr__
|
|
20
|
+
if self\.debug
|
|
21
|
+
|
|
22
|
+
# Don't complain if tests don't hit defensive assertion code:
|
|
23
|
+
raise AssertionError
|
|
24
|
+
raise NotImplementedError
|
|
25
|
+
|
|
26
|
+
# Don't complain if non-runnable code isn't run:
|
|
27
|
+
if 0:
|
|
28
|
+
if __name__ == .__main__.:
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Copilot Instructions for nwp500-python
|
|
2
|
+
|
|
3
|
+
## Project Architecture
|
|
4
|
+
- The codebase is organized around two main components:
|
|
5
|
+
- **API Client (`src/nwp500/api_client.py`)**: Handles RESTful communication with the Navien cloud API for device management, status, and control.
|
|
6
|
+
- **MQTT Client (`src/nwp500/mqtt_client.py`)**: Manages real-time device communication using AWS IoT Core and MQTT protocol. Uses AWS credentials from authentication.
|
|
7
|
+
- **Authentication (`src/nwp500/auth.py`)**: Provides JWT and AWS credential management for both API and MQTT clients.
|
|
8
|
+
- **Data Models (`src/nwp500/models.py`)**: Defines type-safe device, status, and command structures with automatic unit conversions.
|
|
9
|
+
- **Events (`src/nwp500/events.py`)**: Implements an event-driven callback system for device and system updates.
|
|
10
|
+
|
|
11
|
+
## Developer Workflows
|
|
12
|
+
- **Install dependencies**: `pip install -e .` (development mode)
|
|
13
|
+
- **Run tests**: `pytest` (unit tests in `tests/`)
|
|
14
|
+
- **Lint/format**: `ruff format --check src/ tests/ examples/` (use `ruff format ...` to auto-format)
|
|
15
|
+
- **Build docs**: `tox -e docs` (Sphinx docs in `docs/`)
|
|
16
|
+
- **Preview docs**: `python3 -m http.server --directory docs/_build/html`
|
|
17
|
+
|
|
18
|
+
## Patterns & Conventions
|
|
19
|
+
- **Async context managers** for authentication: `async with NavienAuthClient(email, password) as auth_client:`
|
|
20
|
+
- **Environment variables** for credentials: `NAVIEN_EMAIL`, `NAVIEN_PASSWORD`
|
|
21
|
+
- **Device status fields** use conversion formulas (see `docs/DEVICE_STATUS_FIELDS.rst`)
|
|
22
|
+
- **MQTT topics**: `cmd/{deviceType}/{deviceId}/ctrl` for control, `cmd/{deviceType}/{deviceId}/st` for status
|
|
23
|
+
- **Command queuing**: Commands sent while disconnected are queued and sent when reconnected
|
|
24
|
+
- **No base64 encoding/decoding** of MQTT payloads; all payloads are JSON-encoded/decoded
|
|
25
|
+
|
|
26
|
+
## Integration Points
|
|
27
|
+
- **AWS IoT Core**: MQTT client uses `awscrt` and `awsiot` libraries for connection and messaging
|
|
28
|
+
- **aiohttp**: Used for async HTTP requests to the Navien API
|
|
29
|
+
- **pydantic**: Used for data validation and models
|
|
30
|
+
|
|
31
|
+
## Key Files & Directories
|
|
32
|
+
- `src/nwp500/` - Main library code
|
|
33
|
+
- `examples/` - Example scripts for API and MQTT usage
|
|
34
|
+
- `tests/` - Unit tests
|
|
35
|
+
- `docs/` - Sphinx documentation (see `DEVICE_STATUS_FIELDS.rst`, `MQTT_CLIENT.rst`, etc.)
|
|
36
|
+
|
|
37
|
+
## Troubleshooting
|
|
38
|
+
- If authentication fails, check environment variables and credentials
|
|
39
|
+
- If tests hang, check network connectivity and API endpoint status
|
|
40
|
+
- For MQTT, ensure AWS credentials are valid and endpoint is reachable
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
If any section is unclear or missing important project-specific details, please provide feedback so this guide can be improved for future AI agents.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
permissions:
|
|
3
|
+
contents: read
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [ main, develop ]
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [ main, develop ]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint:
|
|
13
|
+
name: Lint and Format Check
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: '3.10'
|
|
22
|
+
|
|
23
|
+
- name: Install tox
|
|
24
|
+
run: |
|
|
25
|
+
python -m pip install --upgrade pip
|
|
26
|
+
python -m pip install tox
|
|
27
|
+
|
|
28
|
+
- name: Run tox lint
|
|
29
|
+
run: tox -e lint
|
|
30
|
+
|
|
31
|
+
test:
|
|
32
|
+
name: Test on Python ${{ matrix.python-version }}
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
strategy:
|
|
35
|
+
matrix:
|
|
36
|
+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
|
|
37
|
+
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
|
|
41
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
42
|
+
uses: actions/setup-python@v5
|
|
43
|
+
with:
|
|
44
|
+
python-version: ${{ matrix.python-version }}
|
|
45
|
+
|
|
46
|
+
- name: Install tox
|
|
47
|
+
run: |
|
|
48
|
+
python -m pip install --upgrade pip
|
|
49
|
+
python -m pip install tox
|
|
50
|
+
|
|
51
|
+
- name: Run tox tests
|
|
52
|
+
run: tox -e default
|
|
53
|
+
|
|
54
|
+
build:
|
|
55
|
+
name: Build Distribution
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
needs: [lint, test]
|
|
58
|
+
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v4
|
|
61
|
+
with:
|
|
62
|
+
fetch-depth: 0 # Required for setuptools_scm
|
|
63
|
+
|
|
64
|
+
- name: Set up Python
|
|
65
|
+
uses: actions/setup-python@v5
|
|
66
|
+
with:
|
|
67
|
+
python-version: '3.10'
|
|
68
|
+
|
|
69
|
+
- name: Install build dependencies
|
|
70
|
+
run: |
|
|
71
|
+
python -m pip install --upgrade pip
|
|
72
|
+
pip install build twine
|
|
73
|
+
|
|
74
|
+
- name: Build package
|
|
75
|
+
run: python -m build
|
|
76
|
+
|
|
77
|
+
- name: Check distribution
|
|
78
|
+
run: twine check dist/*
|
|
79
|
+
|
|
80
|
+
- name: Upload artifacts
|
|
81
|
+
uses: actions/upload-artifact@v4
|
|
82
|
+
with:
|
|
83
|
+
name: dist
|
|
84
|
+
path: dist/
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint-format-test:
|
|
13
|
+
name: Pre-release Checks
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: '3.10'
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: |
|
|
25
|
+
python -m pip install --upgrade pip
|
|
26
|
+
pip install ruff
|
|
27
|
+
pip install -e ".[testing]"
|
|
28
|
+
|
|
29
|
+
- name: Run ruff linter
|
|
30
|
+
run: ruff check src/ tests/ examples/
|
|
31
|
+
|
|
32
|
+
- name: Check code formatting
|
|
33
|
+
run: ruff format --check src/ tests/ examples/
|
|
34
|
+
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: pytest
|
|
37
|
+
|
|
38
|
+
build-and-publish:
|
|
39
|
+
name: Build and Publish to PyPI
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
needs: lint-format-test
|
|
42
|
+
environment:
|
|
43
|
+
name: pypi
|
|
44
|
+
url: https://pypi.org/p/nwp500-python
|
|
45
|
+
permissions:
|
|
46
|
+
id-token: write # Required for trusted publishing
|
|
47
|
+
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
with:
|
|
51
|
+
fetch-depth: 0 # Required for setuptools_scm
|
|
52
|
+
|
|
53
|
+
- name: Set up Python
|
|
54
|
+
uses: actions/setup-python@v5
|
|
55
|
+
with:
|
|
56
|
+
python-version: '3.10'
|
|
57
|
+
|
|
58
|
+
- name: Install build dependencies
|
|
59
|
+
run: |
|
|
60
|
+
python -m pip install --upgrade pip
|
|
61
|
+
pip install build twine
|
|
62
|
+
|
|
63
|
+
- name: Build package
|
|
64
|
+
run: python -m build
|
|
65
|
+
|
|
66
|
+
- name: Check distribution
|
|
67
|
+
run: twine check dist/*
|
|
68
|
+
|
|
69
|
+
- name: Publish to PyPI
|
|
70
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
71
|
+
|
|
72
|
+
github-release:
|
|
73
|
+
name: Create GitHub Release
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
needs: build-and-publish
|
|
76
|
+
|
|
77
|
+
steps:
|
|
78
|
+
- uses: actions/checkout@v4
|
|
79
|
+
|
|
80
|
+
- name: Create Release
|
|
81
|
+
uses: softprops/action-gh-release@v1
|
|
82
|
+
with:
|
|
83
|
+
generate_release_notes: true
|
|
84
|
+
draft: false
|
|
85
|
+
prerelease: false
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Temporary and binary files
|
|
2
|
+
*~
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.so
|
|
5
|
+
*.cfg
|
|
6
|
+
!.isort.cfg
|
|
7
|
+
!setup.cfg
|
|
8
|
+
*.orig
|
|
9
|
+
*.log
|
|
10
|
+
*.pot
|
|
11
|
+
__pycache__/*
|
|
12
|
+
.cache/*
|
|
13
|
+
.*.swp
|
|
14
|
+
*/.ipynb_checkpoints/*
|
|
15
|
+
.DS_Store
|
|
16
|
+
|
|
17
|
+
# Project files
|
|
18
|
+
.ropeproject
|
|
19
|
+
.project
|
|
20
|
+
.pydevproject
|
|
21
|
+
.settings
|
|
22
|
+
.idea
|
|
23
|
+
.vscode
|
|
24
|
+
tags
|
|
25
|
+
|
|
26
|
+
# Package files
|
|
27
|
+
*.egg
|
|
28
|
+
*.eggs/
|
|
29
|
+
.installed.cfg
|
|
30
|
+
*.egg-info
|
|
31
|
+
|
|
32
|
+
# Unittest and coverage
|
|
33
|
+
htmlcov/*
|
|
34
|
+
.coverage
|
|
35
|
+
.coverage.*
|
|
36
|
+
.tox
|
|
37
|
+
junit*.xml
|
|
38
|
+
coverage.xml
|
|
39
|
+
.pytest_cache/
|
|
40
|
+
|
|
41
|
+
# Build and docs folder/files
|
|
42
|
+
build/*
|
|
43
|
+
dist/*
|
|
44
|
+
sdist/*
|
|
45
|
+
docs/api/*
|
|
46
|
+
docs/_rst/*
|
|
47
|
+
docs/_build/*
|
|
48
|
+
cover/*
|
|
49
|
+
MANIFEST
|
|
50
|
+
|
|
51
|
+
# Per-project virtualenvs
|
|
52
|
+
.venv*/
|
|
53
|
+
venv*/
|
|
54
|
+
.conda*/
|
|
55
|
+
.python-version
|
|
56
|
+
.secrets
|
|
57
|
+
reference/*
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Read the Docs configuration file
|
|
2
|
+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
|
3
|
+
|
|
4
|
+
# Required
|
|
5
|
+
version: 2
|
|
6
|
+
|
|
7
|
+
# Build documentation in the docs/ directory with Sphinx
|
|
8
|
+
sphinx:
|
|
9
|
+
configuration: docs/conf.py
|
|
10
|
+
|
|
11
|
+
# Build documentation with MkDocs
|
|
12
|
+
#mkdocs:
|
|
13
|
+
# configuration: mkdocs.yml
|
|
14
|
+
|
|
15
|
+
# Optionally build your docs in additional formats such as PDF
|
|
16
|
+
formats:
|
|
17
|
+
- pdf
|
|
18
|
+
|
|
19
|
+
build:
|
|
20
|
+
os: ubuntu-22.04
|
|
21
|
+
tools:
|
|
22
|
+
python: "3.11"
|
|
23
|
+
|
|
24
|
+
python:
|
|
25
|
+
install:
|
|
26
|
+
- requirements: docs/requirements.txt
|
|
27
|
+
- {path: ., method: pip}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
=========
|
|
2
|
+
Changelog
|
|
3
|
+
=========
|
|
4
|
+
|
|
5
|
+
Version 0.2 (Unreleased)
|
|
6
|
+
========================
|
|
7
|
+
|
|
8
|
+
Added
|
|
9
|
+
-----
|
|
10
|
+
|
|
11
|
+
- **Event Emitter Pattern (Phase 1)**: Event-driven architecture for device state changes
|
|
12
|
+
|
|
13
|
+
- ``EventEmitter`` base class with multiple listeners per event
|
|
14
|
+
- Async and sync handler support
|
|
15
|
+
- Priority-based execution order (higher priority executes first)
|
|
16
|
+
- One-time listeners with ``once()`` method
|
|
17
|
+
- Dynamic listener management with ``on()``, ``off()``, ``remove_all_listeners()``
|
|
18
|
+
- Event statistics tracking (``listener_count()``, ``event_count()``)
|
|
19
|
+
- ``wait_for()`` pattern for waiting on specific events
|
|
20
|
+
- Thread-safe event emission from MQTT callback threads
|
|
21
|
+
- Automatic state change detection for device monitoring
|
|
22
|
+
- 11 events emitted automatically: ``status_received``, ``feature_received``, ``temperature_changed``, ``mode_changed``, ``power_changed``, ``heating_started``, ``heating_stopped``, ``error_detected``, ``error_cleared``, ``connection_interrupted``, ``connection_resumed``
|
|
23
|
+
- NavienMqttClient now inherits from EventEmitter
|
|
24
|
+
- Full backward compatibility with existing callback API
|
|
25
|
+
- 19 unit tests with 93% code coverage
|
|
26
|
+
- Example: ``event_emitter_demo.py``
|
|
27
|
+
- Documentation: ``EVENT_EMITTER.rst``, ``EVENT_QUICK_REFERENCE.rst``, ``EVENT_ARCHITECTURE.rst``
|
|
28
|
+
|
|
29
|
+
- **Authentication**: Simplified constructor-based authentication
|
|
30
|
+
|
|
31
|
+
- ``NavienAuthClient`` now requires ``user_id`` and ``password`` in constructor
|
|
32
|
+
- Automatic authentication when entering async context manager
|
|
33
|
+
- No need to call ``sign_in()`` manually
|
|
34
|
+
- Breaking change: credentials are now required parameters
|
|
35
|
+
- Updated all 18 example files to use new pattern
|
|
36
|
+
- Updated all documentation with new authentication examples
|
|
37
|
+
|
|
38
|
+
- **MQTT Command Queue**: Automatic command queuing when disconnected
|
|
39
|
+
|
|
40
|
+
- Commands sent while disconnected are automatically queued
|
|
41
|
+
- Queue processed in FIFO order when connection is restored
|
|
42
|
+
- Configurable queue size (default: 100 commands)
|
|
43
|
+
- Automatic oldest-command-dropping when queue is full
|
|
44
|
+
- Enabled by default for reliability
|
|
45
|
+
- ``queued_commands_count`` property for monitoring
|
|
46
|
+
- ``clear_command_queue()`` method for manual management
|
|
47
|
+
- Integrates seamlessly with automatic reconnection
|
|
48
|
+
- Example: ``command_queue_demo.py``
|
|
49
|
+
- Documentation: ``COMMAND_QUEUE.rst``
|
|
50
|
+
|
|
51
|
+
- **MQTT Reconnection**: Automatic reconnection with exponential backoff
|
|
52
|
+
|
|
53
|
+
- Automatic reconnection on connection interruption
|
|
54
|
+
- Configurable exponential backoff (default: 1s, 2s, 4s, 8s, ... up to 120s)
|
|
55
|
+
- Configurable max attempts (default: 10)
|
|
56
|
+
- Connection state properties: ``is_reconnecting``, ``reconnect_attempts``
|
|
57
|
+
- User callbacks for connection interruption and resumption events
|
|
58
|
+
- Manual disconnect detection to prevent unwanted reconnection
|
|
59
|
+
- ``MqttConnectionConfig`` with reconnection settings
|
|
60
|
+
- Example: ``reconnection_demo.py``
|
|
61
|
+
- Documentation: Added reconnection section to MQTT_CLIENT.rst
|
|
62
|
+
|
|
63
|
+
- **MQTT Client**: Complete implementation of real-time device communication
|
|
64
|
+
|
|
65
|
+
- WebSocket MQTT connection to AWS IoT Core
|
|
66
|
+
- Device subscription and message handling
|
|
67
|
+
- Status request methods (device info, device status)
|
|
68
|
+
- Control commands for device management
|
|
69
|
+
- Topic pattern matching with wildcard support
|
|
70
|
+
- Connection lifecycle management (connect, disconnect, reconnect)
|
|
71
|
+
|
|
72
|
+
- **Device Control**: Fully implemented and verified control commands
|
|
73
|
+
|
|
74
|
+
- Power control (on/off) with correct command codes
|
|
75
|
+
- DHW mode control (Heat Pump, Electric, Energy Saver, High Demand)
|
|
76
|
+
- DHW temperature control with 20°F offset handling
|
|
77
|
+
- App connection signaling
|
|
78
|
+
- Helper method for display-value temperature control
|
|
79
|
+
|
|
80
|
+
- **Typed Callbacks**: 100% coverage of all MQTT response types
|
|
81
|
+
|
|
82
|
+
- ``subscribe_device_status()`` - Automatic parsing of status messages into ``DeviceStatus`` objects
|
|
83
|
+
- ``subscribe_device_feature()`` - Automatic parsing of feature messages into ``DeviceFeature`` objects
|
|
84
|
+
- ``subscribe_energy_usage()`` - Automatic parsing of energy usage responses into ``EnergyUsageResponse`` objects
|
|
85
|
+
- Type-safe callbacks with IDE autocomplete support
|
|
86
|
+
- Comprehensive error handling and logging
|
|
87
|
+
- Example scripts demonstrating usage patterns
|
|
88
|
+
|
|
89
|
+
- **Energy Usage API (EMS)**: Historical energy consumption data
|
|
90
|
+
|
|
91
|
+
- ``request_energy_usage()`` - Query daily energy usage for specified month(s)
|
|
92
|
+
- ``EnergyUsageResponse`` dataclass with daily breakdown
|
|
93
|
+
- ``EnergyUsageTotal`` with percentage calculations
|
|
94
|
+
- ``MonthlyEnergyData`` with per-day access methods
|
|
95
|
+
- ``EnergyUsageData`` for individual day/month metrics
|
|
96
|
+
- Heat pump vs. electric element usage tracking
|
|
97
|
+
- Operating time statistics (hours)
|
|
98
|
+
- Energy consumption data (Watt-hours)
|
|
99
|
+
- Efficiency percentage calculations
|
|
100
|
+
|
|
101
|
+
- **Data Models**: Comprehensive type-safe models
|
|
102
|
+
|
|
103
|
+
- ``DeviceStatus`` dataclass with 125 sensor and operational fields
|
|
104
|
+
- ``DeviceFeature`` dataclass with 46 capability and configuration fields
|
|
105
|
+
- ``EnergyUsageResponse`` dataclass for historical energy data
|
|
106
|
+
- ``EnergyUsageTotal`` with aggregated statistics and percentages
|
|
107
|
+
- ``MonthlyEnergyData`` with daily breakdown per month
|
|
108
|
+
- ``EnergyUsageData`` for individual day/month metrics
|
|
109
|
+
- ``OperationMode`` enum including STANDBY state (value 0)
|
|
110
|
+
- ``TemperatureUnit`` enum (Celsius/Fahrenheit)
|
|
111
|
+
- MQTT command structures
|
|
112
|
+
- Authentication tokens and user info
|
|
113
|
+
|
|
114
|
+
- **API Client**: High-level REST API client
|
|
115
|
+
|
|
116
|
+
- Device listing and information retrieval
|
|
117
|
+
- Firmware information queries
|
|
118
|
+
- Time-of-Use (TOU) schedule management
|
|
119
|
+
- Push notification token management
|
|
120
|
+
- Async context manager support
|
|
121
|
+
- Automatic session management
|
|
122
|
+
|
|
123
|
+
- **Authentication**: AWS Cognito integration
|
|
124
|
+
|
|
125
|
+
- Sign-in with email/password
|
|
126
|
+
- Access token management
|
|
127
|
+
- Token refresh functionality
|
|
128
|
+
- AWS IoT credentials extraction for MQTT
|
|
129
|
+
- Async context manager support
|
|
130
|
+
|
|
131
|
+
- **Documentation**: Complete protocol and API documentation
|
|
132
|
+
|
|
133
|
+
- MQTT message format specifications
|
|
134
|
+
- Energy usage query API documentation (EMS data)
|
|
135
|
+
- API client usage guide
|
|
136
|
+
- MQTT client usage guide
|
|
137
|
+
- Typed callbacks implementation guide
|
|
138
|
+
- Control command reference with verified command codes
|
|
139
|
+
- Example scripts for common use cases
|
|
140
|
+
- Comprehensive troubleshooting guides
|
|
141
|
+
- Complete energy data reference (ENERGY_DATA_SUMMARY.md)
|
|
142
|
+
|
|
143
|
+
- **Examples**: Production-ready example scripts
|
|
144
|
+
|
|
145
|
+
- ``device_status_callback.py`` - Real-time status monitoring with typed callbacks
|
|
146
|
+
- ``device_feature_callback.py`` - Device capabilities and firmware info
|
|
147
|
+
- ``combined_callbacks.py`` - Both status and feature callbacks together
|
|
148
|
+
- ``mqtt_client_example.py`` - Complete MQTT usage demonstration
|
|
149
|
+
- ``energy_usage_example.py`` - Historical energy usage monitoring and analysis
|
|
150
|
+
- ``reconnection_demo.py`` - MQTT automatic reconnection demonstration
|
|
151
|
+
- ``auth_constructor_example.py`` - Simplified authentication pattern
|
|
152
|
+
|
|
153
|
+
Changed
|
|
154
|
+
-------
|
|
155
|
+
|
|
156
|
+
- **Breaking**: Python version requirement updated to 3.9+
|
|
157
|
+
|
|
158
|
+
- Minimum Python version is now 3.9 (was 3.8)
|
|
159
|
+
- Migrated to native type hints (PEP 585): ``dict[str, Any]`` instead of ``Dict[str, Any]``
|
|
160
|
+
- Removed ``typing.Dict``, ``typing.List``, ``typing.Deque`` imports
|
|
161
|
+
- Cleaner, more readable code with modern Python features
|
|
162
|
+
- Added Python version classifiers (3.9-3.13) to setup.cfg
|
|
163
|
+
- Updated ruff target-version to py39
|
|
164
|
+
|
|
165
|
+
- **Breaking**: ``NavienAuthClient`` constructor signature
|
|
166
|
+
|
|
167
|
+
- Now requires ``user_id`` and ``password`` as first parameters
|
|
168
|
+
- Old: ``NavienAuthClient()`` then ``await client.sign_in(email, password)``
|
|
169
|
+
- New: ``NavienAuthClient(email, password)`` - authentication is automatic
|
|
170
|
+
- Migration: Pass credentials to constructor instead of sign_in()
|
|
171
|
+
- All 18 example files updated to new pattern
|
|
172
|
+
- All documentation updated with new examples
|
|
173
|
+
|
|
174
|
+
- **Documentation**: Major updates across all files
|
|
175
|
+
|
|
176
|
+
- Fixed all RST formatting issues (title underlines, tables)
|
|
177
|
+
- Updated authentication examples in 8 documentation files
|
|
178
|
+
- Fixed broken documentation links (local file paths)
|
|
179
|
+
- Removed "Optional Feature" and "not required for basic operation" phrases
|
|
180
|
+
- Fixed table rendering in DEVICE_STATUS_FIELDS.rst
|
|
181
|
+
- Fixed JSON syntax in code examples
|
|
182
|
+
- Added comprehensive reconnection documentation
|
|
183
|
+
- Added comprehensive command queue documentation
|
|
184
|
+
- Cleaned up backward compatibility references (new library)
|
|
185
|
+
|
|
186
|
+
Fixed
|
|
187
|
+
-----
|
|
188
|
+
|
|
189
|
+
- **Critical Bug**: Thread-safe event emission from MQTT callbacks
|
|
190
|
+
|
|
191
|
+
- Fixed ``RuntimeError: no running event loop in thread 'Dummy-1'``
|
|
192
|
+
- MQTT callbacks run in separate threads created by AWS IoT SDK
|
|
193
|
+
- Implemented ``_schedule_coroutine()`` method for thread-safe scheduling
|
|
194
|
+
- Event loop reference captured during ``connect()`` for cross-thread access
|
|
195
|
+
- Uses ``asyncio.run_coroutine_threadsafe()`` for safe event emission
|
|
196
|
+
- Prevents crashes when emitting events from MQTT message handlers
|
|
197
|
+
- All event emissions now work correctly from any thread
|
|
198
|
+
|
|
199
|
+
- **Bug**: Incorrect method parameter passing in temperature control
|
|
200
|
+
|
|
201
|
+
- Fixed ``set_dhw_temperature_display()`` calling ``set_dhw_temperature()`` with wrong parameters
|
|
202
|
+
- Was passing individual parameters (``device_id``, ``device_type``, ``additional_value``)
|
|
203
|
+
- Now correctly passes ``Device`` object as expected by method signature
|
|
204
|
+
- Simplified implementation to just calculate offset and delegate to base method
|
|
205
|
+
- Updated docstrings to match actual method signatures
|
|
206
|
+
|
|
207
|
+
- **Enhancement**: Anonymized MAC addresses in documentation
|
|
208
|
+
|
|
209
|
+
- Replaced all occurrences of real MAC address (``04786332fca0``) with placeholder (``aabbccddeeff``)
|
|
210
|
+
- Updated ``API_CLIENT.rst``, ``MQTT_CLIENT.rst``, ``MQTT_MESSAGES.rst``
|
|
211
|
+
- Updated built HTML documentation files
|
|
212
|
+
- Protects privacy in public documentation
|
|
213
|
+
|
|
214
|
+
- **Critical Bug**: Device control command codes
|
|
215
|
+
|
|
216
|
+
- Fixed incorrect command code usage causing unintended power-off
|
|
217
|
+
- Power-off now uses command code ``33554433``
|
|
218
|
+
- Power-on now uses command code ``33554434``
|
|
219
|
+
- DHW mode control now uses command code ``33554437``
|
|
220
|
+
- Discovered through network traffic analysis of official app
|
|
221
|
+
|
|
222
|
+
- **Critical Bug**: MQTT topic pattern matching with wildcards
|
|
223
|
+
|
|
224
|
+
- Fixed ``_topic_matches_pattern()`` to correctly handle ``#`` wildcard
|
|
225
|
+
- Topics now match when message arrives on base topic (e.g., ``cmd/52/device/res``)
|
|
226
|
+
- Topics also match subtopics (e.g., ``cmd/52/device/res/extra``)
|
|
227
|
+
- Added length validation to prevent index out of bounds errors
|
|
228
|
+
- Enables callbacks to receive messages correctly
|
|
229
|
+
|
|
230
|
+
- **Bug**: Missing ``OperationMode.STANDBY`` enum value
|
|
231
|
+
|
|
232
|
+
- Added ``STANDBY = 0`` to ``OperationMode`` enum
|
|
233
|
+
- Device reports mode 0 when tank is fully charged and no heating is needed
|
|
234
|
+
- Added graceful fallback for unknown enum values
|
|
235
|
+
- Prevents ``ValueError`` when parsing device status
|
|
236
|
+
|
|
237
|
+
- **Bug**: Insufficient topic subscriptions
|
|
238
|
+
|
|
239
|
+
- Examples now subscribe to broader topic patterns
|
|
240
|
+
- Subscribe to ``cmd/{device_type}/{device_topic}/#`` to catch all command messages
|
|
241
|
+
- Subscribe to ``evt/{device_type}/{device_topic}/#`` to catch all event messages
|
|
242
|
+
- Ensures all device responses are received
|
|
243
|
+
|
|
244
|
+
- **Enhancement**: Robust enum conversion with fallbacks
|
|
245
|
+
|
|
246
|
+
- Added try/except blocks for all enum conversions in ``DeviceStatus.from_dict()``
|
|
247
|
+
- Added try/except blocks for all enum conversions in ``DeviceFeature.from_dict()``
|
|
248
|
+
- Unknown operation modes default to ``STANDBY``
|
|
249
|
+
- Unknown temperature types default to ``FAHRENHEIT``
|
|
250
|
+
- Prevents parsing failures from unexpected values
|
|
251
|
+
|
|
252
|
+
- **Documentation**: Updated MQTT_MESSAGES.rst with correct command codes and temperature offset
|
|
253
|
+
|
|
254
|
+
Verified
|
|
255
|
+
--------
|
|
256
|
+
|
|
257
|
+
- **Device Control**: Real-world testing with Navien NWP500 device
|
|
258
|
+
|
|
259
|
+
- Successfully changed DHW mode from Heat Pump to Energy Saver
|
|
260
|
+
- Successfully changed DHW mode from Energy Saver to High Demand
|
|
261
|
+
- Successfully changed DHW temperature (discovered 20°F offset between message and display)
|
|
262
|
+
- Commands confirmed to reach and control physical device
|
|
263
|
+
- Documented in DEVICE_CONTROL_VERIFIED.md
|
|
264
|
+
|
|
265
|
+
Version 0.1
|
|
266
|
+
===========
|
|
267
|
+
|
|
268
|
+
- Initial Documentation
|