https://github.com/cmgrayb/libdyson-mqtt
MQTT based connections to Dyson devices
https://github.com/cmgrayb/libdyson-mqtt
Last synced: 2 months ago
JSON representation
MQTT based connections to Dyson devices
- Host: GitHub
- URL: https://github.com/cmgrayb/libdyson-mqtt
- Owner: cmgrayb
- License: mit
- Created: 2025-08-17T01:16:16.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2025-08-25T00:42:12.000Z (10 months ago)
- Last Synced: 2026-02-16T00:38:01.435Z (4 months ago)
- Language: Python
- Size: 82 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# libdyson-mqtt
A Python library for MQTT communication with Dyson devices.
## Overview
`libdyson-mqtt` provides a clean, non-blocking interface for communicating with Dyson devices over MQTT. The library handles connection management, message queuing, and provides callbacks for real-time message processing.
## Features
- **Non-blocking operations**: All operations are asynchronous and won't block your application
- **Clean connection management**: Automatic connection handling with proper cleanup
- **Message queuing**: Messages are queued internally for processing
- **Callback support**: Real-time callbacks for messages and connection status
- **Type safety**: Full type annotations and mypy support
- **Comprehensive testing**: Unit and integration tests included
## Installation
```bash
pip install libdyson-mqtt
```
For development:
```bash
pip install -e .[dev]
```
## Quick Start
```python
from libdyson_mqtt import DysonMqttClient, ConnectionConfig
# Configure connection
config = ConnectionConfig(
host="192.168.1.100", # Your Dyson device IP
mqtt_username="your_username",
mqtt_password="your_password",
mqtt_topics=["475/device/status", "475/device/command"],
port=1883,
keepalive=60
)
# Create and connect client
client = DysonMqttClient(config)
client.connect()
# Check if connected
if client.is_connected():
print("Connected successfully!")
# Publish a command
client.publish("475/device/command", '{"command": "status"}')
# Get received messages
messages = client.get_messages()
for msg in messages:
print(f"Topic: {msg.topic}, Payload: {msg.payload_str}")
# Clean disconnect
client.disconnect()
```
## Using Context Manager
For automatic connection management:
```python
from libdyson_mqtt import DysonMqttClient, ConnectionConfig
config = ConnectionConfig(
host="192.168.1.100",
mqtt_username="your_username",
mqtt_password="your_password",
mqtt_topics=["475/device/status", "475/device/command"]
)
# Automatically connects and disconnects
with DysonMqttClient(config) as client:
client.publish("475/device/command", '{"command": "status"}')
messages = client.get_messages()
```
## Using Callbacks
For real-time message processing:
```python
def on_message(message):
print(f"Received: {message.topic} -> {message.payload_str}")
def on_connection_change(connected, error):
if connected:
print("Connected to device!")
else:
print(f"Connection lost: {error}")
client = DysonMqttClient(config)
client.set_message_callback(on_message)
client.set_connection_callback(on_connection_change)
client.connect()
# Messages will now be processed in real-time via callbacks
```
## API Reference
### ConnectionConfig
Configuration class for MQTT connection:
- `host`: IPv4 address or IPv6 .local DNS address
- `mqtt_username`: MQTT username
- `mqtt_password`: MQTT password
- `mqtt_topics`: List of topics to subscribe to
- `port`: MQTT port (default: 1883)
- `keepalive`: Keep-alive interval in seconds (default: 60)
- `client_id`: Optional custom client ID
### DysonMqttClient
Main client class for MQTT communication:
#### Methods
- `connect()`: Connect to MQTT broker (non-blocking)
- `disconnect()`: Disconnect from broker
- `publish(topic, payload, qos=2, retain=False)`: Publish message
- `get_messages(clear_queue=True)`: Get queued messages
- `set_message_callback(callback)`: Set message received callback
- `set_connection_callback(callback)`: Set connection status callback
- `is_connected()`: Check connection status
- `get_status()`: Get detailed connection status
### MqttMessage
Represents a received MQTT message:
- `topic`: Message topic
- `payload`: Raw payload bytes
- `payload_str`: Payload as UTF-8 string
- `qos`: Quality of Service level
- `retain`: Whether message is retained
- `timestamp`: When message was received
- `to_dict()`: Convert to dictionary
## Error Handling
The library defines several exception types:
- `DysonMqttError`: Base exception
- `ConnectionError`: Connection issues
- `AuthenticationError`: Authentication failures
- `TopicError`: Topic subscription/publishing issues
- `ClientNotConnectedError`: Operations on disconnected client
- `CleanupError`: Cleanup failures
```python
from libdyson_mqtt.exceptions import ConnectionError, ClientNotConnectedError
try:
client.connect()
except ConnectionError as e:
print(f"Failed to connect: {e}")
try:
client.publish("test/topic", "message")
except ClientNotConnectedError:
print("Not connected to broker")
```
## Development
Install development dependencies:
```bash
pip install -e .[dev]
```
Run tests:
```bash
pytest
```
Run type checking:
```bash
mypy src/
```
Format code:
```bash
black src/ tests/
isort src/ tests/
```
## Requirements
- Python 3.9+
- paho-mqtt >= 1.6.0
## License
MIT License. See LICENSE file for details.
## Contributing
Contributions are welcome! Please read the contributing guidelines and submit pull requests to the main repository.
## Home Assistant Integration
This library is designed to work well with Home Assistant integrations. The non-blocking design and callback system make it suitable for use in Home Assistant custom components:
```python
# In your Home Assistant integration
import asyncio
from libdyson_mqtt import DysonMqttClient, ConnectionConfig
class DysonDevice:
def __init__(self, hass, config):
self.hass = hass
self.client = DysonMqttClient(config)
self.client.set_message_callback(self._handle_message)
def _handle_message(self, message):
# Process device status updates
self.hass.loop.call_soon_threadsafe(
self._update_state, message
)
async def _update_state(self, message):
# Update Home Assistant entity state
pass
```