ha-mqtt-sdk 0.4.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 (44) hide show
  1. ha_mqtt_sdk-0.4.0/LICENSE +21 -0
  2. ha_mqtt_sdk-0.4.0/PKG-INFO +439 -0
  3. ha_mqtt_sdk-0.4.0/README.md +407 -0
  4. ha_mqtt_sdk-0.4.0/pyproject.toml +119 -0
  5. ha_mqtt_sdk-0.4.0/setup.cfg +4 -0
  6. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/__init__.py +79 -0
  7. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/builders/__init__.py +21 -0
  8. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/builders/discovery_payload.py +134 -0
  9. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/builders/topic_manager.py +134 -0
  10. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/config/__init__.py +14 -0
  11. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/config/device_fields.py +404 -0
  12. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/config/domains.py +45 -0
  13. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/config/mqtt.py +89 -0
  14. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/__init__.py +40 -0
  15. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/async_entity_manager.py +350 -0
  16. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/async_plugin_interface.py +110 -0
  17. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/async_plugin_manager.py +119 -0
  18. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/async_sdk.py +168 -0
  19. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/device_factory.py +68 -0
  20. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/entity_factory.py +157 -0
  21. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/entity_manager.py +388 -0
  22. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/plugin_interface.py +107 -0
  23. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/plugin_manager.py +118 -0
  24. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/core/sdk.py +165 -0
  25. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/exceptions.py +69 -0
  26. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/models/__init__.py +9 -0
  27. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/models/device_info.py +20 -0
  28. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/models/entity.py +218 -0
  29. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/mqtt/__init__.py +29 -0
  30. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/mqtt/async_client.py +242 -0
  31. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/mqtt/base.py +46 -0
  32. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/mqtt/base_async_mqtt_client.py +47 -0
  33. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/mqtt/paho_client.py +250 -0
  34. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/py.typed +1 -0
  35. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/types.py +17 -0
  36. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/utils/__init__.py +20 -0
  37. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/utils/logger.py +26 -0
  38. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/validators/__init__.py +6 -0
  39. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk/validators/payload_validator.py +119 -0
  40. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk.egg-info/PKG-INFO +439 -0
  41. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk.egg-info/SOURCES.txt +42 -0
  42. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk.egg-info/dependency_links.txt +1 -0
  43. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk.egg-info/requires.txt +10 -0
  44. ha_mqtt_sdk-0.4.0/src/ha_mqtt_sdk.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dick kouwenhoven
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,439 @@
1
+ Metadata-Version: 2.4
2
+ Name: ha_mqtt_sdk
3
+ Version: 0.4.0
4
+ Summary: Home Assistant MQTT SDK for discovery, topics, and device management
5
+ Author-email: Dick Kouwenhoven <dick.kouwenhoven@planet.nl>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dickkouwenhoven/HA-MQTT-SDK
8
+ Project-URL: Repository, https://github.com/dickkouwenhoven/HA-MQTT-SDK
9
+ Project-URL: Issues, https://github.com/dickkouwenhoven/HA-MQTT-SDK/issues
10
+ Project-URL: Changelog, https://github.com/dickkouwenhoven/HA-MQTT-SDK/releases
11
+ Keywords: homeassistant,mqtt,iot,sdk,automation,python,smarthome
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Topic :: Home Automation
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Requires-Python: >=3.12
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: paho-mqtt>=2.1.0
23
+ Requires-Dist: aiomqtt>=2.5.1
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=9.0.0; extra == "dev"
26
+ Requires-Dist: pytest-cov>=7.0.0; extra == "dev"
27
+ Requires-Dist: pytest-asyncio>=1.0.0; extra == "dev"
28
+ Requires-Dist: ruff>=0.15.0; extra == "dev"
29
+ Requires-Dist: mypy>=2.0.0; extra == "dev"
30
+ Requires-Dist: pre-commit>=4.0.0; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # Home Assistant MQTT SDK
34
+
35
+ Production-ready Python SDK for integrating devices and applications with Home Assistant through MQTT Discovery.
36
+
37
+ The SDK simplifies Home Assistant MQTT integration by automatically handling:
38
+
39
+ - MQTT Discovery payload generation
40
+ - MQTT topic management
41
+ - Entity registration and validation
42
+ - State and availability updates
43
+ - Command handling
44
+ - Plugin system for structured integrations
45
+ - Sync and Async paths
46
+
47
+ ---
48
+
49
+ ## Features
50
+
51
+ - Home Assistant MQTT Discovery support
52
+ - Automatic MQTT topic generation
53
+ - Entity schema validation
54
+ - Availability management
55
+ - Command callback handling
56
+ - Plugin system (`IntegrationPlugin` / `AsyncIntegrationPlugin`)
57
+ - Sync MQTT support via Paho MQTT
58
+ - Async MQTT support via aiomqtt
59
+ - Dependency injection support
60
+ - Extensive test coverage (100%)
61
+ - Type-checked with mypy
62
+ - Docker support
63
+
64
+ ---
65
+
66
+ ## Requirements
67
+
68
+ - Python 3.12+
69
+ - MQTT Broker (Mosquitto recommended)
70
+ - Home Assistant with MQTT integration enabled
71
+
72
+ ---
73
+
74
+ ## Installation
75
+
76
+ Install from PyPI:
77
+
78
+ ```bash
79
+ pip install ha_mqtt_sdk
80
+ ```
81
+
82
+ Or install from source:
83
+
84
+ ```bash
85
+ git clone https://github.com/dickkouwenhoven/HA-MQTT-SDK.git
86
+ cd HA-MQTT-SDK
87
+ pip install -e .
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Two Paths
93
+
94
+ The SDK provides two parallel APIs:
95
+
96
+ | | Sync | Async |
97
+ |---|---|---|
98
+ | **Entry point** | `HASDK` | `AsyncHASDK` |
99
+ | **Manager** | `EntityManager` | `AsyncEntityManager` |
100
+ | **MQTT client** | `PahoMQTTClient` | `AsyncMQTTClient` |
101
+ | **Plugin base** | `IntegrationPlugin` | `AsyncIntegrationPlugin` |
102
+ | **Use when** | Simple integrations | Concurrent / WebSocket integrations |
103
+
104
+ ---
105
+
106
+ ## Quick Start (Sync)
107
+
108
+ ```python
109
+ from ha_mqtt_sdk import HADomain, MQTTSettings, PahoMQTTClient
110
+ from ha_mqtt_sdk.core.sdk import HASDK
111
+
112
+ # 1. Configure connection
113
+ mqtt_config = MQTTSettings(host="localhost", port=1883)
114
+ client = PahoMQTTClient(config=mqtt_config)
115
+ sdk = HASDK(mqtt_client=client)
116
+
117
+ # 2. Create entities — validated against the HA schema
118
+ sensor = sdk.create_entity(
119
+ domain=HADomain.SENSOR,
120
+ name="Temperature",
121
+ unique_id="temp_1",
122
+ extra={"unit_of_measurement": "°C", "device_class": "temperature"},
123
+ )
124
+
125
+ light = sdk.create_entity(
126
+ domain=HADomain.LIGHT,
127
+ name="Living Room",
128
+ unique_id="light_1",
129
+ )
130
+
131
+ # 3. Connect and register
132
+ sdk.start()
133
+
134
+ sdk.register(sensor) # read-only, no callback
135
+ sdk.register(light, command_callback=handle_command) # accepts HA commands
136
+
137
+ # 4. Publish state
138
+ sdk.update_state(sensor, 21.5)
139
+ sdk.update_state(light, "ON")
140
+
141
+ # 5. Shutdown
142
+ sdk.shutdown()
143
+ ```
144
+
145
+ ### Handling commands
146
+
147
+ ```python
148
+ def handle_command(topic: str, payload: str) -> None:
149
+ print(f"Command received: {topic} -> {payload}")
150
+ # forward to your device here
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Quick Start (Async)
156
+
157
+ ```python
158
+ import asyncio
159
+ from ha_mqtt_sdk import HADomain, MQTTSettings
160
+ from ha_mqtt_sdk.mqtt.async_client import AsyncMQTTClient
161
+ from ha_mqtt_sdk.core.async_sdk import AsyncHASDK
162
+
163
+ async def main() -> None:
164
+ mqtt_config = MQTTSettings(host="localhost", port=1883)
165
+ client = AsyncMQTTClient(config=mqtt_config)
166
+ sdk = AsyncHASDK(async_mqtt_client=client)
167
+
168
+ sensor = sdk.create_entity(
169
+ domain=HADomain.SENSOR,
170
+ name="Temperature",
171
+ unique_id="temp_1",
172
+ )
173
+
174
+ await sdk.start()
175
+ await sdk.register(sensor)
176
+ await sdk.update_state(sensor, 21.5)
177
+ await sdk.shutdown()
178
+
179
+ asyncio.run(main())
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Device Info
185
+
186
+ Attach device information to group entities under one device in Home Assistant:
187
+
188
+ ```python
189
+ from ha_mqtt_sdk.models.device_info import DeviceInfo
190
+
191
+ device_info: DeviceInfo = {
192
+ "identifiers": [("my_integration", "device_ABC123")],
193
+ "manufacturer": "IKEA",
194
+ "model": "DIRIGERA",
195
+ "name": "My Hub",
196
+ }
197
+
198
+ entity = sdk.create_entity(
199
+ domain=HADomain.SENSOR,
200
+ name="Temperature",
201
+ unique_id="temp_1",
202
+ device_info=device_info,
203
+ )
204
+ ```
205
+
206
+ ---
207
+
208
+ ## Plugin System
209
+
210
+ For production integrations the SDK provides a plugin system that manages
211
+ the full device lifecycle. Use this when building integrations for real hubs
212
+ (Dirigera, Philips Hue, Z-Wave, etc.).
213
+
214
+ ### Sync plugin
215
+
216
+ ```python
217
+ from ha_mqtt_sdk.core.plugin_interface import IntegrationPlugin
218
+ from ha_mqtt_sdk.core.sdk import HASDK
219
+
220
+ class MyHubPlugin(IntegrationPlugin):
221
+
222
+ def setup(self, sdk: HASDK) -> None:
223
+ """Discover devices and register entities."""
224
+ for device in self._hub.get_devices():
225
+ entity = sdk.create_entity(
226
+ domain=HADomain.LIGHT,
227
+ name=device.name,
228
+ unique_id=device.id,
229
+ )
230
+ sdk.register(entity, command_callback=self.handle_command)
231
+
232
+ def start(self) -> None:
233
+ """Start listening for hub state changes (e.g. background thread)."""
234
+ ...
235
+
236
+ def stop(self) -> None:
237
+ """Disconnect and clean up."""
238
+ ...
239
+
240
+ def handle_command(self, topic: str, payload: str) -> None:
241
+ """Forward HA commands to the hub."""
242
+ ...
243
+
244
+ # Wire up and run
245
+ sdk = HASDK(mqtt_client=client)
246
+ sdk.use_plugin("my_hub", MyHubPlugin(hub))
247
+ sdk.run() # connect → setup → start
248
+ sdk.shutdown() # stop → disconnect
249
+ ```
250
+
251
+ ### Async plugin
252
+
253
+ ```python
254
+ from ha_mqtt_sdk.core.async_plugin_interface import AsyncIntegrationPlugin
255
+ from ha_mqtt_sdk.core.async_sdk import AsyncHASDK
256
+
257
+ class DirigeraPlugin(AsyncIntegrationPlugin):
258
+
259
+ async def setup(self, sdk: AsyncHASDK) -> None:
260
+ devices = await self._hub.get_devices()
261
+ for device in devices:
262
+ entity = sdk.create_entity(
263
+ domain=HADomain.LIGHT,
264
+ name=device.name,
265
+ unique_id=device.id,
266
+ )
267
+ await sdk.register(entity, command_callback=self.handle_command)
268
+
269
+ async def start(self) -> None:
270
+ self._task = asyncio.create_task(self._listen())
271
+
272
+ async def stop(self) -> None:
273
+ if self._task:
274
+ self._task.cancel()
275
+
276
+ async def handle_command(self, topic: str, payload: str) -> None:
277
+ await self._hub.send_command(topic, payload)
278
+
279
+ # Wire up and run
280
+ sdk = AsyncHASDK(async_mqtt_client=client)
281
+ sdk.use_plugin("dirigera", DirigeraPlugin(hub))
282
+ await sdk.run() # connect → setup → start
283
+ await sdk.shutdown() # stop → disconnect
284
+ ```
285
+
286
+ See `examples/plugin_usage/` for a fully worked sync example and
287
+ `examples/async_plugin_usage/` for the async equivalent.
288
+
289
+ ---
290
+
291
+ ## Supported Entity Domains
292
+
293
+ ```python
294
+ from ha_mqtt_sdk import HADomain
295
+
296
+ HADomain.SENSOR
297
+ HADomain.SWITCH
298
+ HADomain.LIGHT
299
+ HADomain.BINARY_SENSOR
300
+ HADomain.CLIMATE
301
+ # ... and more
302
+ ```
303
+
304
+ The complete list is in `ha_mqtt_sdk/config/domains.py`.
305
+
306
+ ---
307
+
308
+ ## Architecture
309
+
310
+ ```
311
+ Your Application
312
+
313
+
314
+ HASDK / AsyncHASDK ← public entry point
315
+
316
+ ├── PluginManager ← optional: manages plugin lifecycle
317
+ │ └── IntegrationPlugin (your integration code)
318
+
319
+ ├── EntityManager ← entity lifecycle, topic routing
320
+
321
+ └── MQTT Client ← Paho (sync) or aiomqtt (async)
322
+
323
+
324
+ MQTT Broker
325
+
326
+
327
+ Home Assistant
328
+ ```
329
+
330
+ ---
331
+
332
+ ## Project Structure
333
+
334
+ ```
335
+ HA-MQTT-SDK/
336
+ ├── examples/
337
+ │ ├── basic_usage/ ← simple sync example
338
+ │ └── plugin_usage/ ← full plugin-based integration example
339
+ ├── src/
340
+ │ └── ha_mqtt_sdk/
341
+ │ ├── builders/ ← topic + payload builders
342
+ │ ├── config/ ← domains, MQTT settings, field schemas
343
+ │ ├── core/ ← SDK, managers, factory, plugin system
344
+ │ │ ├── sdk.py
345
+ │ │ ├── async_sdk.py
346
+ │ │ ├── entity_manager.py
347
+ │ │ ├── async_entity_manager.py
348
+ │ │ ├── entity_factory.py
349
+ │ │ ├── plugin_interface.py
350
+ │ │ ├── async_plugin_interface.py
351
+ │ │ ├── plugin_manager.py
352
+ │ │ └── async_plugin_manager.py
353
+ │ ├── models/ ← Entity, DeviceInfo
354
+ │ ├── mqtt/ ← Paho + aiomqtt clients + base classes
355
+ │ ├── types.py ← PublishPayload, StateValue
356
+ │ ├── exceptions.py
357
+ │ └── utils/
358
+ ├── tests/
359
+ ├── pyproject.toml
360
+ └── README.md
361
+ ```
362
+
363
+ ---
364
+
365
+ ## Testing
366
+
367
+ Run all tests:
368
+
369
+ ```bash
370
+ pytest
371
+ ```
372
+
373
+ Run with coverage:
374
+
375
+ ```bash
376
+ pytest --cov=ha_mqtt_sdk
377
+ ```
378
+
379
+ ---
380
+
381
+ ## Docker
382
+
383
+ The repository includes a complete Docker environment for development and testing.
384
+
385
+ ```bash
386
+ docker compose up --build
387
+ ```
388
+
389
+ This starts:
390
+
391
+ - MQTT Broker (Mosquitto)
392
+ - SDK container
393
+ - Automated test execution
394
+
395
+ ---
396
+
397
+ ## Logging
398
+
399
+ The SDK uses a centralised logging system:
400
+
401
+ ```python
402
+ from ha_mqtt_sdk.utils.logger import get_logger
403
+
404
+ logger = get_logger(__name__)
405
+ logger.info("Integration started")
406
+ ```
407
+
408
+ ---
409
+
410
+ ## Development
411
+
412
+ Install development dependencies:
413
+
414
+ ```bash
415
+ pip install -r requirements-dev.txt
416
+ ```
417
+
418
+ Run the full quality pipeline:
419
+
420
+ ```bash
421
+ ruff check .
422
+ ruff format . --check
423
+ mypy src/ha_mqtt_sdk
424
+ pytest --cov=ha_mqtt_sdk
425
+ ```
426
+
427
+ ---
428
+
429
+ ## License
430
+
431
+ MIT License — see the LICENSE file for details.
432
+
433
+ ---
434
+
435
+ ## Author
436
+
437
+ Dick Kouwenhoven
438
+
439
+ GitHub: https://github.com/dickkouwenhoven/HA-MQTT-SDK