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

  • 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 also carries Fog extras that official dehumidifier product JSON optionally defines: uv_switch, prompt_sound, screen_display, and timed_off_hour.

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. If it does, callers should expose the matching command/state fields.

The Fog send path does not invent values. FogDeviceManager.sendCommand posts a key only when the cached bean or the user action set it. ProtocolVersion == 0 companions copy UV and TimedOffHour from cache when present; display, tone, and timer commands stay single-key. Unset library fields stay None and are omitted from Fog JSON. Sleep is DeyeDeviceMode.SLEEP_MODE.

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.1

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.1
File Size Uploaded
libdeye-3.0.1.tar.gz 839.5 kB Details

Built distribution (wheel)

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

Total release size: 869.1 kB

Release files / libdeye-3.0.1.tar.gz

Download URL libdeye-3.0.1.tar.gz
Size 839.5 kB
Tags Source
SHA-256 checksum
How to use checksums
4e2e5e6f8ed8db8187ede6c4ea0126e8c4dab4a55c07ddde53ae5f88f28009df
BLAKE2b-256 checksum
How to use checksums
e539e9b5f9bf82431991ac6c1df3e9869e17e28320b8f7f4fe111880aa830a59
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.1-py3-none-any.whl

Download URL libdeye-3.0.1-py3-none-any.whl
Size 29.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e11bbd7187617e67dfe6c9b55e07c1d7fdc3e3fa6b405f7d0cf6e86f645d49aa
BLAKE2b-256 checksum
How to use checksums
85420956b3ca12035d6d45334d77623954b78e1c8bfcdc527cb19c893b5aed13
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

3.0.4

2 release files

3.0.3

2 release files

3.0.2

2 release files

This release

3.0.1 This release

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