Skip to main content

A library to authenticate with yolink device

Project description

YoLink API

A Python library for interacting with YoLink smart home devices. This library provides async support for authenticating with YoLink's cloud API, managing devices, and receiving real-time MQTT events.

Features

  • OAuth2 Authentication: Secure token-based authentication with automatic refresh
  • Device Management: Enumerate and control all YoLink devices in your home
  • Real-time Events: Subscribe to MQTT events for instant device state updates
  • Multi-region Support: Works with both US and EU YoLink endpoints
  • Async/Await: Fully asynchronous design using aiohttp and aiomqtt

Installation

# Using pip
pip install yolink-api

# Using uv
uv add yolink-api

From Source

git clone https://github.com/YoSmart-Inc/yolink-api.git
cd yolink-api
uv sync

Project Structure

yolink-api/
├── examples/                    # Example scripts for common tasks
│   ├── 01_connect_to_api.py    # Basic API connection
│   ├── 02_enumerate_devices.py # List all devices
│   ├── 03_get_device_state.py  # Query device state
│   ├── 04_control_switch.py    # Control switches/outlets
│   └── 05_mqtt_events.py       # Subscribe to real-time events
├── yolink/                      # Main package
│   ├── auth_mgr.py             # Abstract authentication manager
│   ├── client.py               # HTTP client for API requests
│   ├── client_request.py       # Request model for device commands
│   ├── const.py                # Constants and device type definitions
│   ├── device.py               # YoLinkDevice class and models
│   ├── device_helper.py        # Device utility functions
│   ├── endpoint.py             # API endpoint definitions (US/EU)
│   ├── exception.py            # Custom exception classes
│   ├── home_manager.py         # YoLinkHome manager class
│   ├── message_listener.py     # Abstract MQTT message listener
│   ├── message_resolver.py     # Device-specific message parsing
│   ├── model.py                # BRDP/BSDP data models
│   ├── mqtt_client.py          # MQTT client for real-time events
│   ├── outlet_request_builder.py    # Builder for outlet/switch commands
│   ├── thermostat_request_builder.py # Builder for thermostat commands
│   └── unit_helper.py          # Unit conversion utilities
├── pyproject.toml              # Project metadata and dependencies
└── README.md

Getting Started

1. Obtain API Credentials

To use the YoLink API, you need a User Access ID (UAID) and Secret Key:

  1. Log into your YoLink account at yosmart.com
  2. Navigate to SettingsAccountAdvanced SettingsUser Access Credentials
  3. Click Generate to create a new UAID/Secret Key pair
  4. Save these credentials securely - you'll need them for API access

2. Set Environment Variables

Export your credentials as environment variables:

export YOLINK_UAID="your_user_access_id"
export YOLINK_SECRET_KEY="your_secret_key"

3. Run an Example

# Connect to the API and verify credentials
python examples/01_connect_to_api.py

# List all your devices
python examples/02_enumerate_devices.py

Quickstart

Connect to the API

import asyncio
from datetime import datetime, timedelta, timezone

import aiohttp

from yolink.auth_mgr import YoLinkAuthMgr
from yolink.client import YoLinkClient
from yolink.const import OAUTH2_TOKEN
from yolink.endpoint import Endpoints


class SimpleAuthManager(YoLinkAuthMgr):
    """Simple auth manager implementation."""
    
    def __init__(self, session: aiohttp.ClientSession, uaid: str, secret_key: str):
        super().__init__(session)
        self._uaid = uaid
        self._secret_key = secret_key
        self._access_token = None
        self._token_expires_at = None
    
    def access_token(self) -> str:
        return self._access_token or ""
    
    async def check_and_refresh_token(self) -> str:
        if (
            self._access_token is None
            or self._token_expires_at is None
            or datetime.now(timezone.utc) >= self._token_expires_at - timedelta(minutes=5)
        ):
            await self._fetch_token()
        return self._access_token
    
    async def _fetch_token(self) -> None:
        async with self._session.post(
            OAUTH2_TOKEN,
            data={
                "grant_type": "client_credentials",
                "client_id": self._uaid,
                "client_secret": self._secret_key,
            },
        ) as response:
            response.raise_for_status()
            data = await response.json()
            self._access_token = data["access_token"]
            expires_in = data.get("expires_in", 7200)
            self._token_expires_at = datetime.now(timezone.utc) + timedelta(seconds=expires_in)


async def main():
    uaid = "your_uaid"
    secret_key = "your_secret_key"
    
    async with aiohttp.ClientSession() as session:
        auth_mgr = SimpleAuthManager(session, uaid, secret_key)
        client = YoLinkClient(auth_mgr)
        
        # Authenticate
        await auth_mgr.check_and_refresh_token()
        print("Connected!")

asyncio.run(main())

Enumerate Devices

async def list_devices(client: YoLinkClient):
    response = await client.execute(
        url=Endpoints.US.value.url,
        bsdp={"method": "Home.getDeviceList"}
    )
    
    for device in response.data.get("devices", []):
        print(f"{device['name']} ({device['type']}) - {device['deviceId']}")

Get Device State

from yolink.device import YoLinkDevice, YoLinkDeviceMode

async def get_device_state(client: YoLinkClient, device_data: dict):
    # Create a device instance from the device data
    device_mode = YoLinkDeviceMode(**device_data)
    device = YoLinkDevice(device_mode, client)
    
    # Get current state
    state = await device.get_state()
    print(f"State: {state.data}")

Control a Switch

from yolink.outlet_request_builder import OutletRequestBuilder

async def toggle_switch(device: YoLinkDevice, turn_on: bool):
    # "open" = ON, "close" = OFF
    state = "open" if turn_on else "close"
    request = OutletRequestBuilder.set_state_request(state=state, plug_indx=None)
    result = await device.call_device(request)
    
    if result.code == "000000":
        print("Success!")
    else:
        print(f"Failed: {result.desc}")

Subscribe to MQTT Events

import aiomqtt

async def listen_for_events(auth_mgr: SimpleAuthManager, home_id: str):
    topic = f"yl-home/{home_id}/+/report"
    
    async with aiomqtt.Client(
        hostname=Endpoints.US.value.mqtt_broker_host,
        port=Endpoints.US.value.mqtt_broker_port,
        username=auth_mgr.access_token(),
        password="",
        keepalive=60,
    ) as client:
        await client.subscribe(topic)
        
        async for message in client.messages:
            print(f"Event: {message.payload.decode()}")

Supported Devices

This library supports a wide range of YoLink devices including:

Category Device Types
Hubs Hub (YS1603-UC), SpeakerHub (YS1604-UC)
Sensors Door Sensor, Motion Sensor, Water Leak Sensor, Temperature/Humidity Sensor, Vibration Sensor, CO/Smoke Alarm, Soil Sensor
Switches & Outlets In-Wall Switch, Outlet, Multi-Outlet, Smart Plug, Power Strip
Controllers Thermostat, Garage Door Controller, Water Valve, Sprinkler Controller
Locks Smart Lock M1, Smart Lock M2
Remotes KeyFob, On/Off Fob, DimmerFob, SirenFob, FlexFob
Alarms Siren Alarm, Outdoor Alarm, Power Fail Alarm

See the full device list below for specific model numbers.

API Reference

YoLinkAuthMgr (Abstract Base Class)

The authentication manager handles OAuth2 token management. You must implement:

  • access_token() -> str: Return the current access token
  • check_and_refresh_token() -> str: Ensure token is valid, refresh if needed

YoLinkClient

The HTTP client for making API requests:

  • execute(url, bsdp, **kwargs) -> BRDP: Execute an API request
  • get(url, **kwargs) -> ClientResponse: Make a GET request
  • post(url, **kwargs) -> ClientResponse: Make a POST request

YoLinkDevice

Represents a single YoLink device:

  • get_state() -> BRDP: Get real-time device state
  • fetch_state() -> BRDP: Fetch cached device state
  • call_device(request: ClientRequest) -> BRDP: Send a command to the device

YoLinkHome

High-level manager for your YoLink home (used for Home Assistant integration):

  • async_setup(auth_mgr, listener): Initialize the home manager
  • async_unload(): Clean up resources
  • get_devices() -> list[YoLinkDevice]: Get all devices
  • get_device(device_id) -> YoLinkDevice: Get a specific device

Device Models

Click to expand full device list
  • YS1603-UC (Hub)
  • YS1604-UC (SpeakerHub)
  • YS3604-UC (YoLink KeyFob)
  • YS3605-UC (YoLink On/OffFob)
  • YS3606-UC (YoLink DimmerFob)
  • YS3607-UC (YoLink SirenFob)
  • YS3614-UC (YoLink Mini FlexFob)
  • YS4002-UC (YoLink Thermostat)
  • YS4003-UC (YoLink Thermostat Heatpump)
  • YS4906-UC + YS7706-UC (Garage Door Kit 1)
  • YS4908-UC + YS7706-UC (Garage Door Kit 2 (Finger))
  • YS4909-UC (Water Valve Controller)
  • YS5001-UC (X3 Water Valve Controller)
  • YS5002-UC (YoLink Motorized Ball Valve)
  • YS5003-UC (Water Valve Controller 2)
  • YS5705-UC (In-Wall Switch)
  • YS5706-UC (YoLink Relay)
  • YS5707-UC (Dimmer Switch)
  • YS5708-UC (In-Wall Switch 2)
  • YS6602-UC (YoLink Energy Plug)
  • YS6604-UC (YoLink Plug Mini)
  • YS6704-UC (In-wall Outlet)
  • YS6801-UC (Smart Power Strip)
  • YS6802-UC (Smart Outdoor Power Strip)
  • YS6803-UC (Outdoor Energy Plug)
  • YS7103-UC (Siren Alarm)
  • YS7104-UC (Outdoor Alarm Controller)
  • YS7105-UC (X3 Outdoor Alarm Controller)
  • YS7106-UC (Power Fail Alarm)
  • YS7107-UC (Outdoor Alarm Controller 2)
  • YS7201-UC (Vibration Sensor)
  • YS7606-UC (YoLink Smart Lock M1)
  • YS7607-UC (YoLink Smart Lock M2)
  • YS7704-UC (Door Sensor)
  • YS7706-UC (Garage Door Sensor)
  • YS7707-UC (Contact Sensor)
  • YS7804-UC (Motion Sensor)
  • YS7805-UC (Outdoor Motion Sensor)
  • YS7903-UC (Water Leak Sensor)
  • YS7904-UC (Water Leak Sensor 2)
  • YS7906-UC (Water Leak Sensor 4)
  • YS7916-UC (Water Leak Sensor 4 MoveAlert)
  • YS7905-UC (WaterDepthSensor)
  • YS7A01-UC (Smart Smoke/CO Alarm)
  • YS8003-UC (Temperature Humidity Sensor)
  • YS8004-UC (Weatherproof Temperature Sensor)
  • YS8005-UC (Weatherproof Temperature & Humidity Sensor)
  • YS8006-UC (X3 Temperature & Humidity Sensor)
  • YS8014-UC (X3 Outdoor Temperature Sensor)
  • YS8015-UC (X3 Outdoor Temperature & Humidity Sensor)
  • YS5006-UC (FlowSmart Control)
  • YS5007-UC (FlowSmart Meter)
  • YS5008-UC (FlowSmart All-in-One)
  • YS8017-UC (Thermometer)
  • YS5009-UC (LeakStop Controller)
  • YS5029-UC (LeakStop Controller 2 Channel)
  • YS8009-UC (Soil Temperature & Humidity Sensor)
  • YS4102-UC (Smart Sprinkler Controller)
  • YS4103-UC (Smart Sprinkler Controller V2)
  • YS7A12-UC (Smoke Alarm)
  • YS7A06-UC (Smart CO Alarm)

Error Handling

The library defines several exception types:

  • YoLinkError: Base exception class
  • YoLinkClientError: API request errors
  • YoLinkAuthFailError: Authentication failures
  • YoLinkDeviceConnectionFailed: Device communication errors
  • YoLinkUnSupportedMethodError: Unsupported device operations
from yolink.exception import YoLinkClientError, YoLinkAuthFailError

try:
    await device.get_state()
except YoLinkAuthFailError:
    print("Authentication failed - check your credentials")
except YoLinkClientError as e:
    print(f"API error {e.code}: {e.message}")

Dependencies

  • aiohttp>=3.8.1 - Async HTTP client
  • aiomqtt>=2.0.0,<3.0.0 - Async MQTT client
  • pydantic>=2.0.0 - Data validation
  • tenacity>=8.1.0 - Retry logic

License

MIT License - see LICENSE for details.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yolink_api-0.6.4.tar.gz (22.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yolink_api-0.6.4-py3-none-any.whl (24.3 kB view details)

Uploaded Python 3

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page