Drive WAREMA WMS blinds/awnings from a USB stick that reads them but won't move them — jog (hold-to-run) drive, no WebControl pro needed. Home Assistant MQTT cover + CLI.
Project description
warema-wms-jog — drive WAREMA WMS blinds/awnings from a USB stick that "won't move" them
If you control WAREMA WMS blinds with the WMS USB stick (via the
santam85/addon-warema-wms Home Assistant
add-on, the Marc-Berg/wms2mqtt fork, or the
warema-wms-venetian-blinds npm
library) and you've hit the wall where the stick reads positions fine but the blind never
moves — this is for you. You do not need the ~€200 WMS WebControl pro.
The problem (sound familiar?)
People keep reporting the same thing:
- the add-on discovers the device, position shows up in Home Assistant, but open/close
does nothing — the log just shows
wmsRetry blindMoveToPos→wmsTimeout; - it's usually blamed on USB3 RF interference or weak range — and sometimes that's real —
- but on many installs reads work perfectly while only commands are ignored, which is not a range problem.
The cause on those installs is the command, not radio and not authorization. The stick's
absolute move-to-position (blindMoveToPos, 7070 03) is protocol-ACKed (7071…) but the
motor never moves. This shows up especially on awnings, which generally have no intermediate
positioning the way venetian blinds do — the actuator simply doesn't act on a go-to-position
command.
Not an authorization/enrollment problem (an earlier version of this README claimed that — it was wrong). The network-key transfer already authorizes the stick: it reads positions and jog drives the motor. Jog (
7070 06/07) and absolute (7070 03) are the same stick → same actuator → same auth context; only the subcommand differs. If the stick were an unauthorized transmitter, jog wouldn't work either. So the stick is authorized — this awning actuator just doesn't execute absolute positioning. (For venetian blinds,blindMoveToPosdoes work over the same stick — that's the library's normal path.)
The fix: drive by JOG (hold-to-run)
When absolute moves no-op, the motor's jog / hold-to-run command — the basic up/down the calibration tools stream while you hold a direction — drives it:
| Telegram | Effect |
|---|---|
{R06<snr>7070 07 FFFFFFFF} streamed ~7×/s |
drive one direction |
{R06<snr>7070 06 FFFFFFFF} streamed ~7×/s |
drive the other direction |
{R06<snr>7070 01 FFFFFFFF...} |
STOP |
It's dead-man: the motor runs only while frames keep arriving (~5–7 Hz), and an explicit
stop frame halts it. Stream 06/07 to drive, poll position, send 01 to stop — and a
read-only stick becomes a fully drivable one. Verified 2026-06 on a WMS-MM balcony awning whose
absolute moves no-op'd; jog drove it cleanly in both directions (confirmed by position
read-back and by eye). See docs/PROTOCOL.md for the byte-level evidence.
⚠️ Safety — read before you drive
Jog has no soft-limit enforcement. In particular the extend / "open" direction of an awning may have NO hard stop — keep streaming and the fabric runs off the end. The retract / "close" direction usually has a hard mechanical stop at fully-closed.
- Never run-to-limit on the extend side. Bound every open by time AND/OR position, poll the position mid-travel, and stop in time.
- If your end positions were ever mis-taught (e.g. a botched calibration), redo them on the handheld first.
- Test from a known position, watch the blind, keep a panic-stop ready
(
warema-wms-jog --stop-only).
Two ways to use it
Install from PyPI:
pip install warema-wms-jog
It ships two console commands: warema-wms-cover (the HA cover service) and
warema-wms-jog (the CLI primitive). The modules are also importable as warema_wms_cover
and warema_wms_jog.
1. Home Assistant cover (recommended — battle-tested)
warema-wms-cover (module warema_wms_cover) is a self-contained service that owns the stick's
serial port, publishes an MQTT-discovery cover to Home Assistant, and maps
open / close / stop and a position slider to bounded jog runs. It drives toward the target,
polls position live, and stops with coast-anticipation so it lands on target — with a hard
position cap on the extend side so it can never run past your calibrated full-extend. It also
polls while idle so moves from your handheld remote are tracked, and emits a remote_move event
you can use as a manual-override trigger.
pip install warema-wms-jog
WMS_KEY=<your-network-key> WMS_SNR=<device-serial> \
MQTT_HOST=<broker> MQTT_USER=<u> MQTT_PASSWORD=<p> \
MAX_OPEN_RAW=<your-full-extend-raw> \
warema-wms-cover
Docker (e.g. as a Home Assistant compose service driving the stick):
warema:
image: python:3-slim
devices: ["/dev/ttyUSB0:/dev/ttyUSB0"]
command: ["sh", "-c", "pip install -q warema-wms-jog && exec warema-wms-cover"]
environment:
- WMS_KEY=${WMS_KEY}
- WMS_SNR=<device-serial>
- MQTT_HOST=<broker>
- MAX_OPEN_RAW=<your-full-extend-raw>
The stick's serial port must be free (stop the stock add-on/bridge first if it holds it). All
knobs are env vars — see the docstring at the top of warema_wms_cover.py (WMS_PORT, WMS_BAUD,
WMS_CHAN, WMS_PAN, MAX_OPEN_RAW, OPEN_SECS, POS_LEAD, …). Find your full-extend raw
value with the CLI tool below (--getpos-only) at the fully-open position.
2. CLI primitive / proof tool
warema-wms-jog (module warema_wms_jog) is a minimal injector to validate jog on your hardware
before wiring anything: it sends the network preamble, reads position, streams a bounded
jog burst, then stops.
pip install warema-wms-jog
# just read position (find your full-extend raw):
WMS_KEY=<key> warema-wms-jog --snr <serial> --getpos-only
# jog ~1s in one direction (watch it move!), then auto-stop:
WMS_KEY=<key> warema-wms-jog --snr <serial> --code 07 --ms 1000
# panic stop:
WMS_KEY=<key> warema-wms-jog --snr <serial> --stop-only
3. Patch for the node add-on/library
patches/addon-warema-wms-jog.patch adds the jog
primitive (blindJog encoder + vnBlindJogStart/vnBlindJogStop) to the vendored
warema-wms-venetian-blinds library inside the add-on, as a non-breaking addition. See
patches/README.md. Upstreamed as a PR to Marc-Berg/wms2mqtt.
Where to find your network key / serial / PAN / channel
These come from your existing add-on setup — the add-on logs print wms_key, wms_pan_id and
wms_channel on first run after the handheld transfers network access data. Never commit your
network key — these tools read it only from the WMS_KEY env var (or, for the warema-wms-jog CLI,
from a capture trace), and redact it from any echo.
Credit
Built on the reverse-engineering in
warema-wms-venetian-blinds by
aemm (MIT) and the santam85/addon-warema-wms
Home Assistant add-on by Marco Santarelli. The jog discovery + drivers here are MIT-licensed.
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 warema_wms_jog-0.1.0.tar.gz.
File metadata
- Download URL: warema_wms_jog-0.1.0.tar.gz
- Upload date:
- Size: 12.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.20 {"installer":{"name":"uv","version":"0.11.20","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":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
17d168a373fc7d3a4058933525722a132db7ba840ce2541b11712cda6d0fae1e
|
|
| MD5 |
a64ed7935425e8e263ff5f381e2d6740
|
|
| BLAKE2b-256 |
d19250e22237e799b863a2c0ffc603678f973c7e9c32d6341ad58b5ab07ca22a
|
File details
Details for the file warema_wms_jog-0.1.0-py3-none-any.whl.
File metadata
- Download URL: warema_wms_jog-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.20 {"installer":{"name":"uv","version":"0.11.20","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":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
167faf7101ef0727c70b6e59291824fa61c60600299fc9fe73e641c575af0efb
|
|
| MD5 |
8ee1a7da6cd07d5416db5e0d53414539
|
|
| BLAKE2b-256 |
76118019014d5e68660e75d35455aa5a95c07f8217d97b522ec06c59149e91ef
|