Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

bmcond — userspace radio transport for HomeMatic

bmcond (busmatic-concentrator) is a small userspace daemon that bridges a HomeMatic / HomeMatic-IP radio module to multimacd over a plain PTY. It replaces the piVCCU kernel-driver chain (hb_rf_usb_2.ko, hb_rf_eth.ko, generic_raw_uart.ko) with a process running entirely in userspace.

 ┌──────────┐ ┌───────┐ ┌─────────────────┐
│ multimacd│───>│ PTY │<───│ bmcond │───> EFM32 / CC1101
│ (eq-3) │ │ /dev/ │ │ libusb / UDP / │ (HmIP-RFUSB,
└──────────┘ │ raw- │ │ TCP / UART │ HB-RF-USB(2),
│ uart │ └─────────────────┘ HB-RF-ETH,
└───────┘ RPI-RF-MOD,
CULFW32,
HM-MOD-RPI-PCB)

Pure C, single binary, links against glibc, libusb-1.0 and libcjson. No kernel-module dependency. No frame parsing — bmcond is byte- transparent between the transport and the PTY. The Mac-Layer (LLMAC, DUTY-cycle, CSMA-CA, AES, retransmit) is owned by multimacd.

Why a separate transport process

The piVCCU/debmatic stack ships hb_rf_usb_2 and hb_rf_eth as DKMS kernel modules. They expose /dev/raw-uart to userspace and own the USB / Ethernet connection to the radio. That works, but:

  • DKMS rebuilds against every host-kernel update; a missed rebuild takes the radio offline.
  • Only one connection per ETH-attached radio is possible — the kernel driver holds it exclusively, which makes diagnostics (sniffing, firmware updates) awkward.
  • Inside containers the kernel driver still needs the right .ko files on the host plus CAP_SYS_MODULE to load them.

bmcond does all of this in userspace via libusb-direct, UDP or TCP. The result is the same /dev/raw-uart char device-shaped interface that multimacd already knows how to open — only it's a PTY symlink served by an unprivileged process.

Supported radio modules

ModuleTransportbmcond flag
eQ-3 HmIP-RFUSB (1b1f:c020)libusb-direct-U 1b1f:c020
eQ-3 HmIP-RFUSBCDC-UART via cp210x-t /dev/ttyUSB0
HB-RF-USB v1 (FT232RL) + RPI-RF-MODlibusb-direct, CBUS3-reset-U <vid:pid>
HB-RF-USB-2 (CP2102N) + RPI-RF-MODlibusb-direct, GPIO.0-reset-U <vid:pid>
HM-MOD-RPI-PCBRaspberry Pi UART-t /dev/ttyAMA0
CULFW32 / HMUARTLGW-DualTCP-N host:port
HB-RF-ETH (Alexander Reinert)UDP (port 3008)-E host
RFNetHM (HB-RF-ETH-compatible clone)UDP (port 3008)-E host

USB-side per-chip quirks (CP2102N vs FTDI; reset-pin number; polarity; pulse duration) live in transport_usb.c::usb_radio_quirks[].

Build

apt install build-essential libc6-dev libusb-1.0-0-dev libcjson-dev
make concentrator # → bin/busmatic-concentrator
make tools # → bin/copro_diag, bin/hmip_probe, bin/eth_soak

Run

The canonical use-case — local HmIP-RFUSB stick at the USB port — needs no transport flag at all; libusb-direct on 1b1f:c020 is the default:

busmatic-concentrator --raw-uart=/dev/raw-uart -H 001122 -S BMC0000001 -F 4.4.18 -C -v

For other adapters, pass the appropriate flag explicitly:

# HM-MOD-RPI-PCB on Pi's onboard UART
busmatic-concentrator -t /dev/ttyAMA0 --raw-uart=/dev/raw-uart
# RFNetHM box on the LAN
busmatic-concentrator -E 192.168.1.50 --raw-uart=/dev/raw-uart
# CULFW32 advertised via mDNS
busmatic-concentrator -N culfw32.local:2327 --raw-uart=/dev/raw-uart

-h shows the full option list. --raw-uart=PATH is mandatory: it tells bmcond where to symlink the PTY slave so multimacd can open it as its Coprocessor Device Path.

-C is optional; if set, bmcond writes /etc/config/rfd.conf (so rfd finds the modulator) and /var/run/bmcd-config.json (a status snapshot for the JSON API). Both are non-destructive — existing files are backed up to *.bmcd-pre first.

JSON status API

bmcond listens on :9126 and serves a small read-only/read-write HTTP+JSON admin surface — useful for headlessCCU's WebUI sidebar, ops scripts, or curl-based smoke tests:

EndpointWhat
GET /api/healthliveness probe
GET /api/statusversion, uptime, config-snapshot
GET /api/effectivemerged runtime view (sources + slots + claim/verified caps)
GET /api/discoverUSB enumerate + mDNS scan for advertised radios
GET /api/sourcesbmcond.sources.json content
PUT /api/sourcesreplace whole sources doc
GET /api/slotscurrent slots.{bidcos,hmip} assignment
POST /api/reloadrequest a clean restart (writes marker, exits)
GET /api/firmware/inventoryscan /firmware/<HW>/*.eq3
POST /api/firmware/flashflash an .eq3 to the radio (sync)
GET /api/log/tailrecent log lines

See docs/sources_schema.md for the persisted-source format.

Tools

Standalone CLIs in bin/ after make tools:

  • copro_diag — radio inventory, FW probe, .eq3 flash. Speaks all the transports bmcond does (copro_diag eth=host:3008 --flash file.eq3).
  • hmip_probe — HmIP-capability differential probe (which dst-layer
    • cmd-id pairs a given firmware accepts).
  • eth_soak — liveness soak for transport_eth / transport_rfnethm.

Where this is used

  • tostmann/headlessCCU — bundles bmcond together with multimacd, rfd, HMIPServer.jar and a small JSON-RPC stub into a single Home-Assistant Add-On (or plain Docker container).
  • Standalone, paired with debmatic on a Raspberry Pi: drop the piVCCU DKMS modules, point multimacd.conf's Coprocessor Device Path at bmcond's PTY symlink, done.

Layout

concentrator.c main(); arg-parsing; PTY+transport wiring
api.[ch] JSON status API on :9126
sources.[ch] bmcond.sources.json persistence (cJSON)
confgen.[ch] -C: writes rfd.conf + /var/run/bmcd-config.json
backend.[ch] Backend abstraction
hardware.[ch] hw_identify(): /sys/bus/usb-serial probing
radio.[ch] Radio module interface
radio_dualcopro.[ch] Boot-to-App handshake (hw identification)
radio_id.h Identity-snapshot type (HMID/serial/firmware/sgtin)
copro_query.[ch] Co-CPU update protocol (SGTIN/FW probe, .eq3 flash)
eq3_image.[ch] .eq3 firmware-image parser (per-chunk LEN+CRC)
frame.[ch] DualCoPro wrapper codec (used by copro_query / eq3_image)
transport.h Transport vtable
transport_uart.c Local UART
transport_tcp.c TCP connect (CULFW32 mDNS-discovery)
transport_usb.c libusb-direct, per-VID:PID quirks
transport_eth.c HB-RF-ETH UDP transport
transport_rfnethm.c RFNetHM (HB-RF-ETH-compatible clone) UDP transport
tools/copro_diag.c radio inventory + .eq3 flash CLI
tools/hmip_probe.c HmIP capability-differential probe
tools/eth_soak.c transport_eth liveness soak
docs/ sources_schema.md + sources.example.json

License

GPL-2.0-or-later — see LICENSE.

Author

Dirk Tostmann (@tostmann).

About

Userspace transport daemon bridging HomeMatic/HmIP radio modules to multimacd via PTY — replaces piVCCU's hb_rf_usb_2 / hb_rf_eth kernel modules.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages