Skip to main content

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 blindMoveToPoswmsTimeout;
  • 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, blindMoveToPos does 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.

Radio self-heal (0.1.1). The stick's WMS session ({G} / {M#} / {K}) can be lost while the serial port stays open — no error, no exception, nothing in dmesg. Every position read then returns nothing and every drive aborts with no position read, so the cover silently stops moving. The bridge now replays the handshake itself after REINIT_AFTER (default 5) consecutive failed reads, escalating to a serial-port reopen if replays don't take, and publishes availability = offline while the radio is down — so a dead stick shows up in HA as an unavailable cover instead of one that just quietly ignores you. Tune with REINIT_AFTER / REINIT_MIN_GAP (default 30 s between attempts).

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.

Download files

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

Source Distribution

warema_wms_jog-0.1.1.tar.gz (16.8 kB view details)

Uploaded Source

Built Distribution

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

warema_wms_jog-0.1.1-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file warema_wms_jog-0.1.1.tar.gz.

File metadata

  • Download URL: warema_wms_jog-0.1.1.tar.gz
  • Upload date:
  • Size: 16.8 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

Hashes for warema_wms_jog-0.1.1.tar.gz
Algorithm Hash digest
SHA256 c3e55386d514d62209dca69d16b931c31edf52855a0b592cb968776a4bac0f97
MD5 21d41070de89a90f724020ef9d30d8f1
BLAKE2b-256 01a825b2870e55031fb0f89882f909cd03481216923173c0d61a75fed0fc7a00

See more details on using hashes here.

File details

Details for the file warema_wms_jog-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: warema_wms_jog-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 14.7 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

Hashes for warema_wms_jog-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f764ab794eb004d806b9c4e253e60ddbe0ca8d129ed334b06d2603d4424efbb8
MD5 8db29aba2caf147c22d932f76fa20205
BLAKE2b-256 b7bd18626324879fbc7ebb6fa72ca7670d52a81c74a26f0bfdebd5c437a48b87

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 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