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) address —
area.line.device, e.g.1.1.1. Identifies one device. Used for management and ETS programming. - Group address —
main/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:
| Table | What it holds | StackParameters size |
|---|---|---|
| Address table | The list of group addresses the device knows | addressTableSize |
| Association table | Which group address is wired to which group object | associationTableSize |
| Group object table | Per-object config octets (comm/read/write/transmit/update flags) | groupObjectTableSize |
| Application program | Parameter area / application data | applicationProgramSize |
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.