Skip to content

fdebrus/Nikobus-HA

Repository files navigation

Nikobus Integration for Home Assistant

Buy Me a Coffee Nikobus for Home Assistant HACS Custom Maintainer Latest release Open issues GitHub stars

Control your Nikobus installation from Home Assistant — switches, dimmers, and shutters as native entities, plus button presses as automation triggers. Modules and buttons are discovered automatically from the bus, and your real names, rooms, and scenes can be imported from your .nkb project file. There are no address lists to maintain by hand.

Highlights

  • 🔌 Automatic discovery — modules and physical buttons are enumerated straight from the PC-Link; no manual address tables.
  • 💡 Native entities — switches, dimmers (with brightness), and shutters (with simulated position) per channel.
  • 🎛️ Buttons as triggers — every keypad key, IR code, and input becomes an event source (and a press-simulation button) for automations.
  • 📥 Import from .nkb — upload your Nikobus project export and pull in device names, per-channel names, Areas (from rooms), and scenes — pick exactly what to apply.
  • 🎬 Scenes that fire atomically — Central Function scenes are activated on the bus the same way a physical scene key would, with no per-channel fan-out.
  • Real-time or polled — instant pushed state with a Feedback Module, or a configurable poll without one.

Contents


Quick start

  1. Install via HACS (custom repository) and restart Home Assistant.
  2. Add the integration: Settings → Devices & Services → Add Integration → Nikobus. Enter your PC-Link connection — a serial path (/dev/ttyUSB0) or TCP bridge (192.168.2.50:9999).
  3. Open the Nikobus Bridge device and press 1. Load Project Overview — this enumerates the bus via the PC-Link.
  4. Press 2. Load Existing Installation — this maps which button drives which output, and extracts scenes.
  5. (Optional) Upload your .nkb and press 3. Import Names from .nkb to pull in your real names, rooms, and scenes.
  6. Done. Your modules appear as lights / switches / covers; buttons appear as devices you can trigger automations from.

A large install takes a few minutes to scan. Progress is shown on the Bridge device's Discovery status / Discovery progress sensors.


Prerequisites

  • A PC-Link (05-200) on the bus. Home Assistant connects through the PC-Link — it is the required interface and the source of the device inventory. (See Troubleshooting if your install also has a PC-Logic.)
  • One client at a time. Only one program may talk to the bus. Stop the Nikobus PC software (and any other bridge) before starting Home Assistant.
  • A connection path: a USB/serial adapter (/dev/ttyUSB0) or a TCP-to-serial bridge (host:port).
  • (Optional) a Feedback Module (05-207) wired to the PC-Link. If present, enable the toggle during setup and module states are pushed in real time; without one, HA polls on a configurable interval.
  • (Optional) your .nkb project file — the export from the Nikobus PC software. Not required to run, but it's the only place your friendly names, rooms, and scene groupings live. See Importing from your .nkb project.

Supported hardware

Output modules

Module Ref In Home Assistant
Switch Module 05-000-02 switch (or light) per channel
Compact Switch Module 05-002-02 switch / light
Dimmer Module 05-007-02 light with brightness
Compact Dim Controller 05-008-02 light
Roller Shutter Module 05-001-02 cover with simulated position

Interface / system modules

Module Ref Notes
PC-Link 05-200 Required bus interface; all traffic goes through it
PC-Logic 05-201 Logic controller; its 6 inputs surface as LM-INPUT 1–6
Modular Interface, 6 inputs 05-206 Its 6 inputs surface as MI-INPUT 1–6
Feedback Module 05-207 Optional; pushes real-time state when wired to the PC-Link
Audio Distribution Module 05-205 Registered for visibility; I/O mapping not yet decoded

Buttons & transmitters

One HA device is created per physical button, with one button-entity + binary-sensor per key (see the entity model).

  • Bus push buttons — 2-, 4-, and 8-control-point variants across the supported series (4*-072 / 4*-074 / 4*-078, the 05-06x graphite/feedback-LED variants, and the 4*-082 / 4*-084 / 4*-088 series).
  • Push-button & switch interfaces (05-056, 05-057, 05-058).
  • IR receivers — each learned IR code becomes its own op-point.
  • Motion detectors with Nikobus interface (05-7*5).
  • RF transmitters05-302 / 05-304 / 05-311 / 05-314, and the 05-312 Easywave 52-key hand-held (all 52 sub-codes as op-points).
  • Virtual / clustered remotes — multi-page handhelds that emit many bus codes but aren't in PC-Link inventory are clustered into a single Remote Transmitter (<suffix>) device at the end of a link scan.

Installation & setup

  1. Install through HACS using the button below (or clone into config/custom_components/nikobus):

    Add to HACS

  2. Restart Home Assistant.

  3. Settings → Devices & Services → Add Integration → Nikobus.

  4. Enter the serial path or IP:port. The connection is tested immediately.

  5. On Hardware Configuration, enable a toggle if it applies:

    • Feedback Module (05-207) installed — real-time pushed state, no polling.
    • PC-Link older than Gen 3 — compatibility tweaks for 1st/2nd-gen PC-Link hardware.
  6. If neither toggle is set, choose a polling interval (60–3600 s, default 120).

  7. Finish, then run discovery.

Module and button data live in Home Assistant's own storage (.storage/nikobus.modules, .storage/nikobus.buttons, .storage/nikobus.cfs). You don't hand-edit these — they're populated by discovery.


Discovery workflow

Everything is driven from the Nikobus Bridge device page. The three buttons are meant to be pressed in order, top to bottom.

1. Load Project Overview

Press 1. Load Project Overview. The integration probes the PC-Link, walks its inventory, and creates a device for every module and every physical button on the bus.

Two diagnostic sensors track progress:

  • Discovery status — its state is the coarse phase (idle / pc_link / module_scan / finished / error), so history stays clean; the live per-register line is in the message attribute, alongside the fine-grained detail (all kept out of the recorder).
  • Discovery progress — 0–100 %.

2. Load Existing Installation

Press 2. Load Existing Installation. This reads each output module's link table and records which button drives which channel (the linked_modules metadata). It also extracts Central Function (CF) scenes found in those tables. The button is disabled until an inventory has run.

3. Import Names from .nkb (optional)

Press 3. Import Names from .nkb to apply the friendly names, rooms, and scenes from your project file in one shot. This is the quick, non-destructive path — see Importing from your .nkb project for the file upload step and for the choose-what-to-import form with an overwrite option.

Customize a module (optional)

Configure → Customize a module lets you, per channel:

  • Description → the entity name.
  • Entity type → how HA exposes it (switch modules: switch/light/none; dimmers: light/none; rollers: cover/switch/light/none).
  • LED on / off addresses → feedback-LED bus addresses (blank if unused).
  • Travel time up / down (rollers) → seconds to open/close, used by the position calculator.

Changes persist in .storage/nikobus.modules and survive re-discovery.

Installs without a PC-Link

If no PC-Link answers the discovery probe, the integration falls back to importing inventory from optional nikobus_module_config.json / nikobus_button_config.json files in /config (Feedback-module-only installs). These files are only consulted by the Load Project Overview action as a fallback — they are never imported automatically at startup, and never overwrite a PC-Link-discovered inventory.

Since 3.0.0 these files are an inventory source only. The previous behaviour that imported their descriptions as friendly names on every startup has been removed — entity names live in Home Assistant (see Renaming). If you only kept the files for their names and you have a PC-Link, you can delete them; the integration logs a warning when it finds them.


Importing from your .nkb project

The bus tells the integration what is installed and how it's wired — but not what you called things. Your friendly names ("Appliques Salon"), your rooms, and your named scene groupings live only in the Nikobus PC software's project file. The .nkb import reads them and applies them to Home Assistant.

A .nkb is the project export from the Nikobus PC software (a ZIP holding the project database). Nothing leaves your machine — it's parsed locally inside Home Assistant.

Step 1 — Upload the file

Settings → Devices & Services → Nikobus → Configure → Upload .nkb project file. Pick your export (any filename); it's validated (it must parse as a real .nkb) and saved as nikobus.nkb in your config folder. No copying over Samba/SSH.

Prefer to place it yourself? Drop the file in /config as nikobus.nkb (or as the only *.nkb there) and skip this step.

Step 2 — Import

You have two ways to apply it:

Quick path — the button. Press 3. Import Names from .nkb on the Bridge device. It imports everything, non-destructively: it fills in names/Areas where you haven't set your own, and never clobbers a manual rename.

Choose what to import. Configure → Import from .nkb (choose what) opens a form where you tick exactly which categories to apply, with an optional overwrite toggle:

Category What it sets
Device names Modules, buttons, IR receivers → Name (Room) (the room disambiguates the often-repeated Nikobus names).
Channel names The per-output entities you actually toggle — each light / cover / switch (e.g. Appliques Salon, Terrasse).
Areas Each device is placed into a Home Assistant Area matching its Nikobus room (created if needed).
Scenes Named scene groups — both light scenes and shutter / master scenes (see Scenes).
Overwrite (toggle) Off (default): suggested only — a name or Area you set by hand always wins. On: force the .nkb values over your existing names/Areas.

So you can, for example, refresh just the channel names without disturbing the Areas you've already organised, or re-run with overwrite after a project change to push the latest names through.

Re-running is safe and idempotent — unchanged entries are skipped, and (without overwrite) anything you've personalised is left alone.


Buttons, inputs & the entity model

The model: device → op-points → (button + sensor)

Every physical button is one device. Each operation point on it — a key on a keypad, an IR code on a receiver, an A/B state on an input — gets two entities:

Entity Direction Use
Button HA → bus Press it to emit the same bus frame a physical press would (simulate the press).
Binary sensor (disabled by default) bus → HA Pulses to pressed (then back to idle after ~1 s) when the real button is pressed; use it in state-based automations.

Binary sensors are disabled by default — enable them on the device page if you want to monitor presses.

PC-Logic & Modular Interface inputs

The PC-Logic (05-201) and Modular Interface (05-206) each expose 6 inputs. Each input is rendered as its own child device under the owning module:

  • PC-Logic inputs → LM-INPUT 1LM-INPUT 6 (LM = Logic Module).
  • Modular Interface inputs → MI-INPUT 1MI-INPUT 6 (MI = Modular Interface).

Each input has two keys — A and B — because the firmware emits one telegram when the contact closes (A) and another when it releases (B). Each key has the usual button + binary-sensor pair:

  • Use the A / B buttons to simulate the input going on/off from HA.
  • Use the A / B sensors to monitor the input's real state on the bus.
  • Use the A/B latch switch (added in 3.0.0) for a persistent on/off mirror: the A signal latches it on, B latches it off, and turn_on / turn_off drive the matching bus frame. It tracks physical presses and other controllers, and survives restarts.

The latch switch assumes the input emits both its A and B telegrams (one per direction) — the normal case. An input wired to emit only one of the two can be turned on/off from HA but its mirrored state won't follow physical presses in both directions.

Input addresses are computed by firmware from the module's own address (not stored in inventory) and synthesised automatically — no configuration needed.

trigger:
  - platform: state
    entity_id: binary_sensor.lm_input_1_key_a
    to: "pressed"   # these sensors report "pressed" / "idle"

What each button exposes

After a link scan, button entities carry their wiring as attributes:

linked_outputs:
  - module_address: "0E6C"
    channel: 1
    mode: "M01 (Dim on/off (2 buttons))"
wall_button_address: "0D1C80"
wall_button_model: "05-348"
wall_button_type: "IR Button with 4 Operation Points"
wall_button_key: "1C"

Conversely, every light / switch / cover exposes a controlled_by attribute listing the buttons that drive it — so you can answer "which wall button turns on this light?" from the entity page.

Renaming

Discovered devices get generic names like Bus push button, 4 control buttons (1843B4). You have two ways to give them friendly names:

  • In bulk, from your projectimport them from the .nkb. This is the fastest way to name a whole install at once, rooms and all.
  • By hand — rename in the HA UI (device → ⋮ → Rename). HA stores this as name_by_user and preserves it across reloads, restarts, and re-discovery (names are keyed by the entity's stable unique_id).

The two coexist: a non-overwrite .nkb import only suggests names, so anything you've renamed by hand is left untouched.

IR codes across multiple receivers

When the same IR code is learned by several receivers, each gets its own op-point with a distinct bus address, and the name is qualified with the receiver (IR 30A on 0D1C80) so duplicates stay distinguishable.

Virtual / off-bus buttons

Addresses not present on the physical bus (IR scene triggers, hand-added codes) aren't created as entities. Fire them from scripts:

service: nikobus.send_button_press
data:
  address: "84DFFC"

Events & automations

The integration fires structured HA bus events for the full press lifecycle:

  • Base: nikobus_button_pressed, nikobus_button_released.
  • Classified: nikobus_short_button_pressed (< 1 s), nikobus_long_button_pressed (≥ 1 s). The threshold is SHORT_PRESS in const.py.
  • Release buckets: nikobus_button_pressed_0 (< 1 s) … _3 (≥ 3 s).
  • Hold milestones (while still held): nikobus_button_timer_1 / _2 / _3 at 1/2/3 s. These count wire frames (40 ms cadence), not wall-clock, so a bridge that buffers and bursts frames still classifies correctly.
  • Post-refresh: nikobus_button_operation after impacted modules are refreshed.

All events share one payload schema:

address: "004E2C"        # button address (uppercase hex, no 0x)
module_address: "9105"   # impacted module, or null
channel: 1
ts: "2024-05-01T12:00:00Z"
press_id: "004E2C-..."
state: "pressed" | "released" | "timer"
duration_s: 1.2          # null on initial press
bucket: 1                # 0/1/2/3, else null
threshold_s: 2           # timer milestone, else null
source: "nikobus"

Always quote button addresses in YAML. A value like 25E952 parses as scientific notation and becomes null. Use a leading space inside the quotes (address: " 25E952"). Addresses with any letter other than E are unaffected.

Examples

Toggle a light on a press

trigger:
  - platform: event
    event_type: nikobus_button_pressed
    event_data:
      address: "004E2C"
action:
  - service: homeassistant.toggle
    target:
      entity_id: light.example_light

Hold-to-dim (fires after 2 s held)

trigger:
  - platform: event
    event_type: nikobus_button_timer_2
    event_data:
      address: "004E2C"
action:
  - service: light.turn_on
    target:
      entity_id: light.living_room_dimmer
    data:
      brightness_pct: 30
      transition: 1

Drive a scene from a physical button (after sunset)

trigger:
  - platform: event
    event_type: nikobus_button_pressed
    event_data:
      address: " 25E952"   # leading space avoids YAML scientific-notation
condition:
  - condition: sun
    after: sunset
action:
  - service: scene.turn_on
    target:
      entity_id: scene.scene_close_all_shutters

Move a cover to an exact position (the virtual travel calculator stops it at the target):

trigger:
  - platform: event
    event_type: nikobus_button_pressed
    event_data:
      address: "C9A5"
action:
  - service: cover.set_cover_position
    target:
      entity_id: cover.living_room_blind
    data:
      position: 60

Scenes

Scene entities come from up to three sources. Most installs are covered by the first two, which need no configuration.

CF broadcasts (auto-extracted from the bus)

A Nikobus Central Function (CF) is a multi-output activation that already lives on the bus — every "scene" key on a keypad is a CF. 2. Load Existing Installation reads them from the module link tables, classifies them (switch_pair / roller_pair), and persists them to .storage/nikobus.cfs. They appear as scene entities automatically, e.g.:

  • Nikobus switch CF 384102 (22 ch)
  • Nikobus roller CF 3880CB (6 ch)

Metadata is exposed as attributes:

bus_address: "3880CB"
pattern: "roller_pair"
member_count: 6
outputs:
  - { module_address: "8B9C", channel: 5, mode: "M02 (Open)" }

Activating a CF from HA is indistinguishable from a physical press — the integration emits the same #N<address>\r#E1 frame, so modules fire atomically on the bus (no per-channel fan-out, no partial-activation risk). Roller travel uses each module's stored M01/M02/M03 timings. No configuration needed; CFs are re-extracted on every scan.

CF scenes get generic names (Nikobus switch CF …). Import from your .nkb to give them their real names — and to surface scenes the bus alone can't (next).

.nkb-sourced scenes (named light + shutter/master scenes)

Light scenes self-identify on the bus (their preset-recall modes), so the step above already surfaces them. Shutter / "all-off" / master scenes have no such fingerprint — on the bus they're indistinguishable from an ordinary multi-output button — so discovery can't tell they're scenes. Your .nkb does mark them (the Central-Function grouping).

Selecting Scenes during a .nkb import uses that information to:

  • name matched light-scene CFs with their real project names, and
  • create the shutter / master scenes that discovery couldn't, as real scene entities (keyed on the address that fires them, sourced from the .nkb and preserved across future re-discovery).

User-authored scenes (nikobus_scene_config.json)

For HA-side per-channel groupings that don't exist as a CF on the bus. Create, edit and delete them from the UI: Settings → Devices & Services → Nikobus → Configure → Manage scenes — pick the module, channel and state per member; the integration writes the file and reloads the scene entities for you.

The file lives in /config and is loaded at startup; a missing/empty file is fine, and you can still edit it by hand if you prefer. Dimmers use 0–255, switches "on"/"off", shutters "open"/"close"/"stop".

{
  "scene": [
    {
      "id": "scene_close_all_shutters",
      "description": "Close all shutters",
      "channels": [
        {"module_id": "9105", "channel": "1", "state": "close"},
        {"module_id": "9105", "channel": "2", "state": "close"}
      ]
    }
  ]
}

Activation sends one command per channel (HA-driven fan-out), touching only the channels you list.

Which one? A scene that already exists in Nikobus → it's a CF, no config needed (import the .nkb for its name). A new cross-module grouping that doesn't exist in Nikobus → write it in the JSON file.

Upgrading to 3.0.0: light-scene CFs are now keyed on the address the bus actually emits (the wire form), which both fixes activation and splits a multi-key trigger into one scene per key. As a result a light-scene's unique_id (and entity id) changes on the first discovery after upgrade — the old scene.nikobus_cf_… entity is replaced by one or more new ones. Re-point any automation or dashboard that referenced the old entity. CF switch/roller scenes are unaffected.


Connectivity

Only one client may connect to the bus at a time.

  • Direct serial/USB: /dev/ttyUSB0
  • Network bridge: 192.168.2.50:9999

On a dropped connection the integration reconnects with exponential back-off (5 s → 10 s → 20 s → … capped at 60 s). Entities go unavailable until the link is restored, then resume without an HA restart.

The Connection sensor on the Bridge device exposes the live status (connected / reconnecting / disconnected) and carries diagnostic attributes you can use in automations: last_connected (timestamp of the last successful connect), reconnect_attempts (consecutive retries since), and connection_string. For example, alert when the bus has been down for a while:

trigger:
  - platform: state
    entity_id: sensor.nikobus_bridge_connection
    to: "disconnected"
    for: "00:05:00"

TCP bridge example 1 TCP bridge example 2


Services

The integration registers four services in the nikobus. domain. All appear in Developer Tools → Actions with a form (from services.yaml) and can be called from scripts and automations.

nikobus.query_module_inventory

Triggers a discovery scan. It has three modes depending on which fields you pass:

  • Full inventory — no fields: re-enumerate every module and button from the PC-Link.
  • Single modulemodule_address only: re-scan one module's link table.
  • Forensic register readmodule_address + register_start + register_end (+ optional sub_byte): read a specific register range, for reverse-engineering / diagnostics.
Field Required Example Description
module_address no "05" Module to scan. Omit for a full PC-Link inventory.
register_start forensic "0x70" First register (forensic mode).
register_end forensic "0x83" Last register (forensic mode).
sub_byte no "04" Memory bank — 04 output link table (default), 00 module header, 01 BP-cell / vendor map.

Forensic mode requires module_address, register_start and register_end together. No response value; results go to the integration log and the stores. Can't run while another discovery is in progress.

action: nikobus.query_module_inventory
data:
  module_address: "05"

nikobus.send_button_press

Fires a button-press frame on the bus for address — exactly as if that physical key or IR code were pressed. Handy for triggering a Central Function / light scene, or a virtual / off-bus address that discovery doesn't know about, from an automation.

Field Required Example Description
address yes "84DFFC" 6-hex bus address to broadcast. Quote it — the YAML scientific-notation trap.

No response value.

action: nikobus.send_button_press
data:
  address: "84DFFC"

nikobus.detect_stale_inventory

Probes every known output module for bus presence and returns which respond and which don't — useful after replacing hardware, or with a second-hand PC-Link that still carries the previous install's records. Read-only: it never modifies storage (pair it with purge_stale_inventory).

Field Required Default Description
outer_attempts no 1 Full-sweep passes (1–3); raise on a busy bus.
outer_delay no 0 Seconds between passes (0–10).

Returns (response data): checked, present_modules, absent_modules, and orphaned_buttons (buttons whose links all point at absent modules).

action: nikobus.detect_stale_inventory
data:
  outer_attempts: 2
  outer_delay: 3
response_variable: stale

nikobus.purge_stale_inventory

Removes the given module addresses (and any buttons orphaned by them) from the persisted module + button stores. Feed it the absent_modules from detect_stale_inventory once you've confirmed they're really gone.

Field Required Example Description
addresses yes ["CCDD", "EEFF"] Module addresses to remove.

Returns (response data): removed_modules, removed_buttons, not_found.

action: nikobus.purge_stale_inventory
data:
  addresses: ["CCDD", "EEFF"]
response_variable: purged

Troubleshooting

Discovery says "No PC-Link" although I have one (PC-Logic installs)

If your install has a PC-Logic (05-201) configured as master, the PC-Logic answers the bus address-inquiry, not the PC-Link. The integration (like Niko's own software) reads the device inventory only from a PC-Link. Make sure Home Assistant's connection terminates at the PC-Link, then re-run discovery. A PC-Logic that answers instead is reported as "connect to a PC-Link module" — the same message the Nikobus PC software shows.

Buttons missing, or a button shows the wrong number of control points

Run 1. Load Project Overview followed by 2. Load Existing Installation while connected to the PC-Link. If a specific physical button type isn't recognised at all, its device-type byte may be uncatalogued — open an issue with the diagnostics download and the model number printed on the button.

The .nkb import did nothing / "no .nkb file found"

  • Make sure the file is uploaded: Configure → Upload .nkb project file (it's saved as nikobus.nkb), or place it in /config yourself as nikobus.nkb.
  • If several *.nkb files are in /config and none is named nikobus.nkb, the integration won't guess — rename the one to import to nikobus.nkb.
  • Names/Areas you'd already set by hand are left alone unless you tick Overwrite in Import from .nkb (choose what). If a non-overwrite run "did nothing", it likely had nothing new to fill in.
  • A file that won't parse (corrupt / not a real export) is reported as an error and nothing is changed.

Entities show as Manual button, or some entities are missing after an upgrade

This is stale data left in storage from an older release (e.g. an install that previously fell back to manual config). Symptoms: entries typed Manual button, and HA logging "Platform nikobus does not generate unique IDs … already exists" (duplicate addresses cause real entities to be dropped).

To clear it:

  1. Stop Home Assistant completely (not just reload — .storage is rewritten on shutdown, so deleting while running won't stick).
  2. Delete .storage/nikobus.buttons and .storage/nikobus.modules. (Keep any nikobus_*_config.json files if you rely on them for inventory.)
  3. Start HA, then run 1. Load Project Overview2. Load Existing Installation.

The store rebuilds cleanly with proper device types and no duplicates. Names you set in the HA UI are keyed by unique_id and reattach automatically.

Custom channel/button names didn't carry over

Friendly names you set in Home Assistant live in HA's entity/device registry (keyed by unique_id), not in the integration's store — so a clean re-discovery preserves them as long as the bus addresses are unchanged. (Removed in 3.0.0: names are no longer imported from a legacy nikobus_button_config.json; set them in HA, or import them from your .nkb, and they persist.)

State is slow to update

Without a Feedback Module, external changes (manual relay actuation, another client) are only seen on the next poll. Physical button presses still trigger immediate targeted refreshes. Add a 05-207 Feedback Module for real-time updates, or lower the polling interval.

Stale records from a previous install

A second-hand PC-Link (or replaced hardware) can leave records for modules that are no longer on the bus. Run nikobus.detect_stale_inventory to see which addresses don't respond, then nikobus.purge_stale_inventory to remove the ones you confirm are gone. See Services for all four services and their parameters.


Known limitations

  • Quote button addresses in YAML (scientific-notation trap — see Events).
  • No bus-level auto-discovery. The serial path / host:port is entered manually; the PC-Link doesn't advertise over mDNS/SSDP/USB.
  • One client per bus. Stop any other Nikobus software before starting HA.
  • Polling latency without a Feedback Module (60–3600 s; presses still refresh immediately).
  • One config entry per HA instance. Two separate Nikobus buses can't share one Home Assistant.
  • Inventory comes from the PC-Link. A PC-Logic cannot serve the device inventory (see Troubleshooting).
  • Friendly names, rooms, and named scenes come from the .nkb. The bus carries wiring, not labels — without the project file, devices keep their generic discovered names.

How the integration works

The code is split into two packages.

nikobus-connect — pip-installed, pinned in manifest.json. The low-level layer:

  • NikobusConnect — serial/TCP transport + PC-Link handshake.
  • NikobusEventListener — parses CR-terminated ASCII frames; dispatches presses and feedback.
  • NikobusCommandHandler — queued, retrying command processor that throttles bursts.
  • NikobusAPI — high-level operations (read/set output state, cover start/stop).
  • NikobusDiscovery — PC-Link inventory + module register scan; reverse-engineers button→output mappings and classifies CF broadcasts.

This integration (custom_components/nikobus/) — the Home Assistant glue:

  • coordinator.py — wires the library together; owns polling, discovery lifecycle, state signals, and the .nkb name/Area/scene apply.
  • nkbstorage.py — the three HA Stores (nikobus.modules, nikobus.buttons, nikobus.cfs).
  • nkbnames.py — reads names, rooms, per-channel names, and scene groups from a .nkb project (Access database in a ZIP, parsed with a vendored pure-Python reader).
  • nkbmanual.py — optional fallback import of nikobus_*_config.json for no-PC-Link installs (inventory source only).
  • nkbactuator.py — turns incoming button frames into HA events with debounce + duration tracking.
  • nkbconfig.py — scene-file loader/writer.
  • nkbtravelcalculator.py — virtual cover-position tracking.
  • router.py — maps module channels to HA entity types; builds the controlled_by reverse index.
  • config_flow.py — config flow (connection → hardware → polling) and the Configure options menu (customize, upload .nkb, import .nkb).
  • repairs.py — the "No Nikobus buttons configured" repair flow.
  • diagnostics.py — the diagnostics download for bug reports.
  • entity.py + the platforms (light / switch / cover / button / binary_sensor / sensor / scene).

Staying in sync

  1. Button-driven refresh — each button carries its linked_modules; a press immediately refreshes the impacted module group(s).
  2. Periodic refresh — the polling interval, or the Feedback Module's push when present.

Interoperability

The integration talks to Nikobus hardware over its serial bus. It was developed independently, solely for interoperability between Home Assistant and Nikobus hardware the user already owns, in line with Article 6 of Directive 2009/24/EC. The .nkb reader parses a project file the user already owns, locally, for the same purpose.


Issues, discussion & legal

Questions / support: the Home Assistant community thread.

Trademark: Nikobus is a trademark of Niko NV. This project is an independent community effort, not affiliated with, endorsed by, or sponsored by Niko NV.

License: provided for personal and non-commercial use. You may view, copy, modify, and share the code and documentation for non-commercial purposes. Commercial use requires prior written permission from the maintainers. Provided "as is" without warranties of any kind.

About

Home Assistant integration for Nikobus

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages