Kbox-UniStack Docs

Core Concepts

The KNX and kbox-stack mental model — telegrams, group objects, datapoint types, the four tables, System B security, and the dependency-injected peripheral model.

KNX in one minute

KNX is a fieldbus for building automation. Devices share a single twisted-pair (TP1) bus and talk by broadcasting short telegrams. There are two kinds of address:

  • Individual (physical) addressarea.line.device, e.g. 1.1.1. Identifies one device. Used for management and ETS programming.
  • Group addressmain/middle/sub, e.g. 0/0/1. A logical channel. A switch and the lamps it controls share a group address; a "write" to that group is delivered to every device subscribed to it.

Runtime traffic is mostly group communication: a device sends a GroupValueWrite to a group address, and subscribed devices apply the new value.

A broadcast telegram uses destination 0x0000 with address-type = group. Group vs individual is a bit in the telegram, not just a formatting convention.

Group objects and datapoint types (DPT)

A group object (also called a datapoint) is one addressable value inside a device — "lamp on/off", "setpoint", "measured temperature". In kbox-stack a group object is a DeviceObject: an object id, a data type (Bit / Byte / Float / ByteArray), and its current value.

The stack stores raw bytes. The DPT gives those bytes meaning:

  • A 1-bit object carries DPT 1.xxx (boolean: on/off, open/closed).
  • A 1-byte object carries DPT 5.xxx (0–100 %, scene number, …).
  • A 2-byte float object carries DPT 9.xxx (temperature, humidity, …), encoded with the KNX 2-octet float codec.

kbox-stack keeps the DPT encode/decode separate from storage: the raw word lives in the object, and the DPT codec (Dpt::D9 for 2-byte floats) is applied by the caller. See Value Encoding (DPT) for the encoding rules.

The four tables

A KNX device's group-communication behaviour is described by four tables that ETS downloads into the device. In kbox-stack these map to flash segments and to StackParameters size fields:

TableWhat it holdsStackParameters size
Address tableThe list of group addresses the device knowsaddressTableSize
Association tableWhich group address is wired to which group objectassociationTableSize
Group object tablePer-object config octets (comm/read/write/transmit/update flags)groupObjectTableSize
Application programParameter area / application dataapplicationProgramSize

At runtime the GroupObjectTables resolves an incoming group address to the affected group objects by walking the address table (address → id), the association table (id → object ids), and the group object table (config octets). See Database for the resolution engine.

The size fields you pass to StackParameters reserve the flash segments that hold these tables. An ETS download must fit within them — size them for the maximum number of group objects you expect.

System B and KNX Data Secure

kbox-stack targets the KNX System B profile with mask version 07B0h (reported in the A_DeviceDescriptor_Read response). System B covers ETS S-Mode download, property/load-state management, and the standard management services.

KNX Data Secure is optional and layered on top: telegrams are wrapped/unwrapped with AES-CCM and protected against replay by a sequence number. The same prebuilt .a contains both paths — you get the secure path by constructing the stack through the secure factory. See KNX Data Secure.

The DI peripheral model

Every hardware dependency the stack has is injected as an interface reference. The naming convention has three layers:

  • I<X> — a pure interface (pure-virtual only). The DI contract. The stack core includes only these.
  • Base<X> — hardware-agnostic shared logic/state (for example a blink state machine, or a tx/rx queue). For peripherals that need no hardware, Base<X> is concrete and used directly (e.g. BaseButton, BaseClock).
  • Hal<X> — a concrete platform implementation (STM32 HAL today). Only these touch the vendor SDK.

The seven peripherals are IBusDriver, ITransmitter, IWatchDog, IClock, ILed, IButton, and IFlash. The stack constructor takes them all as I<X>& — it never news a driver and never sees a concrete Hal<X>.

This is what makes the stack portable: to move to a new MCU you implement the same I<X> interfaces against your HAL and rebuild the binary. Nothing in the core changes. See Porting and Peripheral Interfaces.