Async Python library to control Zeptrion lights and blinds (Feller / Schneider Electric)
Project description
pyzeptrion
An async Python library for controlling Zeptrion devices made by Feller AG (Schneider Electric). Supports lights (on/off and dimmable bulbs) and covers (blinds/shutters).
For the implementation, I used the API documentation provided by Feller AG. Unfortunately, this documentation has been discontinued since March 2025.
Supported devices
Tested with:
The library implements the Zeptrion REST API (/zrap/) which is available on all Zeptrion Wi-Fi devices. Other Zeptrion products should work as well.
Device types detected automatically:
| API cat | Type |
|---|---|
| 1 | Bulb on/off |
| 3 | Bulb dimmable |
| 5 / 6 | Blind |
Requirements
- Python 3.10+
- One or more Zeptrion devices on your local network
- Consumers (bulbs, blinds) wired to the switch channels
Installation
pip install pyzeptrion
Quick start
All classes use async/await. Use asyncio.run() or an existing event loop.
Discover devices on the network
import asyncio
from pyzeptrion.discover import ZeptrionRegistry
async def main():
registry = await ZeptrionRegistry.create_registry()
for device in registry.devices:
print(device)
asyncio.run(main())
Output example:
Host: 192.168.0.181 Channel: 1 dev_type: Bulb dimmable
Host: 192.168.0.185 Channel: 1 dev_type: Blind
...
Control a dimmable bulb
import asyncio
from pyzeptrion.bulb import ZeptrionBulb
async def main():
bulb = await ZeptrionBulb.create("192.168.0.181", "1")
await bulb.on() # turn on
await bulb.off() # turn off
await bulb.set_level(30) # dim to 30% (0–100)
await bulb.set_level(100) # full brightness
await bulb.set_level(0) # turn off via set_level
print(bulb)
await bulb.close()
asyncio.run(main())
Note on dimming: The Zeptrion API does not expose the current brightness level — the state endpoint only returns on/off.
set_level()uses a calibrated press-and-hold strategy: it ramps fully up to 100 %, then holdsdim_downfor a proportional duration based on the target level. The full travel time constant (DIMMER_FULL_TRAVEL_TIME = 3.4 s) was measured on real hardware and can be adjusted inpyzeptrion/const.pyif your device travels faster or slower.
Control a blind
import asyncio
from pyzeptrion.blind import ZeptrionBlind
async def main():
blind = await ZeptrionBlind.create("192.168.0.185", "1")
await blind.move_open() # open
await blind.move_close() # close
await blind.stop() # stop mid-movement
await blind.close()
asyncio.run(main())
Using an existing aiohttp session
All classes accept an optional session parameter so you can share a single aiohttp.ClientSession across multiple devices (useful for Home Assistant integrations):
import asyncio
import aiohttp
from pyzeptrion.bulb import ZeptrionBulb
async def main():
async with aiohttp.ClientSession() as session:
bulb = await ZeptrionBulb.create("192.168.0.181", "1", session=session)
await bulb.on()
asyncio.run(main())
API reference
ZeptrionBulb
| Method | Description |
|---|---|
await ZeptrionBulb.create(host, chn, session=None) |
Factory — creates and initialises the object |
await bulb.on() |
Turn on |
await bulb.off() |
Turn off |
await bulb.dim_up() |
Start dimming up (press-and-hold) |
await bulb.dim_down() |
Start dimming down (press-and-hold) |
await bulb.set_level(target) |
Dim to target % (0–100); 0 turns the light off |
await bulb.get_state() |
Returns True (on) or False (off) |
await bulb.post_cmd(cmd) |
Send a raw command string to the device |
await bulb.close() |
Close the aiohttp session (only if owned by this object) |
Properties: name, group, host, chn, dev_type, dev_id, state
ZeptrionBlind
| Method | Description |
|---|---|
await ZeptrionBlind.create(host, chn, session=None) |
Factory — creates and initialises the object |
await blind.move_open() |
Open the blind |
await blind.move_close() |
Close the blind |
await blind.stop() |
Stop movement |
await blind.get_state() |
Returns True (open) or False (closed) |
await blind.close() |
Close the aiohttp session |
Properties: name, group, host, chn, dev_type, dev_id, state
ZeptrionRegistry
| Method | Description |
|---|---|
await ZeptrionRegistry.create_registry() |
Discovers all Zeptrion devices via Zeroconf (waits ~5 s) |
registry.devices |
List of ZeptrionRegistryDevice objects, sorted by type |
ZeptrionRegistryDevice has properties: host, chn, dev_type
Command line interface
# Discover all devices on the network
python3 -m pyzeptrion.cli discover
# Turn a bulb on/off
python3 -m pyzeptrion.cli set -a 192.168.0.181 -c 1 -p on
python3 -m pyzeptrion.cli set -a 192.168.0.181 -c 1 -p off
# Dim a dimmable bulb to a specific level (0–100)
python3 -m pyzeptrion.cli set -a 192.168.0.181 -c 1 -p dim_to --level 30
# Control a blind
python3 -m pyzeptrion.cli set -a 192.168.0.185 -c 1 -p move_close
python3 -m pyzeptrion.cli set -a 192.168.0.185 -c 1 -p move_open
python3 -m pyzeptrion.cli set -a 192.168.0.185 -c 1 -p stop
Valid commands for bulbs: on, off, toggle, dim_up, dim_down, dim_to (requires --level)
Valid commands for blinds: move_open, move_close, stop
Exceptions
| Exception | When raised |
|---|---|
ZeptrionConnectionError |
Network timeout or HTTP error communicating with the device |
ZeptrionError |
Base exception class |
Home Assistant
This library is designed to be used as the backend for a Home Assistant custom integration. See the companion repository for details.
Development
Set up
git clone https://github.com/footprintsonthemoon/zeptrion_python.git
cd zeptrion_python
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Run the tests
pytest tests/
The test suite uses pytest-asyncio and aioresponses to mock all HTTP and Zeroconf calls — no real hardware is needed.
Build and publish
# Build source distribution and wheel
python -m build
# Upload to PyPI (requires a PyPI account and API token)
twine upload dist/pyzeptrion-*
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyzeptrion-2.0.1.tar.gz.
File metadata
- Download URL: pyzeptrion-2.0.1.tar.gz
- Upload date:
- Size: 17.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df523a60e7b09a51399ed7238cc7f00fbdebfc2c035435ceb2358c3153cefdac
|
|
| MD5 |
2f034230ccb79ef1d9b6f09d8c0fdca4
|
|
| BLAKE2b-256 |
a2e42cb56a7fd7cb17c623fc502b770bf777a13a88f1d4c07bace318fb0a1544
|
File details
Details for the file pyzeptrion-2.0.1-py3-none-any.whl.
File metadata
- Download URL: pyzeptrion-2.0.1-py3-none-any.whl
- Upload date:
- Size: 12.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a23ebca17fa9bd5a5b59ad5db026f6b53108efdc89192b6c04c3c140fd97632
|
|
| MD5 |
0c7f488e3e292d569c1745fa64b57b6f
|
|
| BLAKE2b-256 |
f3b13c89e123e90e6c6f4bc9c6572a723c43ffa60bdebb24a8caf7628374eaa0
|