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.
Files changed (83) hide show
  1. nwp500_python-1.0.0/.coveragerc +28 -0
  2. nwp500_python-1.0.0/.github/copilot-instructions.md +44 -0
  3. nwp500_python-1.0.0/.github/workflows/ci.yml +84 -0
  4. nwp500_python-1.0.0/.github/workflows/release.yml +85 -0
  5. nwp500_python-1.0.0/.gitignore +57 -0
  6. nwp500_python-1.0.0/.readthedocs.yml +27 -0
  7. nwp500_python-1.0.0/AUTHORS.rst +5 -0
  8. nwp500_python-1.0.0/CHANGELOG.rst +268 -0
  9. nwp500_python-1.0.0/CONTRIBUTING.rst +297 -0
  10. nwp500_python-1.0.0/LICENSE.txt +21 -0
  11. nwp500_python-1.0.0/Makefile +69 -0
  12. nwp500_python-1.0.0/PKG-INFO +249 -0
  13. nwp500_python-1.0.0/README.rst +212 -0
  14. nwp500_python-1.0.0/RELEASE.md +330 -0
  15. nwp500_python-1.0.0/docs/API_CLIENT.rst +541 -0
  16. nwp500_python-1.0.0/docs/API_REFERENCE.rst +31 -0
  17. nwp500_python-1.0.0/docs/AUTHENTICATION.rst +605 -0
  18. nwp500_python-1.0.0/docs/COMMAND_QUEUE.rst +315 -0
  19. nwp500_python-1.0.0/docs/DEVELOPMENT.rst +344 -0
  20. nwp500_python-1.0.0/docs/DEVICE_STATUS_FIELDS.rst +534 -0
  21. nwp500_python-1.0.0/docs/ENERGY_MONITORING.rst +300 -0
  22. nwp500_python-1.0.0/docs/ERROR_CODES.rst +345 -0
  23. nwp500_python-1.0.0/docs/EVENT_EMITTER.rst +691 -0
  24. nwp500_python-1.0.0/docs/MQTT_CLIENT.rst +964 -0
  25. nwp500_python-1.0.0/docs/MQTT_MESSAGES.rst +378 -0
  26. nwp500_python-1.0.0/docs/Makefile +29 -0
  27. nwp500_python-1.0.0/docs/_static/.gitignore +1 -0
  28. nwp500_python-1.0.0/docs/authors.rst +2 -0
  29. nwp500_python-1.0.0/docs/changelog.rst +2 -0
  30. nwp500_python-1.0.0/docs/conf.py +292 -0
  31. nwp500_python-1.0.0/docs/contributing.rst +1 -0
  32. nwp500_python-1.0.0/docs/index.rst +361 -0
  33. nwp500_python-1.0.0/docs/license.rst +7 -0
  34. nwp500_python-1.0.0/docs/openapi.yaml +529 -0
  35. nwp500_python-1.0.0/docs/readme.rst +2 -0
  36. nwp500_python-1.0.0/docs/requirements.txt +6 -0
  37. nwp500_python-1.0.0/examples/.ruff.toml +4 -0
  38. nwp500_python-1.0.0/examples/README.md +110 -0
  39. nwp500_python-1.0.0/examples/api_client_example.py +254 -0
  40. nwp500_python-1.0.0/examples/auth_constructor_example.py +40 -0
  41. nwp500_python-1.0.0/examples/authenticate.py +107 -0
  42. nwp500_python-1.0.0/examples/combined_callbacks.py +164 -0
  43. nwp500_python-1.0.0/examples/command_queue_demo.py +198 -0
  44. nwp500_python-1.0.0/examples/device_feature_callback.py +244 -0
  45. nwp500_python-1.0.0/examples/device_status_callback.py +235 -0
  46. nwp500_python-1.0.0/examples/device_status_callback_debug.py +199 -0
  47. nwp500_python-1.0.0/examples/energy_usage_example.py +157 -0
  48. nwp500_python-1.0.0/examples/event_emitter_demo.py +269 -0
  49. nwp500_python-1.0.0/examples/improved_auth_pattern.py +64 -0
  50. nwp500_python-1.0.0/examples/mask.py +64 -0
  51. nwp500_python-1.0.0/examples/mqtt_client_example.py +231 -0
  52. nwp500_python-1.0.0/examples/periodic_device_info.py +150 -0
  53. nwp500_python-1.0.0/examples/periodic_requests.py +238 -0
  54. nwp500_python-1.0.0/examples/reconnection_demo.py +140 -0
  55. nwp500_python-1.0.0/examples/simple_periodic_info.py +66 -0
  56. nwp500_python-1.0.0/examples/simple_periodic_status.py +66 -0
  57. nwp500_python-1.0.0/examples/test_api_client.py +262 -0
  58. nwp500_python-1.0.0/examples/test_mqtt_connection.py +100 -0
  59. nwp500_python-1.0.0/examples/test_mqtt_messaging.py +273 -0
  60. nwp500_python-1.0.0/examples/test_periodic_minimal.py +88 -0
  61. nwp500_python-1.0.0/pyproject.toml +95 -0
  62. nwp500_python-1.0.0/setup.cfg +84 -0
  63. nwp500_python-1.0.0/setup.py +22 -0
  64. nwp500_python-1.0.0/src/nwp500/__init__.py +102 -0
  65. nwp500_python-1.0.0/src/nwp500/api_client.py +373 -0
  66. nwp500_python-1.0.0/src/nwp500/auth.py +502 -0
  67. nwp500_python-1.0.0/src/nwp500/config.py +9 -0
  68. nwp500_python-1.0.0/src/nwp500/constants.py +12 -0
  69. nwp500_python-1.0.0/src/nwp500/events.py +361 -0
  70. nwp500_python-1.0.0/src/nwp500/models.py +650 -0
  71. nwp500_python-1.0.0/src/nwp500/mqtt_client.py +1654 -0
  72. nwp500_python-1.0.0/src/nwp500/skeleton.py +152 -0
  73. nwp500_python-1.0.0/src/nwp500_python.egg-info/PKG-INFO +249 -0
  74. nwp500_python-1.0.0/src/nwp500_python.egg-info/SOURCES.txt +82 -0
  75. nwp500_python-1.0.0/src/nwp500_python.egg-info/dependency_links.txt +1 -0
  76. nwp500_python-1.0.0/src/nwp500_python.egg-info/not-zip-safe +1 -0
  77. nwp500_python-1.0.0/src/nwp500_python.egg-info/requires.txt +15 -0
  78. nwp500_python-1.0.0/src/nwp500_python.egg-info/top_level.txt +1 -0
  79. nwp500_python-1.0.0/tests/conftest.py +10 -0
  80. nwp500_python-1.0.0/tests/test_command_queue.py +84 -0
  81. nwp500_python-1.0.0/tests/test_events.py +329 -0
  82. nwp500_python-1.0.0/tests/test_skeleton.py +25 -0
  83. 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,5 @@
1
+ ============
2
+ Contributors
3
+ ============
4
+
5
+ * Emmanuel Levijarvi <emansl@gmail.com>
@@ -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