Skip to main content

Pyowershades

Pyowershades is an asyncio Python library for communicating with PowerShades motorized shade controllers over UDP. It handles connection management, packet building and parsing, device discovery, and asynchronous status push callbacks. While orginally developed for use in Home Assistant it can work for any asyncio application.

Requirements

  • Python 3.12+

Installation

pip install pyowershades

Usage

Discover devices on the network

import asyncio
from pyowershades import async_discover_devices

async def main():
    devices = await async_discover_devices(["192.168.1.255"])
    for device in devices:
        print(device)  # {"ip": "192.168.1.50", "serial": 12345, "model": 1}

asyncio.run(main())

Connect to a shade and control it

import asyncio
from pyowershades import PowerShadesConnection, OP_SET_POSITION, build_set_position_payload

async def main():
    conn = PowerShadesConnection("192.168.1.50")
    await conn.async_connect()

    # Move to 50%
    await conn.async_request(OP_SET_POSITION, build_set_position_payload(50))

    conn.close()

asyncio.run(main())

Receive live status pushes

from pyowershades import PowerShadesConnection, StatusReply, parse_status_reply

def on_status(status: StatusReply) -> None:
    print(f"Position: {status.position}%  Battery: {status.battery_mv} mV")

conn = PowerShadesConnection("192.168.1.50")
conn.set_status_callback(on_status)
await conn.async_connect()

The shade sends status pushes to whichever UDP socket last sent it a command (the "UDP subscriber"). As long as your connection stays active and periodically polls the device, it will receive live position updates.

API reference

Discovery

async_discover_devices(local_addresses: list[str], timeout: float = ...) -> list[DiscoveredDevice]
async_get_device_info(ip: str, timeout: float = ...) -> PowerShadesDeviceInfo

Connection

class PowerShadesConnection:
    def __init__(self, ip: str) -> None
    async def async_connect(self) -> None
    async def async_request(self, op: int, payload: bytes = b"", ...) -> bytes
    def set_status_callback(self, callback: Callable[[StatusReply], None]) -> None
    def close(self) -> None

Raises PowerShadesTimeoutError if the device does not respond.

Packet building

Function Description
build_packet(op, payload) Build a raw UDP packet for any opcode
build_set_position_payload(percent) Payload for moving to a position (0–100)
build_set_limit_payload(limit_type) Payload for setting upper/lower limits
build_set_name_payload(name) Payload for renaming a PoE shade

Parsing

Function Description
parse_status_reply(data) Parse a status packet into a StatusReply
parse_serial_reply(data) Parse a serial/model reply
parse_shade_name_reply(data) Parse a shade name reply
parse_device_name_reply(data) Parse a device name reply
parse_error_list(raw) Decode Get Debug Info's error_list (comma-separated PoEErrorCode values) into list[int]
battery_percentage(battery_mv) Convert mV to a battery percentage (0–100)

Constants

Opcodes (OP_GET_STATUS, OP_SET_POSITION, OP_JOG_UP, OP_JOG_DOWN, OP_JOG_STOP, OP_STEP_UP, OP_STEP_DOWN, OP_SET_LIMIT, OP_CLEAR_LIMITS, OP_INDICATE, OP_GET_SERIAL, OP_GET_SHADE_NAME, OP_GET_DEVICE_NAME), limit types (LIMIT_UPPER, LIMIT_LOWER), POE_ERROR_CODES (int → name mapping for parse_error_list's output), and timing constants (REQUEST_TIMEOUT, REQUEST_RETRIES, DISCOVERY_TIMEOUT).

See docs/PROTOCOL.md for a full reference of every UDP command the protocol supports, including ones this library doesn't implement yet.

Notes

  • PowerShades devices send status pushes only to the last controller that sent them a command. If another controller (e.g. the PowerShades app or Control4) sends a command, your connection will stop receiving pushes until it sends one again.
  • State inference (opening, closing, open, closed) is not done by this library (beacuse the shade does not send it), only raw position values are reported.
  • Push packets are sent every ~10 seconds by the shade while its moving.
  • Tested with PoE PowerShades controllers. RF hub support is unknown.
  • No authentitcation is needed to control the shade, this means anyone on your local network using this can control your shade(s).

License

MIT

Metadata

Release files for pyowershades 0.3.0

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

Source distribution (sdist)

Source distribution for pyowershades 0.3.0
File Size Uploaded
pyowershades-0.3.0.tar.gz 18.5 kB Details

Built distribution (wheel)

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

Total release size: 31.9 kB

Release files / pyowershades-0.3.0.tar.gz

Download URL pyowershades-0.3.0.tar.gz
Size 18.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6d943ccbf088ff8e35bab714463d8532fae626bce6a0f579d7148ae5b6222228
BLAKE2b-256 checksum
How to use checksums
4939a08b49a154512637566e8e3ecc0bdb424fb4ae629695015173e89314c759
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Release files / pyowershades-0.3.0-py3-none-any.whl

Download URL pyowershades-0.3.0-py3-none-any.whl
Size 13.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f11c95ea0a95f74c5d254f684b84bea9d2d5d69d24a522f9a549f8ca7ea0a4ef
BLAKE2b-256 checksum
How to use checksums
fdcd00c36aae06f3a3b408bf09cf61dfb44ecb5943ae1cdb1542743e1f5d0873
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.1

2 release files

0.4.0

2 release files

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

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