Skip to main content
pre-commit.ci status Codecov PyPI-Server Monthly Downloads ReadTheDocs

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

  • DYD-ES25A3

  • DYD-B13A3

  • DYD-RT12

  • 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):

  1. Command-line arguments (--username, --password, --token, --device-id)

  2. Process environment variables (DEYE_USERNAME, DEYE_PASSWORD, …)

  3. 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 and device-list payloads may omit any Fog key. Optional controls stay None and are not posted. Diagnostic flags Demisting, WaterTank, and Fan default to off. 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.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for libdeye 3.0.4
File Size Uploaded
libdeye-3.0.4.tar.gz 845.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for libdeye 3.0.4
File Interpreter ABI Platform
libdeye-3.0.4-py3-none-any.whl Python 3 none any Details

Total release size: 876.3 kB

Release files / libdeye-3.0.4.tar.gz

Download URL libdeye-3.0.4.tar.gz
Size 845.1 kB
Tags Source
SHA-256 checksum
How to use checksums
22e5664b5cf5487a9739259b67693a98ef0eb7a42137e4d891697a4df26398f4
BLAKE2b-256 checksum
How to use checksums
8c468dd2aeadf2a97d5d2958ee72e84d1e7a2b814530a5bbebb1ca18e034fa7c
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.4-py3-none-any.whl

Download URL libdeye-3.0.4-py3-none-any.whl
Size 31.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bcdc836f4e1cccf62157431eed5483452e7fd409284157c0c2b680f7264c91d0
BLAKE2b-256 checksum
How to use checksums
4794c820c5bc4a24caa52cf2027cd06e0b0a8a5103ac7a8ed0273761377d4178
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 history Release notifications | RSS feed

This release

3.0.4 This release

2 release files

3.0.3

2 release files

3.0.2

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.1.6

2 release files

2.1.5

2 release files

2.1.4

2 release files

2.1.3

2 release files

2.1.2

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page