libdeye
A Python library to connect to Deye 德业 Cloud and control Deye dehumidifier devices.
Supported devices:
DYD-B12A3
DYD-D50A3
DYD-D50B3
DYD-E12A3
DYD-G25A3
DYD-N20A3
DYD-L48A3
DYD-T22A3
DYD-U20A3
DYD-U20Air
DYD-V58A3
DYD-W20A3
DYD-W20A3-京鱼座
DYD-X20A3
DYD-Z12A3
DYD-Z20B3
DYD-Z20B3-天猫精灵
DYD-S12A3
DYD-F20C3
JD121EC
JD201FC
TM208FC
DY-612S
DY-620S
DY-8220C
DY-890C
DY-890T
DY-6138A
DY-8138C
DY-8158C
DY-8158T
DY-Y16A3
DY-SC60Y
DYD-P40
A10
DYD-P30
DY-C65DZ/A
For devices not in the above list, consider adding your own definitions here.
Command Line Tool
This library also includes a command-line tool for testing and interacting with Deye devices.
Installation
The CLI tool is automatically installed when you install the library:
pip install libdeye
# or
uv add libdeye
Usage
# List devices (prints platform and CLASSIC / FOG / COMBO transport)
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD devices
# List all available product types
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD products
# Get device state (works for Classic, Fog, and Combo)
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD get --device-id YOUR_DEVICE_ID
# Set device state
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD set --device-id YOUR_DEVICE_ID --power on --target-humidity 50
# Set device mode and fan speed (enum names, not display labels)
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD set --device-id YOUR_DEVICE_ID --mode AUTO_MODE --fan-speed HIGH
# Set additional device features
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD set --device-id YOUR_DEVICE_ID --anion on --oscillating on --water-pump off --child-lock off
# Monitor device state changes in real-time
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD monitor --device-id YOUR_DEVICE_ID
# Get MQTT information for Classic platform
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD classic-mqtt
# Get MQTT information for Fog platform
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD fog-mqtt
# Enable debug logging
deye-cli --debug --username YOUR_USERNAME --password YOUR_PASSWORD devices
# Print authentication token (useful for saving to .env file)
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD print-token
# Force refresh the authentication token
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD refresh-token
Using Environment Variables and .env Files
Credentials can be provided via command-line arguments, process environment variables, or a .env file. Precedence (highest to lowest):
Command-line arguments (--username, --password, --token, --device-id)
Process environment variables (DEYE_USERNAME, DEYE_PASSWORD, …)
Values from a .env file
This matches the default behavior of python-dotenv and 12-factor app conventions: .env is a local default, and already-set environment variables are not overwritten.
You can export variables in your shell:
export DEYE_USERNAME=your_username
export DEYE_PASSWORD=your_password
deye-cli devices
Or store them in a .env file to avoid typing them in each command:
# Create a .env file in your working directory
echo "DEYE_USERNAME=your_username" > .env
echo "DEYE_PASSWORD=your_password" >> .env
# Now you can run commands without specifying credentials
deye-cli devices
# You can also specify a different .env file location
deye-cli --env-file /path/to/your/.env devices
The supported variable names (used by both the environment and .env files) are:
DEYE_USERNAME=your_phone_number_or_username
DEYE_PASSWORD=your_password
# Optional: store auth token to avoid login each time
DEYE_AUTH_TOKEN=your_auth_token
# Optional: default device for get / set / monitor
DEYE_DEVICE_ID=your_device_id
With DEYE_DEVICE_ID configured, you can omit --device-id:
# Get device state without specifying device-id
deye-cli get
# Set device state without specifying device-id
deye-cli set --power on --target-humidity 50
# Monitor device state changes
deye-cli monitor
Getting and Using Authentication Tokens
To avoid sending your username and password with each request, you can use an authentication token:
# Get your authentication token
deye-cli --username YOUR_USERNAME --password YOUR_PASSWORD print-token
# Copy the token and add it to your .env file
echo "DEYE_AUTH_TOKEN=your_token_here" >> .env
# Now you can use the token instead of username/password
deye-cli devices
# If your token expires, you can refresh it
deye-cli --token YOUR_TOKEN refresh-token
Available Commands
devices: List devices on the account, including IoT platform and command transport (CLASSIC, FOG, or COMBO)
products: List all available product types
get: Query current state via DeyeClient (Classic MQTT poll, Fog HTTP GET, or Combo MQTT poll)
set: Send a command via DeyeClient.apply (power, mode, fan speed, humidity, anion, water pump, oscillating, child lock, plus optional Fog sleep / UV / temperature / prompt sound / screen display / timed-off hour)
monitor: Subscribe to MQTT state and availability updates
print-token: Print the authentication token for use in .env file
refresh-token: Force refresh the authentication token
classic-mqtt: Get MQTT broker credentials for Classic / Combo devices
fog-mqtt: Get MQTT broker credentials for Fog devices (inbound state only; Fog commands use HTTP)
set --mode and set --fan-speed take DeyeDeviceMode / DeyeFanSpeed enum names, for example MANUAL_MODE, CLOTHES_DRYER_MODE, AUTO_MODE, LOW, HIGH. Humidity range depends on the product (often 25-80 or 26-90).
For more options, run:
deye-cli --help
Public API
Callers use DeyeClient and DeyeDevice. The library selects Classic MQTT, Fog HTTP, or Combo MQTT from each device-list entry. Do not construct platform MQTT clients yourself.
Call refresh() or ensure_connected() before subscribe(). Send commands with device.apply(command, baseline=...). Fog devices with cached ProtocolVersion == 0 send the official companion snapshot for each changed property (not a union of every cached key); otherwise only changed fields are posted.
DeyeDeviceCommand.to_json matches official FogDeviceManager.sendCommand: every PropertyParam Integer is skipped when null, including child lock and anion. Unset library fields stay None and are omitted. Classic to_bytes treats unset switches as off.
The product JSON (uvLight, tone, displayScreen, hasDelayer) only shows or hides those controls, the same way it gates anion and oscillating. Use get_product_feature_config (uv, prompt_sound, screen_display, timed_off) to decide whether a product advertises them.
Fog GET payloads may omit any of those keys; a missing or invalid value stays None and is not posted. ProtocolVersion == 0 companions copy cached non-null Integers for that command’s official key set (display, tone, and timer stay single-key). Sleep is DeyeDeviceMode.SLEEP_MODE. to_json_diff treats omitted keys as absent on the baseline, so the first set value is published without the caller inventing a placeholder.
import asyncio
import aiohttp
from libdeye import DeyeClient
async def main() -> None:
async with aiohttp.ClientSession() as session:
client = DeyeClient.from_credentials(
session, "<phone_number>", "<password>"
)
await client.authenticate()
devices = await client.list_devices()
if not devices:
print("No devices found")
return
device = devices[0]
print(f"Device: {device.name} (ID: {device.device_id})")
print(f"Transport: {device.transport.name}")
state = await device.refresh()
print(
f"Current humidity: {state.environment_humidity}% "
f"(Target: {state.target_humidity}%)"
)
def on_state_update(state) -> None:
print(
f"Device state updated. Current humidity: "
f"{state.environment_humidity}%"
)
unsubscribe = device.subscribe(on_state=on_state_update)
command = state.to_command()
command.target_humidity = 40
await device.apply(command, baseline=state)
await asyncio.sleep(30)
unsubscribe()
client.disconnect()
if __name__ == "__main__":
asyncio.run(main())
Metadata
Release files for libdeye 3.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| libdeye-3.0.2.tar.gz | 840.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| libdeye-3.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 870.8 kB
Release files / libdeye-3.0.2.tar.gz
| Download URL | libdeye-3.0.2.tar.gz |
|---|---|
| Size | 840.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
777532a9b925619816af5aa1bff1668f312e626530e7cc5d1cd96a45fa59f5e2
|
|
BLAKE2b-256 checksum How to use checksums |
4ac0a9c41323590d0404c1a6d0b72e927b8d8a7e85c92806e758b809cc684ed5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / libdeye-3.0.2-py3-none-any.whl
| Download URL | libdeye-3.0.2-py3-none-any.whl |
|---|---|
| Size | 30.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a62f4e08c3050ac2ad64eeae40e22b2434148449aa31ac9899844180524c98f2
|
|
BLAKE2b-256 checksum How to use checksums |
f052d3fc2cfa198791f4e11ba6f5f62ad8c1cab9b167ab96566c59a9c1574c28
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|