Skip to main content

hoermoles-ble

Getting started: commissioning a drive

Everyday use is via the hoermoles-ble CLI (published separately as package hoermoles-ble-cli, built on top of this library):

  1. Install the CLI as a standalone tool - this gives you the hoermoles-ble command on your $PATH, no workspace checkout needed:

    uv tool install hoermoles-ble-cli
    

    (Contributing to/developing this repo instead? Use cd python && uv sync and prefix every command below with uv run instead.)

  2. Get the QR code sticker's content onto disk - there's no camera-scanning app yet, so either read it with a separate scanner app, or take a photo of the sticker and decode it with a command-line QR decoder, e.g. zbarimg (zbarimg --raw photo.jpg). Then save the decoded content once:

    hoermoles-ble save-qr "<QR code content>"
    
  3. Scan for the drive over BLE - matches the saved QR code by serial number and saves the drive's product type to the device registry (see below):

    hoermoles-ble scan
    

    Seeing only the short packet ("incompletely parsed", no Admin taught: ... line) is normal and not a sign of anything - both our own drive (already paired) and the official app's own code treat this as a plain BLE scan-timing artifact, not something tied to admin/pairing status (the decompiled app has explicit, unconditional logic to recover once the longer packet eventually arrives - see the local reveng report). Just use a longer --timeout or retry scan.

  4. Register (one-time pairing). Only works while the drive still accepts a new admin (AdminsCanBeTeached=True in the scan output above) - reset via the drive's menu 19/parameter 02 first if not (this invalidates the existing pairing, e.g. with your phone):

    hoermoles-ble register --address <MAC>
    

    This derives and saves the root key under ~/.hoermoles/credentials/<MAC>.json - no QR code, app, or cloud needed again afterwards.

  5. Trigger the gate:

    hoermoles-ble exec --address <MAC> impulse
    

From here on --address can usually be omitted (it defaults to the only/ first saved credentials). See packages/hoermoles-ble-cli/README.md for the full command reference (menu-get/menu-set for operator settings, view-log for the audit log/diagnostics counters, list-devices, ...) and the workspace-level python/README.md for a longer walkthrough.

Library internals

Protocol core (protocol.py, crypto_rsa.py) and BLE client (client.py, transport.py, ble_transport.py) for the Hoermann BlueSecur "Signed" channel.

protocol.py deliberately has no third-party dependencies (stdlib only) and serves as a template for ports to other languages. bleak (for the real BLE transport) is an optional extra: pip install hoermoles-ble[bleak].

Reverse-engineered from the official Hoermann BlueSecur app; see the module docstrings in protocol.py, client.py, and advertisement.py for details on where each part of the protocol comes from.

Unit-tested in tests/ (uv run pytest from the workspace root python/) - the pure protocol/crypto/config logic directly, client.py against an in-memory fake transport. See the workspace README for details; this package's live-hardware verification notes above are the complement to that, not a replacement.

Operator menu/parameter settings

Besides the channel commands (open/close/light/...), the drive also exposes its classic numbered configuration menus (menu 20 "reversal limit", menu 25 "operator light", menu 52 "speed door open", ...) over BLE - the same menus normally set via the hand-transmitter/display sequence, exposed by the official app as "operator settings". HoermannClient.read_properties() and .write_properties() (in client.py) read/write these; menu_settings.py provides the menu-number-to-wire-byte table and valid values per menu for every product the official app knows about (Supramatic Serie 4/E4, Rollmatic 2, SilentDrive 2, Supramatic 4 H4, HET), sourced from the app's own embedded menu-concept resources, one DriveMenuTable per (product_class, product_id) in DRIVE_MENU_TABLES. See the module docstring for the exact firmware/software scope per product (menu_group wire bytes are NOT interchangeable across products or even across ProductIDs that share the same advertised name) and the CLI's menu-get/menu-set commands for a ready-to-use example.

The read direction (read_properties()/GET_PROPERTIES/GET_SELECTED_PROPERTIES) is live-verified against a real Supramatic E4 - both a full, unfiltered read and filtered multi-menu reads returned plausible values. One live-confirmed protocol quirk: a GET_SELECTED_PROPERTIES request that mixes a menu group < 100 with one >= 100 makes the drive drop the connection instead of answering - read_properties() avoids this via protocol.batch_menu_groups_for_selected_properties(). The write direction (write_properties()/SET_PROPERTIES) is only structurally derived from the decompiled app and NOT yet confirmed live for any product - read a value back before writing it, and double-check menu numbers/values against the printed operator manual.

Device registry (which product a paired drive is)

devices.py keeps a separate <config_dir>/devices.json registry mapping each MAC address to its product_class/product_id/product_name (and serial number, if known) via save_device_info()/get_device_info()/ list_device_infos() - deliberately not part of credentials.py/ Credentials, since it's non-secret metadata and, unlike a per-device credentials file, one file can list every drive ever seen. scan_devices() itself is read-only (no root key needed, nothing persisted) - the CLI's scan command is what saves a DeviceInfo for each device it finds with a decodable product_class/product_id; register also saves one directly from the QR code prefix. menu-get/menu-set use the registry to pick the right DriveMenuTable automatically.

Audit log and diagnostics counters

HoermannClient.read_log()/.read_service_data() (in client.py) read the same two things the app's "log"/diagnostics view shows: a security/access audit log (who registered, which channel got toggled, blocked login attempts, clock changes, ...) and service counters (operating hours, door cycles, maintenance counters, ...) - see device_log.py for the LogTag/ServiceType name tables and per-tag field decoding (parse_log_fields()). Both are live-verified against a real Supramatic E4 - that check is also what caught a transcription error in SERVICE_TYPE_NAMES (wire byte 17 is ELEMENTS_COUNTER, not ENGINE_RUNTIME - the wire-byte-to-meaning mapping in the decompiled app is an explicit switch statement, not the ServiceType enum's own declared integer values). A handful of ServiceType entries carry a proprietary Hoermann fixed-32-day- month timestamp encoding instead of a plain counter - NOT decoded here (see SERVICE_TYPE_IS_TIMESTAMP), only the plain-integer counters (including operating hours) are. See the CLI's view-log command for a ready-to-use example.

Download files

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

Source Distribution

hoermoles_ble-0.9.0.tar.gz (60.6 kB view details)

Uploaded Source

Built Distribution

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

hoermoles_ble-0.9.0-py3-none-any.whl (54.0 kB view details)

Uploaded Python 3

File details

Details for the file hoermoles_ble-0.9.0.tar.gz.

File metadata

  • Download URL: hoermoles_ble-0.9.0.tar.gz
  • Upload date:
  • Size: 60.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for hoermoles_ble-0.9.0.tar.gz
Algorithm Hash digest
SHA256 24180eea30c57104b50086550b31db6577d303bfbb8a3441dd47a51d07aca602
MD5 3955d0c906dea6ee9cbcc6b522cc9273
BLAKE2b-256 7f4f8b4ee33ef3d542513535b343b7784b8819e9b186dc9e2437f6c377778088

See more details on using hashes here.

Provenance

The following attestation bundles were made for hoermoles_ble-0.9.0.tar.gz:

Publisher: pypi-publish.yml on the78mole/hoermoles-ble

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hoermoles_ble-0.9.0-py3-none-any.whl.

File metadata

  • Download URL: hoermoles_ble-0.9.0-py3-none-any.whl
  • Upload date:
  • Size: 54.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for hoermoles_ble-0.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bd11d140cbb767026a6fb1f263db29ceb3b5a3ddb7f14b2e8156fad94488ca1e
MD5 26047e32bbd42e46f0eef714f3c6a532
BLAKE2b-256 5523e01dc2fba879b7ee680c8c3e095ba39a63d825b1d390fc7dc5491384cf51

See more details on using hashes here.

Provenance

The following attestation bundles were made for hoermoles_ble-0.9.0-py3-none-any.whl:

Publisher: pypi-publish.yml on the78mole/hoermoles-ble

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.12.1

2 files

0.12.0

2 files

0.11.0

2 files

0.10.0

2 files

This release

0.9.0 This release

2 files

0.6.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.2

2 files

0.3.1

2 files

0.2.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