nwp500-python 1.1.4__tar.gz → 1.1.5__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.1.4/src/nwp500_python.egg-info → nwp500_python-1.1.5}/PKG-INFO +1 -1
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/DEVICE_STATUS_FIELDS.rst +5 -0
- nwp500_python-1.1.5/docs/FIRMWARE_TRACKING.rst +146 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/index.rst +1 -0
- nwp500_python-1.1.5/src/nwp500/constants.py +31 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500/models.py +48 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5/src/nwp500_python.egg-info}/PKG-INFO +1 -1
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500_python.egg-info/SOURCES.txt +1 -0
- nwp500_python-1.1.4/src/nwp500/constants.py +0 -12
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/.coveragerc +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/.github/copilot-instructions.md +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/.github/workflows/ci.yml +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/.github/workflows/release.yml +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/.gitignore +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/.pre-commit-config.yaml +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/.readthedocs.yml +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/AUTHORS.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/CHANGELOG.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/CONTRIBUTING.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/LICENSE.txt +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/Makefile +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/README.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/RELEASE.md +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/API_CLIENT.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/API_REFERENCE.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/AUTHENTICATION.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/COMMAND_QUEUE.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/DEVELOPMENT.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/DEVICE_FEATURE_FIELDS.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/ENERGY_MONITORING.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/ERROR_CODES.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/EVENT_EMITTER.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/MQTT_CLIENT.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/MQTT_MESSAGES.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/Makefile +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/_static/.gitignore +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/authors.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/changelog.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/conf.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/contributing.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/license.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/openapi.yaml +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/readme.rst +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/docs/requirements.txt +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/.ruff.toml +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/README.md +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/api_client_example.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/auth_constructor_example.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/authenticate.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/combined_callbacks.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/command_queue_demo.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/device_feature_callback.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/device_status_callback.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/device_status_callback_debug.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/energy_usage_example.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/event_emitter_demo.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/improved_auth_pattern.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/mask.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/mqtt_client_example.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/periodic_device_info.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/periodic_requests.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/power_control_example.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/reconnection_demo.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/set_dhw_temperature_example.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/set_mode_example.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/simple_periodic_info.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/simple_periodic_status.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/test_api_client.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/test_mqtt_connection.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/test_mqtt_messaging.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/examples/test_periodic_minimal.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/pyproject.toml +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/scripts/format.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/scripts/lint.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/scripts/setup-dev.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/setup.cfg +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/setup.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500/__init__.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500/api_client.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500/auth.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500/cli.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500/config.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500/events.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500/mqtt_client.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500_python.egg-info/dependency_links.txt +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500_python.egg-info/entry_points.txt +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500_python.egg-info/not-zip-safe +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500_python.egg-info/requires.txt +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/src/nwp500_python.egg-info/top_level.txt +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/tests/conftest.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/tests/test_command_queue.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/tests/test_events.py +0 -0
- {nwp500_python-1.1.4 → nwp500_python-1.1.5}/tox.ini +0 -0
|
@@ -428,6 +428,11 @@ This document lists the fields found in the ``status`` object of device status m
|
|
|
428
428
|
- °F
|
|
429
429
|
- Heater element lower off differential temperature setting.
|
|
430
430
|
- ``raw / 10.0``
|
|
431
|
+
* - ``heatMinOpTemperature``
|
|
432
|
+
- float
|
|
433
|
+
- °F
|
|
434
|
+
- Minimum operating temperature for the heating element. This sets the lower threshold at which the heating element can operate.
|
|
435
|
+
- ``raw + 20``
|
|
431
436
|
* - ``drOverrideStatus``
|
|
432
437
|
- integer
|
|
433
438
|
- None
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
|
|
2
|
+
Firmware Version Tracking
|
|
3
|
+
=========================
|
|
4
|
+
|
|
5
|
+
This document tracks firmware versions and the device status fields they introduce or modify.
|
|
6
|
+
|
|
7
|
+
Purpose
|
|
8
|
+
-------
|
|
9
|
+
|
|
10
|
+
The Navien NWP500 water heater receives firmware updates that may introduce new status fields or modify existing behavior. This tracking system helps:
|
|
11
|
+
|
|
12
|
+
1. **Graceful Degradation**: The library can handle unknown fields from newer firmware versions without crashing
|
|
13
|
+
2. **User Reporting**: Users can report firmware versions when encountering new fields
|
|
14
|
+
3. **Library Updates**: Maintainers can prioritize adding support for new fields based on firmware adoption
|
|
15
|
+
4. **Documentation**: Track when fields were introduced for better device compatibility documentation
|
|
16
|
+
|
|
17
|
+
How It Works
|
|
18
|
+
------------
|
|
19
|
+
|
|
20
|
+
When the library encounters unknown fields in device status messages:
|
|
21
|
+
|
|
22
|
+
1. It checks if the field is documented in ``constants.KNOWN_FIRMWARE_FIELD_CHANGES``
|
|
23
|
+
2. If the field is known but not implemented, it logs an INFO message
|
|
24
|
+
3. If the field is completely unknown, it logs a WARNING message asking users to report their firmware version
|
|
25
|
+
4. The unknown field is safely ignored, and the library continues to function
|
|
26
|
+
|
|
27
|
+
Known Firmware Field Changes
|
|
28
|
+
-----------------------------
|
|
29
|
+
|
|
30
|
+
The following table tracks known fields that have been introduced in firmware updates:
|
|
31
|
+
|
|
32
|
+
.. list-table::
|
|
33
|
+
:header-rows: 1
|
|
34
|
+
:widths: 20 15 15 50
|
|
35
|
+
|
|
36
|
+
* - Field Name
|
|
37
|
+
- First Observed
|
|
38
|
+
- Conversion
|
|
39
|
+
- Description
|
|
40
|
+
* - ``heatMinOpTemperature``
|
|
41
|
+
- Controller: 184614912, WiFi: 34013184
|
|
42
|
+
- ``raw + 20``
|
|
43
|
+
- Minimum operating temperature for the heating element. Sets the lower threshold at which the heating element can operate.
|
|
44
|
+
|
|
45
|
+
Reporting New Fields
|
|
46
|
+
--------------------
|
|
47
|
+
|
|
48
|
+
If you see a warning message about unknown fields, please help us improve the library by reporting:
|
|
49
|
+
|
|
50
|
+
1. **The unknown field name(s)** from the warning message
|
|
51
|
+
2. **Your device firmware versions**:
|
|
52
|
+
|
|
53
|
+
- Controller SW Version (``controllerSwVersion``)
|
|
54
|
+
- Panel SW Version (``panelSwVersion``)
|
|
55
|
+
- WiFi SW Version (``wifiSwVersion``)
|
|
56
|
+
|
|
57
|
+
3. **Sample raw values** for the unknown field (if possible)
|
|
58
|
+
4. **Your device model** (e.g., NWP500)
|
|
59
|
+
|
|
60
|
+
You can get your firmware versions by running:
|
|
61
|
+
|
|
62
|
+
.. code-block:: python
|
|
63
|
+
|
|
64
|
+
from nwp500.mqtt_client import NavienMQTTClient
|
|
65
|
+
from nwp500.auth import NavienAuthClient
|
|
66
|
+
from nwp500.api_client import NavienAPIClient
|
|
67
|
+
import asyncio
|
|
68
|
+
import os
|
|
69
|
+
|
|
70
|
+
async def get_firmware():
|
|
71
|
+
async with NavienAuthClient(
|
|
72
|
+
os.getenv("NAVIEN_EMAIL"),
|
|
73
|
+
os.getenv("NAVIEN_PASSWORD")
|
|
74
|
+
) as auth:
|
|
75
|
+
api = NavienAPIClient(auth)
|
|
76
|
+
devices = await api.get_devices()
|
|
77
|
+
device = devices[0]
|
|
78
|
+
|
|
79
|
+
mqtt = NavienMQTTClient(auth, device.mac_address, device.device_type)
|
|
80
|
+
await mqtt.connect()
|
|
81
|
+
|
|
82
|
+
def feature_callback(feature):
|
|
83
|
+
print(f"Controller SW: {feature.controllerSwVersion}")
|
|
84
|
+
print(f"Panel SW: {feature.panelSwVersion}")
|
|
85
|
+
print(f"WiFi SW: {feature.wifiSwVersion}")
|
|
86
|
+
|
|
87
|
+
await mqtt.request_device_info(feature_callback)
|
|
88
|
+
await asyncio.sleep(2)
|
|
89
|
+
await mqtt.disconnect()
|
|
90
|
+
|
|
91
|
+
asyncio.run(get_firmware())
|
|
92
|
+
|
|
93
|
+
Or using the CLI (if implemented):
|
|
94
|
+
|
|
95
|
+
.. code-block:: bash
|
|
96
|
+
|
|
97
|
+
nwp-cli --device-info
|
|
98
|
+
|
|
99
|
+
Please report issues at: https://github.com/eman/nwp500-python/issues
|
|
100
|
+
|
|
101
|
+
Adding New Fields
|
|
102
|
+
-----------------
|
|
103
|
+
|
|
104
|
+
When adding support for a newly discovered field:
|
|
105
|
+
|
|
106
|
+
1. Add the field to ``DeviceStatus`` dataclass in ``models.py``
|
|
107
|
+
2. Add appropriate conversion logic in ``DeviceStatus.from_dict()``
|
|
108
|
+
3. Document the field in ``DEVICE_STATUS_FIELDS.rst``
|
|
109
|
+
4. Update ``constants.KNOWN_FIRMWARE_FIELD_CHANGES`` with field metadata
|
|
110
|
+
5. Update this tracking document with firmware version information
|
|
111
|
+
6. Remove the field from ``KNOWN_FIRMWARE_FIELD_CHANGES`` once implemented
|
|
112
|
+
|
|
113
|
+
Example entry in ``constants.py``:
|
|
114
|
+
|
|
115
|
+
.. code-block:: python
|
|
116
|
+
|
|
117
|
+
KNOWN_FIRMWARE_FIELD_CHANGES = {
|
|
118
|
+
"newFieldName": {
|
|
119
|
+
"introduced_in": "controller: 123, panel: 456, wifi: 789",
|
|
120
|
+
"description": "What this field represents",
|
|
121
|
+
"conversion": "raw + 20", # or "raw / 10.0", "bool (1=OFF, 2=ON)", etc.
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Firmware Version History
|
|
126
|
+
------------------------
|
|
127
|
+
|
|
128
|
+
This section tracks observed firmware versions and their associated changes.
|
|
129
|
+
|
|
130
|
+
**Latest Known Versions** (as of 2025-10-15):
|
|
131
|
+
|
|
132
|
+
- Controller SW Version: 184614912
|
|
133
|
+
- Panel SW Version: 0 (not used on NWP500 devices)
|
|
134
|
+
- WiFi SW Version: 34013184
|
|
135
|
+
|
|
136
|
+
**Observed Features:**
|
|
137
|
+
|
|
138
|
+
- These versions include support for ``heatMinOpTemperature`` field
|
|
139
|
+
- Recirculation pump fields (``recirc*``) are present but not yet documented
|
|
140
|
+
|
|
141
|
+
*Note: This tracking system was implemented on 2025-10-15. Historical firmware information is not available.*
|
|
142
|
+
|
|
143
|
+
Contributing
|
|
144
|
+
------------
|
|
145
|
+
|
|
146
|
+
If you have information about different firmware versions or field changes, please submit a pull request or open an issue. Your contributions help make this library more robust and compatible with different device configurations.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module defines constants for the Navien API.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# MQTT Command Codes
|
|
6
|
+
CMD_STATUS_REQUEST = 16777219
|
|
7
|
+
CMD_DEVICE_INFO_REQUEST = 16777217
|
|
8
|
+
CMD_POWER_ON = 33554434
|
|
9
|
+
CMD_POWER_OFF = 33554433
|
|
10
|
+
CMD_DHW_MODE = 33554437
|
|
11
|
+
CMD_DHW_TEMPERATURE = 33554464
|
|
12
|
+
CMD_ENERGY_USAGE_QUERY = 16777225
|
|
13
|
+
|
|
14
|
+
# Known Firmware Versions and Field Changes
|
|
15
|
+
# Track firmware versions where new fields were introduced to help with debugging
|
|
16
|
+
KNOWN_FIRMWARE_FIELD_CHANGES = {
|
|
17
|
+
# Format: "field_name": {"introduced_in": "version", "description": "what it does"}
|
|
18
|
+
"heatMinOpTemperature": {
|
|
19
|
+
"introduced_in": "Controller: 184614912, WiFi: 34013184",
|
|
20
|
+
"description": "Minimum operating temperature for heating element",
|
|
21
|
+
"conversion": "raw + 20",
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# Latest known firmware versions (as of 2025-10-15)
|
|
26
|
+
# These versions have been observed with heatMinOpTemperature field
|
|
27
|
+
LATEST_KNOWN_FIRMWARE = {
|
|
28
|
+
"controllerSwVersion": 184614912, # Observed on NWP500 device
|
|
29
|
+
"panelSwVersion": 0, # Panel SW version not used on this device
|
|
30
|
+
"wifiSwVersion": 34013184, # Observed on NWP500 device
|
|
31
|
+
}
|
|
@@ -10,6 +10,8 @@ from dataclasses import dataclass, field
|
|
|
10
10
|
from enum import Enum
|
|
11
11
|
from typing import Any, Optional, Union
|
|
12
12
|
|
|
13
|
+
from . import constants
|
|
14
|
+
|
|
13
15
|
_logger = logging.getLogger(__name__)
|
|
14
16
|
|
|
15
17
|
|
|
@@ -303,6 +305,7 @@ class DeviceStatus:
|
|
|
303
305
|
heUpperOffDiffTempSetting: float
|
|
304
306
|
heLowerOnDiffTempSetting: float
|
|
305
307
|
heLowerOffDiffTempSetting: float
|
|
308
|
+
heatMinOpTemperature: float
|
|
306
309
|
drOverrideStatus: int
|
|
307
310
|
touOverrideStatus: int
|
|
308
311
|
totalEnergyCapacity: float
|
|
@@ -317,6 +320,9 @@ class DeviceStatus:
|
|
|
317
320
|
# Copy data to avoid modifying the original dictionary
|
|
318
321
|
converted_data = data.copy()
|
|
319
322
|
|
|
323
|
+
# Get valid field names for this class
|
|
324
|
+
valid_fields = {f.name for f in cls.__dataclass_fields__.values()}
|
|
325
|
+
|
|
320
326
|
# Handle key typo from documentation/API
|
|
321
327
|
if "heLowerOnTDiffempSetting" in converted_data:
|
|
322
328
|
converted_data["heLowerOnDiffTempSetting"] = converted_data.pop(
|
|
@@ -373,6 +379,7 @@ class DeviceStatus:
|
|
|
373
379
|
"heUpperOffTempSetting",
|
|
374
380
|
"heLowerOnTempSetting",
|
|
375
381
|
"heLowerOffTempSetting",
|
|
382
|
+
"heatMinOpTemperature",
|
|
376
383
|
]
|
|
377
384
|
for field_name in add_20_fields:
|
|
378
385
|
if field_name in converted_data:
|
|
@@ -457,6 +464,34 @@ class DeviceStatus:
|
|
|
457
464
|
# Default to FAHRENHEIT for unknown temperature types
|
|
458
465
|
converted_data["temperatureType"] = TemperatureUnit.FAHRENHEIT
|
|
459
466
|
|
|
467
|
+
# Filter out any unknown fields not defined in the dataclass
|
|
468
|
+
# This handles new fields added by firmware updates gracefully
|
|
469
|
+
unknown_fields = set(converted_data.keys()) - valid_fields
|
|
470
|
+
if unknown_fields:
|
|
471
|
+
# Check if any unknown fields are documented in constants
|
|
472
|
+
known_firmware_fields = set(constants.KNOWN_FIRMWARE_FIELD_CHANGES.keys())
|
|
473
|
+
known_new_fields = unknown_fields & known_firmware_fields
|
|
474
|
+
truly_unknown = unknown_fields - known_firmware_fields
|
|
475
|
+
|
|
476
|
+
if known_new_fields:
|
|
477
|
+
_logger.info(
|
|
478
|
+
"Ignoring known new fields from recent firmware: %s. "
|
|
479
|
+
"These fields are documented but not yet implemented in DeviceStatus. "
|
|
480
|
+
"Please report this with your firmware version to help us track field changes.",
|
|
481
|
+
known_new_fields,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
if truly_unknown:
|
|
485
|
+
_logger.warning(
|
|
486
|
+
"Discovered new unknown fields from device status: %s. "
|
|
487
|
+
"This may indicate a firmware update. Please report this issue with your "
|
|
488
|
+
"device firmware version (controllerSwVersion, panelSwVersion, wifiSwVersion) "
|
|
489
|
+
"so we can update the library. See constants.KNOWN_FIRMWARE_FIELD_CHANGES.",
|
|
490
|
+
truly_unknown,
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
converted_data = {k: v for k, v in converted_data.items() if k in valid_fields}
|
|
494
|
+
|
|
460
495
|
return cls(**converted_data)
|
|
461
496
|
|
|
462
497
|
|
|
@@ -518,6 +553,9 @@ class DeviceFeature:
|
|
|
518
553
|
# Copy data to avoid modifying the original dictionary
|
|
519
554
|
converted_data = data.copy()
|
|
520
555
|
|
|
556
|
+
# Get valid field names for this class
|
|
557
|
+
valid_fields = {f.name for f in cls.__dataclass_fields__.values()}
|
|
558
|
+
|
|
521
559
|
# Convert temperature fields with 'raw + 20' formula (same as DeviceStatus)
|
|
522
560
|
temp_add_20_fields = [
|
|
523
561
|
"dhwTemperatureMin",
|
|
@@ -543,6 +581,16 @@ class DeviceFeature:
|
|
|
543
581
|
# Default to FAHRENHEIT for unknown temperature types
|
|
544
582
|
converted_data["temperatureType"] = TemperatureUnit.FAHRENHEIT
|
|
545
583
|
|
|
584
|
+
# Filter out any unknown fields (similar to DeviceStatus)
|
|
585
|
+
unknown_fields = set(converted_data.keys()) - valid_fields
|
|
586
|
+
if unknown_fields:
|
|
587
|
+
_logger.info(
|
|
588
|
+
"Ignoring unknown fields from device feature: %s. "
|
|
589
|
+
"This may indicate new device capabilities from a firmware update.",
|
|
590
|
+
unknown_fields,
|
|
591
|
+
)
|
|
592
|
+
converted_data = {k: v for k, v in converted_data.items() if k in valid_fields}
|
|
593
|
+
|
|
546
594
|
return cls(**converted_data)
|
|
547
595
|
|
|
548
596
|
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module defines constants for the Navien API.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
# MQTT Command Codes
|
|
6
|
-
CMD_STATUS_REQUEST = 16777219
|
|
7
|
-
CMD_DEVICE_INFO_REQUEST = 16777217
|
|
8
|
-
CMD_POWER_ON = 33554434
|
|
9
|
-
CMD_POWER_OFF = 33554433
|
|
10
|
-
CMD_DHW_MODE = 33554437
|
|
11
|
-
CMD_DHW_TEMPERATURE = 33554464
|
|
12
|
-
CMD_ENERGY_USAGE_QUERY = 16777225
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|