Skip to content

Repository files navigation

BACnet Hub for Home Assistant

Expose Home Assistant entities as BACnet objects on a local BACnet/IP device and import remote BACnet client points back into Home Assistant.

Built with bacpypes3.

Important

Breaking change in 2.0: the per-point Release button entities (button.bacnet_doi_..._release) were removed and replaced by the bacnet_hub.release service plus a bundled tile feature.

How to migrate:

  • Automations/scripts that pressed a release button now call the bacnet_hub.release service with the point's entity as target (optional priority, default 8).
  • Dashboards: edit the point's Tile card and add BACnet: Release manual override under Features — see Setting it up on a tile.
  • Orphaned button entries in the entity registry disappear after the next reload of the integration.

What This Integration Does

This integration has two roles:

  1. Home Assistant -> BACnet (local BACnet device)
  • Publishes selected HA entities as BACnet objects.
  • Keeps BACnet present values synchronized from HA state changes.
  • Supports BACnet -> HA writeback for supported mappings.
  1. BACnet -> Home Assistant (remote BACnet clients)
  • Discovers remote BACnet devices via Who-Is/I-Am.
  • Imports supported remote points as HA entities.
  • Uses BACnet COV subscriptions for event-driven updates.

Key Features

  • Labels-first auto mapping (no manual mapping UI).
  • Automatic mapping lifecycle: add, refresh, remove, cleanup.
  • Event-driven sync with debounce on registry/label/area changes.
  • Deterministic entity IDs and stable unique IDs.
  • Configurable BACnet write priority (8..16) per discovered client device.
  • bacnet_hub.release service plus a bundled tile feature to relinquish the commanded value.
  • Built-in diagnostics for hub and discovered clients.
  • Integration services: bacnet_hub.reload, bacnet_hub.release.

Requirements

  • Home Assistant with custom integrations enabled.
  • Network access to BACnet/IP segment.
  • Dependency (from manifest.json):
    • bacpypes3==0.0.106

Installation

HACS (custom repository)

  1. HACS -> Integrations -> Custom repositories.
  2. Add this repository as type Integration.
  3. Install BACnet Hub.
  4. Restart Home Assistant.
  5. Settings -> Devices & Services -> Add Integration -> BACnet Hub.

Manual

Copy custom_components/bacnet_hub to:

config/custom_components/bacnet_hub

Then restart Home Assistant.

Configuration

Initial setup

Required fields:

  • instance (BACnet device instance, 0..4194302)
  • address (IPv4[/prefix][:port], example: 192.168.31.36/24:47808)
  • device_name (BACnet device objectName)
  • device_description (BACnet device description)

Defaults:

  • device_name: HA-BACnet-Hub
  • device_description: BACnet Hub - Home Assistant Custom Integration

Options

Beyond the device fields above, the options flow offers:

  • debug_bacpypes (default: off) — escalates the bacpypes3 loggers to DEBUG for wire-level troubleshooting. Leave off in normal operation; the log volume is substantial.

Label import model

The integration runs in labels mode and auto-manages mappings from selected labels.

  • On setup/options, at least one label must be selected.
  • A default label is auto-created if possible:
    • Name: BACnet
    • Icon: mdi:server-network-outline
    • Color: light-green
  • Entities can be discovered by direct entity label, by device label, or by labels assigned to the linked area (entity area or device area).

Home Assistant -> BACnet Mapping

Automatic object type selection (generic entities)

  • Binary-like domains -> binaryValue:
    • binary_sensor, switch, light, lock, cover, input_boolean, alarm_control_panel, device_tracker, button
  • Numeric/unit-based states -> analogValue
  • Fallback -> binaryValue

Climate mapping

For climate.*, multiple BACnet mappings can be created:

  • hvac_mode
    • binaryValue for simple off/heat
    • otherwise multiStateValue with dynamic stateText
  • hvac_action -> binaryValue (read-only mirror)
  • current_temperature -> analogValue
  • set_temperature (reads HA attribute temperature) -> analogValue

BACnet object support (publisher)

  • analogValue
  • binaryValue
  • multiStateValue

Published mappings are mirrored as observer entities and split by platform:

  • sensor / binary_sensor only (non-interactive read-only observers)
  • configuration-like observers use entity_category=config (for example climate setpoints/modes)

Note: This avoids confusing UI behavior where toggles/sliders can be clicked but immediately snap back.

BACnet -> Home Assistant Writeback (for published mappings)

Write requests are accepted only if mapping/service checks pass; otherwise BACnet write is denied (writeAccessDenied).

Supported write targets:

  • light, switch, fan, group -> turn_on / turn_off
  • cover -> open_cover / close_cover
  • number, input_number -> set_value
  • climate:
    • HVAC mode mapping -> set_hvac_mode
    • setpoint mapping -> set_temperature

BACnet Client Discovery and Point Import

The integration discovers remote BACnet devices and imports supported points into HA.

Supported remote BACnet point types

  • analog-input (ai)
  • analog-output (ao)
  • analog-value (av)
  • binary-input (bi)
  • binary-output (bo)
  • binary-value (bv)
  • multi-state-value (mv)
  • characterstring-value (csv)

Imported platform mapping

  • ai -> sensor (read-only)
  • ao -> number if writable, else sensor
  • av -> number (writable)
  • bi -> binary_sensor (read-only)
  • bo -> switch if writable, else binary_sensor
  • bv -> switch (writable)
  • mv -> select (writable)
  • csv -> text (writable)

Writable conditions:

  • ao / bo require priorityArray support.
  • av, bv, mv, csv are writable by design.

Implementation detail:

  • Imported client point entities are created with entity_registry_enabled_default = false (disabled by default until enabled in HA).

Write priority and release (commandable points)

Commandable points (ao, bo, av, bv, mv with a priorityArray) are written at a configurable BACnet priority:

  • Each discovered client device gets a Write priority select entity (options 8..16, default 8, category Configuration, disabled by default).
    • 8 is Manual Operator — writes from HA override a controller's own program until the slot is released.
    • 16 is the lowest priority and matches the behavior of a priority-less write.
    • The chosen priority survives restarts.
  • Releasing a slot is done with the bacnet_hub.release service (see Services) or the bundled tile feature (see Lovelace tile feature).
    • Breaking change (2.0): the former per-point Release button entities (button.bacnet_doi_<client>_<type>_<instance>_release) were removed. Automations or dashboards that pressed them must call the service (or use the tile feature) instead. Orphaned button entries in the entity registry are not deleted actively; they disappear after the next reload of the integration.
    • The release writes BACnet Null at the chosen priority, clearing that slot in the point's priorityArray so the remote controller takes over again with its own value.
    • Without a release, a value written from HA stays latched in the priority array indefinitely.
  • Writable client point entities expose extra state attributes:
    • priority_array: all 16 slots, null for free slots. Excluded from the recorder so the database is not flooded on every state change.
    • relinquish_default: the value that applies when no slot is occupied.

Synchronization Model

  • Initial auto-sync runs during setup.
  • Mapping refresh is triggered by:
    • entity_registry_updated
    • device_registry_updated
    • label_registry_updated
    • area_registry_updated
  • Debounce: 2 seconds.
  • Stale/orphan published entities are automatically cleaned up.

Diagnostics

Hub diagnostics

Provides diagnostic sensors (examples):

  • description
  • firmware revision
  • model name
  • object identifier / object name
  • system status
  • vendor identifier / vendor name
  • IP address / subnet mask / MAC address

Client diagnostics

For discovered clients, diagnostic sensors include similar device and network fields.

Entity IDs and Unique IDs

Published mirror entities use deterministic IDs based on hub instance + BACnet object instance:

  • sensor.bacnet_doi_<hub_instance>_av_<instance>
  • binary_sensor.bacnet_doi_<hub_instance>_bv_<instance>

Client point entities:

  • <platform>.bacnet_doi_<client_instance>_<type_slug>_<object_instance>
  • Write priority: select.bacnet_doi_<client_instance>_write_priority

Published unique IDs are stable and hub-scoped:

  • bacnet_hub:hub:<hub_key>:<object-type>:<instance>

Services

bacnet_hub.reload

Reload one BACnet Hub config entry.

Fields:

  • entry_id (optional)
    • If omitted and exactly one BACnet Hub entry exists, that entry is reloaded.

bacnet_hub.release

Release a priority array slot on one or more commandable client points (targeted by entity).

Fields:

  • priority (optional, 1..16, default 8 = Manual Operator)
    • The slot that is cleared by writing BACnet Null.

Behavior:

  • Only points that support priorityArray are accepted; other targets raise a validation error.
  • After the write the point is re-read immediately, so the HA state updates without waiting for the next COV notification.
  • With multiple targets, errors are collected per entity and reported bundled at the end instead of aborting on the first failure.

Example:

service: bacnet_hub.release
target:
  entity_id: number.bacnet_doi_1234_ao_1
data:
  priority: 8

Lovelace tile feature

The integration ships a tile feature (custom:bacnet-release-feature) and serves it automatically — no manual dashboard resource setup is needed. It replaces the removed release button entities and offers itself on every entity that exposes a priority_array attribute, i.e. the writable client points (number, switch, select) of commandable objects.

Setting it up on a tile

  1. Open the dashboard editor and edit (or add) a Tile card for the point, e.g. switch.bacnet_doi_1234_bo_1.
  2. Under Features click Add feature and pick BACnet: Release manual override (on a German frontend: BACnet: Handbedienung aufheben). The entry only shows up for entities that carry priority_array; for sensors or published mirrors it is not offered.
  3. Optionally set the priority (1–16) in the card's YAML. It defaults to 8 and must match the slot your writes land in — with the default Write priority of 8 nothing needs to be changed. The feature has no visual editor beyond that single option.
type: tile
entity: switch.bacnet_doi_1234_bo_1
features:
  - type: toggle
  - type: custom:bacnet-release-feature
    priority: 8

Behavior

  • Full-width Release button (German frontend: Aufheben); only enabled while the configured slot is occupied, greyed out otherwise.
  • Warning-colored while active — a manual override is a state the operator is supposed to notice.
  • Releases immediately on click (no confirmation dialog) by calling bacnet_hub.release for the tile's entity.
  • The module registers itself once HA's frontend is ready and repairs any tile that rendered before that; a one-line version stamp appears in the browser console on load, and window.__bacnetReleaseFeature.heal() can be run from the console for support.

Limitations

  • BACnet/IP focus (IPv4/prefix:port bind format).
  • Single config entry (single_config_entry: true).
  • Labels-first auto model; legacy/manual mappings are removed during sync.
  • Published multiStateValue currently has no dedicated HA mirror platform entity.
  • BACnet sends no COV for priorityArray/relinquishDefault; besides updating on writes/releases from HA and after COV presentValue changes, commandable points poll these properties every 30 seconds, so external changes appear with up to that much delay.

Troubleshooting

  • No entities imported:
    • Verify selected labels in options.
    • Verify labels are attached to entity, its device, or the linked area.
  • Address bind errors (address already in use):
    • Ensure only one BACnet process binds the same IP/port.
  • Direct BACnet writes rejected:
    • Check write target is supported and corresponding HA service exists.
  • Client points not updating:
    • Confirm remote device supports COV/read for the point.
    • Trigger reload via bacnet_hub.reload.

Development

Unit tests live in tests/ and run against the pinned dependencies:

pip install -r requirements_test.txt
pytest

The CI workflow (.github/workflows/validate.yml) runs manifest/translation validation, a Python syntax check, and the test suite on every PR.

License

MIT. See LICENSE.

Copyright (c) 2025-2026 Alessio Magliarella

About

Publishes Home Assistant entities as BACnet objects and supports bidirectional writes (ReadProperty/WriteProperty). Built with **bacpypes3**.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages