nwp500-python 9.4.2__py3-none-any.whl → 9.5.0__py3-none-any.whl

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 (89) hide show
  1. nwp500/__init__.py +331 -120
  2. nwp500/api_client.py +884 -9
  3. nwp500/auth.py +394 -40
  4. nwp500/ble/__init__.py +110 -0
  5. nwp500/ble/__main__.py +163 -0
  6. nwp500/ble/client.py +546 -0
  7. nwp500/ble/mqtt_adapter.py +211 -0
  8. nwp500/ble/protocol.py +890 -0
  9. nwp500/cli/__main__.py +474 -100
  10. nwp500/cli/ble_backend.py +196 -0
  11. nwp500/cli/calibration.py +488 -0
  12. nwp500/cli/handlers.py +2 -2
  13. nwp500/cli/output_formatters.py +1 -1
  14. nwp500/cli/recording.py +126 -0
  15. nwp500/cli/simulate.py +507 -0
  16. nwp500/config.py +2 -0
  17. nwp500/converters.py +2 -2
  18. nwp500/encoding.py +6 -5
  19. nwp500/enums.py +79 -19
  20. nwp500/models/__init__.py +40 -1
  21. nwp500/models/account.py +61 -0
  22. nwp500/models/device.py +223 -2
  23. nwp500/models/diagnostics.py +5 -2
  24. nwp500/models/maintenance.py +31 -0
  25. nwp500/models/mqtt_models.py +202 -1
  26. nwp500/models/schedule.py +15 -8
  27. nwp500/models/status.py +88 -30
  28. nwp500/models/tou.py +3 -0
  29. nwp500/mqtt/_control_commands.py +9 -4
  30. nwp500/mqtt/_device_subscriptions.py +76 -0
  31. nwp500/mqtt/client.py +55 -27
  32. nwp500/mqtt/command_queue.py +1 -1
  33. nwp500/mqtt/connection.py +30 -5
  34. nwp500/mqtt/control.py +258 -22
  35. nwp500/mqtt/periodic.py +1 -1
  36. nwp500/mqtt/reconnection.py +1 -1
  37. nwp500/mqtt/subscriptions.py +214 -4
  38. nwp500/mqtt/types.py +34 -0
  39. nwp500/mqtt/utils.py +17 -1
  40. nwp500/mqtt_events.py +82 -1
  41. nwp500/reservations.py +47 -17
  42. nwp500/sim/__init__.py +130 -0
  43. nwp500/sim/api.py +1934 -0
  44. nwp500/sim/attribution.py +195 -0
  45. nwp500/sim/book.py +1361 -0
  46. nwp500/sim/calibration.py +3702 -0
  47. nwp500/sim/circulation.py +191 -0
  48. nwp500/sim/codec.py +92 -0
  49. nwp500/sim/cold_supply.py +167 -0
  50. nwp500/sim/controller.py +1584 -0
  51. nwp500/sim/decay.py +1121 -0
  52. nwp500/sim/defaults.py +197 -0
  53. nwp500/sim/delivery.py +711 -0
  54. nwp500/sim/draw_forecast.py +494 -0
  55. nwp500/sim/engine.py +2308 -0
  56. nwp500/sim/extensions.py +212 -0
  57. nwp500/sim/heat_pump_recovery.py +268 -0
  58. nwp500/sim/heating_trajectory.py +342 -0
  59. nwp500/sim/inputs.py +352 -0
  60. nwp500/sim/location_air.py +167 -0
  61. nwp500/sim/meter.py +130 -0
  62. nwp500/sim/observed.py +568 -0
  63. nwp500/sim/params.py +1205 -0
  64. nwp500/sim/physics/__init__.py +2 -0
  65. nwp500/sim/physics/compressor.py +450 -0
  66. nwp500/sim/physics/draw.py +474 -0
  67. nwp500/sim/physics/element.py +623 -0
  68. nwp500/sim/physics/refrigerant.py +168 -0
  69. nwp500/sim/physics/tank.py +72 -0
  70. nwp500/sim/profile.py +238 -0
  71. nwp500/sim/ready.py +728 -0
  72. nwp500/sim/record.py +333 -0
  73. nwp500/sim/result.py +257 -0
  74. nwp500/sim/schedules.py +243 -0
  75. nwp500/sim/tank_physics.py +504 -0
  76. nwp500/sim/tou_triggers.py +308 -0
  77. nwp500/sim/units.py +20 -0
  78. nwp500/sim_adapters.py +1323 -0
  79. nwp500/sim_home_assistant.py +1153 -0
  80. nwp500/sim_live.py +360 -0
  81. nwp500/status_history.py +68 -0
  82. nwp500/topic_builder.py +36 -0
  83. {nwp500_python-9.4.2.dist-info → nwp500_python-9.5.0.dist-info}/METADATA +50 -16
  84. nwp500_python-9.5.0.dist-info/RECORD +114 -0
  85. {nwp500_python-9.4.2.dist-info → nwp500_python-9.5.0.dist-info}/WHEEL +1 -1
  86. nwp500_python-9.4.2.dist-info/RECORD +0 -63
  87. {nwp500_python-9.4.2.dist-info → nwp500_python-9.5.0.dist-info}/entry_points.txt +0 -0
  88. {nwp500_python-9.4.2.dist-info → nwp500_python-9.5.0.dist-info}/licenses/LICENSE.txt +0 -0
  89. {nwp500_python-9.4.2.dist-info → nwp500_python-9.5.0.dist-info}/top_level.txt +0 -0
nwp500/__init__.py CHANGED
@@ -4,10 +4,15 @@ This package provides Python bindings for Navien Smart Control API and MQTT
4
4
  communication for NWP500 heat pump water heaters.
5
5
  """
6
6
 
7
+ from collections.abc import Mapping
8
+ from importlib import import_module
7
9
  from importlib.metadata import (
8
10
  PackageNotFoundError,
9
11
  version,
10
12
  ) # pragma: no cover
13
+ from importlib.util import find_spec
14
+ from types import MappingProxyType
15
+ from typing import TYPE_CHECKING, Any
11
16
 
12
17
  try:
13
18
  # Change here if project is renamed and does not equal the package name
@@ -18,128 +23,314 @@ except PackageNotFoundError: # pragma: no cover
18
23
  finally:
19
24
  del version, PackageNotFoundError
20
25
 
21
- # Export main components
22
- from nwp500.api_client import (
23
- NavienAPIClient,
24
- )
25
- from nwp500.auth import (
26
- AuthenticationResponse,
27
- AuthTokens,
28
- NavienAuthClient,
29
- UserInfo,
30
- authenticate,
31
- refresh_access_token,
32
- )
33
- from nwp500.enums import (
34
- CommandCode,
35
- CurrentOperationMode,
36
- DhwOperationSetting,
37
- DREvent,
38
- ErrorCode,
39
- FilterChange,
40
- HeatSource,
41
- InstallType,
42
- OnOffFlag,
43
- Operation,
44
- RecirculationMode,
45
- TemperatureType,
46
- TempFormulaType,
47
- TouRateType,
48
- TouWeekType,
49
- UnitType,
50
- VolumeCode,
51
- )
52
- from nwp500.events import (
53
- EventEmitter,
54
- EventListener,
55
- )
56
- from nwp500.exceptions import (
57
- APIError,
58
- AuthenticationError,
59
- DeviceCapabilityError,
60
- DeviceError,
61
- InvalidCredentialsError,
62
- MqttConnectionError,
63
- MqttCredentialsError,
64
- MqttError,
65
- MqttNotConnectedError,
66
- MqttPublishError,
67
- Nwp500Error,
68
- ParameterValidationError,
69
- RangeValidationError,
70
- TokenRefreshError,
71
- ValidationError,
72
- )
73
- from nwp500.factory import (
74
- create_navien_clients,
75
- )
76
- from nwp500.models import (
77
- ConvertedTOUPlan,
78
- DescalingInfo,
79
- Device,
80
- DeviceDiagnostics,
81
- DeviceErrorSummary,
82
- DeviceFeature,
83
- DeviceInfo,
84
- DeviceStatus,
85
- DiagnosticsComponentCounters,
86
- DiagnosticsDhwUsage,
87
- DiagnosticsEventCounters,
88
- EnergyUsageDay,
89
- EnergyUsageResponse,
90
- EnergyUsageTotal,
91
- FirmwareDownloadEntry,
92
- FirmwareDownloadInfo,
93
- FirmwareInfo,
94
- Location,
95
- MonthlyEnergyData,
96
- MqttCommand,
97
- MqttRequest,
98
- OtaCommitPayload,
99
- RecirculationSchedule,
100
- RecirculationScheduleEntry,
101
- ReservationEntry,
102
- ReservationSchedule,
103
- TOUInfo,
104
- TOUPeriod,
105
- TOUReservationSchedule,
106
- TOUSchedule,
107
- fahrenheit_to_half_celsius,
108
- preferred_to_half_celsius,
109
- reservation_param_to_preferred,
110
- )
111
- from nwp500.mqtt import (
112
- ConnectionDropEvent,
113
- ConnectionEvent,
114
- MqttConnectionConfig,
115
- MqttDiagnosticsCollector,
116
- MqttMetrics,
117
- NavienMqttClient,
118
- PeriodicRequestType,
119
- QoS,
120
- )
121
- from nwp500.mqtt_events import (
122
- MqttClientEvents,
123
- )
124
- from nwp500.openei import (
125
- OpenEIClient,
126
- )
127
- from nwp500.reservations import (
128
- add_reservation,
129
- delete_reservation,
130
- fetch_reservations,
131
- update_reservation,
132
- update_reservations_confirmed,
133
- )
134
- from nwp500.tou_schedule import (
135
- configure_tou_schedule_confirmed,
136
- )
137
- from nwp500.unit_system import (
138
- get_unit_system,
139
- reset_unit_system,
140
- set_unit_system,
26
+ # The exports load on first use (PEP 562), so a part of the library
27
+ # imports without the others' dependencies: ``nwp500.sim`` needs neither
28
+ # aiohttp nor awsiotsdk, which the clients load.
29
+ if TYPE_CHECKING:
30
+ from nwp500.api_client import (
31
+ NavienAPIClient,
32
+ get_app_version,
33
+ )
34
+ from nwp500.auth import (
35
+ AuthenticationResponse,
36
+ AuthTokens,
37
+ NavienAuthClient,
38
+ UserInfo,
39
+ authenticate,
40
+ refresh_access_token,
41
+ )
42
+ from nwp500.enums import (
43
+ CommandCode,
44
+ CurrentOperationMode,
45
+ DhwOperationSetting,
46
+ DREvent,
47
+ ErrorCode,
48
+ FilterChange,
49
+ HeatSource,
50
+ InstallType,
51
+ OnOffFlag,
52
+ Operation,
53
+ RecirculationMode,
54
+ ReservationMode,
55
+ TemperatureType,
56
+ TempFormulaType,
57
+ TouRateType,
58
+ TouWeekType,
59
+ UnitType,
60
+ VolumeCode,
61
+ )
62
+ from nwp500.events import (
63
+ EventEmitter,
64
+ EventListener,
65
+ )
66
+ from nwp500.exceptions import (
67
+ APIError,
68
+ AuthenticationError,
69
+ DeviceCapabilityError,
70
+ DeviceError,
71
+ InvalidCredentialsError,
72
+ MqttConnectionError,
73
+ MqttCredentialsError,
74
+ MqttError,
75
+ MqttNotConnectedError,
76
+ MqttPublishError,
77
+ Nwp500Error,
78
+ ParameterValidationError,
79
+ RangeValidationError,
80
+ TokenRefreshError,
81
+ ValidationError,
82
+ )
83
+ from nwp500.factory import (
84
+ create_navien_clients,
85
+ )
86
+ from nwp500.models import (
87
+ AppConnectionEvent,
88
+ AppConnectionInfo,
89
+ AppConnectionStatus,
90
+ AppVersionInfo,
91
+ ControlFailCode,
92
+ ControlFailDetail,
93
+ ControlFailResponse,
94
+ ConvertedTOUPlan,
95
+ DescalingInfo,
96
+ Device,
97
+ DeviceDiagnostics,
98
+ DeviceErrorHistoryEntry,
99
+ DeviceErrorSummary,
100
+ DeviceFeature,
101
+ DeviceInfo,
102
+ DeviceInstaller,
103
+ DeviceStatus,
104
+ DiagnosticsComponentCounters,
105
+ DiagnosticsDhwUsage,
106
+ DiagnosticsEventCounters,
107
+ DisplayPreferences,
108
+ EnergyUsageDay,
109
+ EnergyUsageResponse,
110
+ EnergyUsageTotal,
111
+ FirmwareDetail,
112
+ FirmwareDeviceGroup,
113
+ FirmwareDownloadEntry,
114
+ FirmwareDownloadInfo,
115
+ FirmwareInfo,
116
+ Location,
117
+ MaintenanceHistoryEntry,
118
+ MonthlyEnergyData,
119
+ MqttCommand,
120
+ MqttRequest,
121
+ OtaCommitPayload,
122
+ PushSettings,
123
+ RecirculationSchedule,
124
+ RecirculationScheduleEntry,
125
+ ReservationEntry,
126
+ ReservationSchedule,
127
+ SimpleDevice,
128
+ TOUInfo,
129
+ TOUPeriod,
130
+ TOUReservationSchedule,
131
+ TOUSchedule,
132
+ UserProfile,
133
+ fahrenheit_to_half_celsius,
134
+ preferred_to_half_celsius,
135
+ reservation_param_to_preferred,
136
+ )
137
+ from nwp500.mqtt import (
138
+ ConnectionDropEvent,
139
+ ConnectionEvent,
140
+ MqttConnectionConfig,
141
+ MqttDiagnosticsCollector,
142
+ MqttMetrics,
143
+ NavienMqttClient,
144
+ PeriodicRequestType,
145
+ QoS,
146
+ )
147
+ from nwp500.mqtt_events import (
148
+ AppConnectionReceivedEvent,
149
+ ControlFailedEvent,
150
+ MqttClientEvents,
151
+ )
152
+ from nwp500.openei import (
153
+ OpenEIClient,
154
+ )
155
+ from nwp500.reservations import (
156
+ add_reservation,
157
+ delete_reservation,
158
+ fetch_reservations,
159
+ update_reservation,
160
+ update_reservations_confirmed,
161
+ )
162
+ from nwp500.tou_schedule import (
163
+ configure_tou_schedule_confirmed,
164
+ )
165
+ from nwp500.unit_system import (
166
+ get_unit_system,
167
+ reset_unit_system,
168
+ set_unit_system,
169
+ )
170
+
171
+ #: Each export and the module it is loaded from.
172
+ _EXPORTS: Mapping[str, str] = MappingProxyType(
173
+ {
174
+ name: module
175
+ for module, names in {
176
+ "nwp500.api_client": (
177
+ "NavienAPIClient",
178
+ "get_app_version",
179
+ ),
180
+ "nwp500.auth": (
181
+ "AuthenticationResponse",
182
+ "AuthTokens",
183
+ "NavienAuthClient",
184
+ "UserInfo",
185
+ "authenticate",
186
+ "refresh_access_token",
187
+ ),
188
+ "nwp500.enums": (
189
+ "CommandCode",
190
+ "CurrentOperationMode",
191
+ "DhwOperationSetting",
192
+ "DREvent",
193
+ "ErrorCode",
194
+ "FilterChange",
195
+ "HeatSource",
196
+ "InstallType",
197
+ "OnOffFlag",
198
+ "Operation",
199
+ "RecirculationMode",
200
+ "ReservationMode",
201
+ "TemperatureType",
202
+ "TempFormulaType",
203
+ "TouRateType",
204
+ "TouWeekType",
205
+ "UnitType",
206
+ "VolumeCode",
207
+ ),
208
+ "nwp500.events": (
209
+ "EventEmitter",
210
+ "EventListener",
211
+ ),
212
+ "nwp500.exceptions": (
213
+ "APIError",
214
+ "AuthenticationError",
215
+ "DeviceCapabilityError",
216
+ "DeviceError",
217
+ "InvalidCredentialsError",
218
+ "MqttConnectionError",
219
+ "MqttCredentialsError",
220
+ "MqttError",
221
+ "MqttNotConnectedError",
222
+ "MqttPublishError",
223
+ "Nwp500Error",
224
+ "ParameterValidationError",
225
+ "RangeValidationError",
226
+ "TokenRefreshError",
227
+ "ValidationError",
228
+ ),
229
+ "nwp500.factory": ("create_navien_clients",),
230
+ "nwp500.models": (
231
+ "AppConnectionEvent",
232
+ "AppConnectionInfo",
233
+ "AppConnectionStatus",
234
+ "AppVersionInfo",
235
+ "ControlFailCode",
236
+ "ControlFailDetail",
237
+ "ControlFailResponse",
238
+ "ConvertedTOUPlan",
239
+ "DescalingInfo",
240
+ "Device",
241
+ "DeviceDiagnostics",
242
+ "DeviceErrorHistoryEntry",
243
+ "DeviceErrorSummary",
244
+ "DeviceFeature",
245
+ "DeviceInfo",
246
+ "DeviceInstaller",
247
+ "DeviceStatus",
248
+ "DiagnosticsComponentCounters",
249
+ "DiagnosticsDhwUsage",
250
+ "DiagnosticsEventCounters",
251
+ "DisplayPreferences",
252
+ "EnergyUsageDay",
253
+ "EnergyUsageResponse",
254
+ "EnergyUsageTotal",
255
+ "FirmwareDetail",
256
+ "FirmwareDeviceGroup",
257
+ "FirmwareDownloadEntry",
258
+ "FirmwareDownloadInfo",
259
+ "FirmwareInfo",
260
+ "Location",
261
+ "MaintenanceHistoryEntry",
262
+ "MonthlyEnergyData",
263
+ "MqttCommand",
264
+ "MqttRequest",
265
+ "OtaCommitPayload",
266
+ "PushSettings",
267
+ "RecirculationSchedule",
268
+ "RecirculationScheduleEntry",
269
+ "ReservationEntry",
270
+ "ReservationSchedule",
271
+ "SimpleDevice",
272
+ "TOUInfo",
273
+ "TOUPeriod",
274
+ "TOUReservationSchedule",
275
+ "TOUSchedule",
276
+ "UserProfile",
277
+ "fahrenheit_to_half_celsius",
278
+ "preferred_to_half_celsius",
279
+ "reservation_param_to_preferred",
280
+ ),
281
+ "nwp500.mqtt": (
282
+ "ConnectionDropEvent",
283
+ "ConnectionEvent",
284
+ "MqttConnectionConfig",
285
+ "MqttDiagnosticsCollector",
286
+ "MqttMetrics",
287
+ "NavienMqttClient",
288
+ "PeriodicRequestType",
289
+ "QoS",
290
+ ),
291
+ "nwp500.mqtt_events": (
292
+ "AppConnectionReceivedEvent",
293
+ "ControlFailedEvent",
294
+ "MqttClientEvents",
295
+ ),
296
+ "nwp500.openei": ("OpenEIClient",),
297
+ "nwp500.reservations": (
298
+ "add_reservation",
299
+ "delete_reservation",
300
+ "fetch_reservations",
301
+ "update_reservation",
302
+ "update_reservations_confirmed",
303
+ ),
304
+ "nwp500.tou_schedule": ("configure_tou_schedule_confirmed",),
305
+ "nwp500.unit_system": (
306
+ "get_unit_system",
307
+ "reset_unit_system",
308
+ "set_unit_system",
309
+ ),
310
+ }.items()
311
+ for name in names
312
+ }
141
313
  )
142
314
 
315
+
316
+ def __getattr__(name: str) -> Any:
317
+ """An export, imported on first use and kept; a submodule by its
318
+ name (``nwp500.mqtt``), as the eager imports once left it bound."""
319
+ module = _EXPORTS.get(name)
320
+ if module is not None:
321
+ value = getattr(import_module(module), name)
322
+ elif find_spec(f"{__name__}.{name}") is not None:
323
+ value = import_module(f"{__name__}.{name}")
324
+ else:
325
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
326
+ globals()[name] = value
327
+ return value
328
+
329
+
330
+ def __dir__() -> list[str]:
331
+ return sorted({*globals(), *_EXPORTS})
332
+
333
+
143
334
  __all__ = [
144
335
  "__version__",
145
336
  # Device Capabilities
@@ -173,6 +364,22 @@ __all__ = [
173
364
  "TOUReservationSchedule",
174
365
  "MqttRequest",
175
366
  "MqttCommand",
367
+ "ControlFailCode",
368
+ "ControlFailDetail",
369
+ "ControlFailResponse",
370
+ "AppConnectionEvent",
371
+ "AppConnectionInfo",
372
+ "AppConnectionStatus",
373
+ "DeviceInstaller",
374
+ "PushSettings",
375
+ "FirmwareDeviceGroup",
376
+ "FirmwareDetail",
377
+ "DisplayPreferences",
378
+ "SimpleDevice",
379
+ "DeviceErrorHistoryEntry",
380
+ "MaintenanceHistoryEntry",
381
+ "UserProfile",
382
+ "AppVersionInfo",
176
383
  "EnergyUsageTotal",
177
384
  "EnergyUsageDay",
178
385
  "MonthlyEnergyData",
@@ -189,6 +396,7 @@ __all__ = [
189
396
  "OnOffFlag",
190
397
  "Operation",
191
398
  "RecirculationMode",
399
+ "ReservationMode",
192
400
  "TemperatureType",
193
401
  "TempFormulaType",
194
402
  "TouRateType",
@@ -223,6 +431,7 @@ __all__ = [
223
431
  "DeviceError",
224
432
  # API Client
225
433
  "NavienAPIClient",
434
+ "get_app_version",
226
435
  # OpenEI Client
227
436
  "OpenEIClient",
228
437
  # Reservation helpers
@@ -246,6 +455,8 @@ __all__ = [
246
455
  "EventEmitter",
247
456
  "EventListener",
248
457
  "MqttClientEvents",
458
+ "ControlFailedEvent",
459
+ "AppConnectionReceivedEvent",
249
460
  # Unit system management
250
461
  "set_unit_system",
251
462
  "get_unit_system",