From wb-plc
Writing software FOR Wiren Board controllers — custom daemons (C++/Python/Go), MQTT bridges (Zigbee2MQTT → WB, Modbus → WB, custom hardware), MQTT-RPC services, wbdev cross-compilation, Debian packaging, /devices/X/controls/Y topic conventions. Use when user wants to write a daemon, integration bridge, or hardware adapter. NOT for wb-rules JS automation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/wb-plc:wb-devThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Load when the task involves **writing code** that runs on or talks to a WB controller:
Load when the task involves writing code that runs on or talks to a WB controller:
/devices/…/controls/…, KNX → WB, custom hardware → WB)Do NOT load for:
/wb-rules insteadEvery integration or service running on WB must expose its state and any connected devices/sensors as MQTT virtual devices following the WB conventions (see the MQTT conventions section below).
This is non-negotiable — the web interface, wb-rules automation, and other services on the controller all consume the unified /devices/…/controls/… topic space. An integration that talks only to its own internal bus or API without publishing to MQTT is invisible to the rest of the WB ecosystem.
What to expose:
| What you have | What to publish |
|---|---|
| Integration service itself | A virtual device with status/version controls, e.g. /devices/my-integration/controls/status |
| Connected physical device (sensor, actuator) | A virtual device per unit: /devices/my-sensor_1/… |
| Numeric reading (temperature, power, etc.) | A value control with units set |
| On/off controllable output | A switch control (writable, no readonly) |
| Service error or connectivity loss | Set /devices/<id>/meta/error non-empty (LWT pattern) |
All meta topics (/devices/<id>/meta, /devices/<id>/controls/<id>/meta) must be published with the retained flag on startup.
| Controller | Architecture | libc |
|---|---|---|
| WB8 | arm64 | 2.31 |
| WB6 / WB7 | armhf | 2.31 |
| WB5 and earlier | armel | 2.31 |
Compiling directly on the controller is discouraged (limited RAM). Use cross-compilation via wbdev.
Default to Docker for custom software and integrations. Use a deb package only when the package is small, self-contained, and has no external runtime dependencies.
Decision rule:
| Docker | deb package | |
|---|---|---|
| Root partition impact | None | Uses limited root space |
| Survives firmware update | Yes (data in /mnt/data) | Config in /etc may be reset |
| Dependency management | Bundled in image | Requires WB apt repo |
| When to use | Complex integrations, third-party runtimes, anything co-located with Dockerized software | Small self-contained daemon with only WB-apt deps |
Follow the WB wiki, not generic Docker docs: WebFetch('https://wiki.wirenboard.com/wiki/Docker')
wb-docker-manager.sh (not apt install docker-ce — that breaks the storage path)/mnt/data/ — the larger partition, survives firmware updates/mnt/data/<project>/docker-compose.yml# Deploy a new service
ssh root@<HOST> 'mkdir -p /mnt/data/my-integration'
scp docker-compose.yml root@<HOST>:/mnt/data/my-integration/
ssh root@<HOST> 'docker compose -f /mnt/data/my-integration/docker-compose.yml up -d'
# Check logs
ssh root@<HOST> 'docker compose -f /mnt/data/my-integration/docker-compose.yml logs -f'
For the container to publish to the local MQTT broker, use network_mode: host in docker-compose — this is the simplest approach on WB and avoids any bridge networking issues. With host networking, localhost:1883 inside the container reaches the host's mosquitto directly.
services:
my-integration:
image: my-integration:latest
network_mode: host
restart: unless-stopped
Docker-based cross-compilation tool. All packaging commands run on the developer machine and produce a .deb.
wbdev chroot # interactive cross-build shell
wbdev make # invoke make inside the container
wbdev cdeb # build and package a C++ project
wbdev gdeb # build and package a Go project
wbdev ndeb # build an architecture-independent package
Install the produced .deb on the controller:
scp package.deb root@<HOST>:/tmp/
ssh root@<HOST> 'apt install -y /tmp/package.deb'
apt install ./file.deb resolves dependencies automatically. Never run binaries from /tmp in production.
Canonical configs (clang-format, pyproject.toml, find-python-files) live in https://github.com/wirenboard/codestyle. Apply formatters before every commit; CI checks them.
Base/I suffixes, CamelCase methods, .clang-format).go fmt, staticcheck.For naming rules, exact CLI invocations and config paths — see references/codestyle.md.
Every integration on WB must expose state through the /devices/<id>/controls/<id> topic space; the web UI, wb-rules, and other services consume that namespace. All /meta topics are retained; /meta/error doubles as the LWT. Specific typed controls (temperature, voltage) are deprecated — use type: value + units.
MQTT-RPC uses paired topics /rpc/v1/<driver>/<service>/<method>/<client_id>{,/reply} with strict JSON requests ({id, params}) and responses ({id, result, error}).
For the full topic structure, naming rules, meta JSON shapes, control types table, publishing rules, MQTT-RPC details, and the Python reference implementation — see references/mqtt-conventions.md.
Drop a JSON Schema at /etc/wb-mqtt-confed/schemas/<name>.schema.json to get a "Device configurations" page in the web UI for free. wb-mqtt-confed renders the schema as a form, validates on save, writes the config file, and restarts the service. Plain-JSON configs need no converters; custom formats use toJSON/fromJSON.
For the schema skeleton, full configFile parameter table, WB-specific extensions (_format: checkbox, wb-autocomplete, etc.) and install instructions — see references/confed-schema.md.
Wiki: https://wiki.wirenboard.com/wiki/CryptodevATECCx08_Auth
The ATECCx08 chip stores the controller's private key in hardware — the key never leaves the chip.
Use cases:
Workflow:
When developing services that must verify the controller's identity, use the chip-signed certificate as the client cert. Do not try to extract or copy private keys — that is intentionally impossible.
/devices/.../controls/... namespace can't be used by the web UI or wb-rules.apt install docker-ce directly. Use wb-docker-manager.sh from the WB community repo — generic apt install breaks the /mnt/data storage path./mnt/data/<project>/.# pylint: disable= at top of file, # type: ignore on a module) to ship — surface the issue instead.make on the controller. Use wbdev on the developer machine — controller RAM is too limited for serious builds.Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub wirenboard/wb-ai-skills --plugin wb-plc