Skip to main content

Pure Python async/await implementation for controlling EASYWAVE radio modules (RX11, RX21, RX22, RX25, RX09)

Project description

EASYWAVE Home Control

Pure Python async/await implementation for controlling EASYWAVE radio modules (RX11, RX21, RX22, RX25, RX09).

Optimized for Home Assistant integration with 100% non-blocking async API.

Features

  • Pure Async/Await - No blocking calls on event loop, optimized for Home Assistant
  • Multi-Family Support - Binary protocol (RX11/21/22/25) + ASCII protocol (RX09)
  • High Performance - 115200 baud communication, request pipelining
  • Robust - Comprehensive error handling, health checks, timeout management
  • Clean API - Unified .create() factory method for all devices
  • Type Hints - Full Pylance strict-mode compliant type annotations
  • Well-Tested - Comprehensive examples and integration patterns

Installation

pip install easywave-home-control

Quick Start

Creating Devices

The easiest way is the AsyncDeviceFactory — or use the device class directly for full type safety:

import asyncio
from easywave_home_control import AsyncDeviceFactory, RX11Device

async def main():
    # Option A: Factory (string-based, flexible)
    device = await AsyncDeviceFactory.create("RX11", port="/dev/ttyUSB0", timeout=5.0)

    # Option B: Device class directly (type-safe, recommended for typed code)
    # device = await RX11Device.create(port="/dev/ttyUSB0", timeout=5.0)

    try:
        # Device is now connected and ready to use
        info = await device.get_device_info()
        print(f"Device: {info}")

        # Check connectivity
        connected = await device.ping_request(timeout=3.0)
        print(f"Connected: {connected}")

        # Use device-specific methods
        result, hw_version = await device.query_hw_version()  # hw_version: str
        if result == RX11ErrorCode.SUCCESS:
            print(f"Hardware Version: {hw_version}")
    finally:
        # Always disconnect when done
        await device.disconnect()

asyncio.run(main())

Device Support

RxModule Family (Binary Protocol, 115200 baud)

Device Type Functions Features Baudrate
RX11 USB Transceiver 25 EW, Bidi, Secwave 115200
RX21 Serial Module 25 EW, Bidi, Secwave 115200
RX22 Serial Module 25 EW, Bidi, Secwave 115200
RX25 Serial Module 25 EW, Bidi, Secwave 115200

RX09 Family (ASCII Protocol, 57600 baud)

Device Type Functions Features Baudrate
RX09 Basic Receiver 11 EW Basic only 57600

Async API Documentation

Device Classes

RxModule Devices (Binary Protocol, 115200 baud)

from easywave_home_control import RX11Device, RX21Device, RX22Device, RX25Device

# All RxModule devices use the same interface
device = await RX11Device.create(port="/dev/ttyUSB0")

# RxModule-specific methods
result, hw_version = await device.query_hw_version()  # hw_version: str, e.g. "RX11 V1.3"
result, fw_version = await device.query_fw_version()  # fw_version: str, e.g. "1.4"

# Easywave Basic (EW) functions
result, info_type, transmitter, info_data = await device.ew_rcv_button_request(timeout=30.0)
await device.ew_send_cmd_request(gateway=gateway_serial, button=0)

# Easywave Bidi (EWB) functions
result, receiver = await device.ewb_join_device_request(transmitter_serial)

# Check error codes
if result == RX11ErrorCode.SUCCESS:
    print(f"Success: {info_type}")
else:
    print(f"Error: {result}")

RX09 Device (ASCII Protocol, 57600 baud)

from easywave_home_control import RX09Device

device = await RX09Device.create(port="/dev/ttyUSB0")

# RX09-specific methods
result, serial_number, button_code = await device.receive_telegramm(timeout=30.0)
result, position_count = await device.query_positions()
result = await device.send_telegramm(position=0, button_code="A")

# Check error codes
if result == RX09ErrorCode.SUCCESS:
    print("Success")

Common Methods (All Devices)

# Connection management
# Note: .connect() is called automatically by .create() — only needed for direct instantiation
await device.connect() -> bool
await device.disconnect() -> None

# Device info
await device.get_device_info() -> dict[str, Any]
await device.ping_request(timeout=5.0) -> bool

# Properties (common)
device.is_connected -> bool

RxModule-Only Properties (RX11 / RX21 / RX22 / RX25)

# Detailed status — one of: "connected", "disconnected", "reconnecting", "error", "hardware_error"
device.connection_status -> str
device.has_hardware_error -> bool  # True after USB disconnect or I/O error
device.state_good -> bool          # False if protocol errors have occurred
device.last_error -> str | None    # Last error message, if any

Error Codes

Each device family has device-specific error code enums:

# RxModule devices (RX11, RX21, RX22, RX25)
from easywave_home_control import RX11Device, RX11ErrorCode

if result == RX11ErrorCode.SUCCESS:
    print("Command successful")
elif result == RX11ErrorCode.ERR_RF_TIMEOUT:
    print("RF communication timeout")
elif result == RX11ErrorCode.ERR_FAILSTATE:
    print("Device in failure state")

# RX09 device
from easywave_home_control import RX09Device, RX09ErrorCode

if result == RX09ErrorCode.SUCCESS:
    print("Command successful")

Callbacks

Register callbacks to respond to device events:

def on_disconnect():
    print("Device disconnected or hardware error occurred")

device.set_disconnect_callback(on_disconnect)

# Register callback for spontaneous RCV messages (RX09 only)
def on_button_pressed(data: dict[str, Any]):
    serial = data["serial_number"]
    button = data["button_code"]
    print(f"Button {button} pressed on {serial:06X}")

device.register_rcv_callback(on_button_pressed)

Examples

See the examples/ directory for complete working examples:

Protocol Details

RxModule Protocol (RX11/21/22/25)

Binary request/response protocol at 115200 baud with:

  • Packet structure: [SOP(0x81)] [Function+Params] [EOP(0x82)]
  • Byte stuffing for bytes in range 0x80-0x82
  • Request/response IRP/ICP pairs with handles
  • Timeout support (default 5.0s, RCV functions support indefinite waiting)

RX09 Protocol (RX09)

ASCII text-based protocol at 57600 baud with:

  • Comma-separated commands (e.g., CMD,PARAM1,PARAM2)
  • CR (0x0D) line terminator
  • Simple request/response matching
  • Limited function set (Easywave Basic only)

Type Hints & Validation

The library is fully typed and passes Pylance strict-mode validation:

pylance --mode=strict

All generic types are explicitly specified (no Unknown types):

  • dict[str, Any] instead of dict
  • list[bytes] instead of list
  • asyncio.Task[None] instead of asyncio.Task

Requirements

  • Python 3.9+
  • pyserial >= 3.5

License

Apache License 2.0 - See LICENSE for details.

Contributing

Contributions are welcome! Please submit issues and pull requests to the Home Assistant repository.

Support

For support, please refer to the Home Assistant Easywave Integration documentation.

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

easywave_home_control-0.1.2.tar.gz (36.3 kB view details)

Uploaded Source

Built Distribution

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

easywave_home_control-0.1.2-py3-none-any.whl (38.7 kB view details)

Uploaded Python 3

File details

Details for the file easywave_home_control-0.1.2.tar.gz.

File metadata

  • Download URL: easywave_home_control-0.1.2.tar.gz
  • Upload date:
  • Size: 36.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for easywave_home_control-0.1.2.tar.gz
Algorithm Hash digest
SHA256 c852d7f5be28337440b5bc91c536d6a0f01c5e433deabb572f5d2468bc58c735
MD5 d37a192355417f5f5ce70e64057116b3
BLAKE2b-256 e83fdcf249984214beea303255ccc6547e267f3b935fdf54437e376f397abb64

See more details on using hashes here.

Provenance

The following attestation bundles were made for easywave_home_control-0.1.2.tar.gz:

Publisher: publish.yml on eldateas/PyPI-EasywaveHomeControl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file easywave_home_control-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for easywave_home_control-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0bc4d31da9863ac29c4fadd9053e08370d2c3e8d0155305d823d3316307ba092
MD5 9527d5650e344bf03010b0ce31ebda0e
BLAKE2b-256 e1a8ae3194fa50f5c7b94abd0997b972515047e76ddcf7dc2ca6a0357c704d78

See more details on using hashes here.

Provenance

The following attestation bundles were made for easywave_home_control-0.1.2-py3-none-any.whl:

Publisher: publish.yml on eldateas/PyPI-EasywaveHomeControl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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