Product data (.knxprod) and generated models¶
bussard reads vendor product data to learn a device's com-object table, parameters,
and how to download a configuration into it. This document covers the .knxprod format,
what bussard import-product does with it, the model files it generates, and the
licensing and versioning caveats. The command's flags are in
reference.md; a worked adopt-a-device recipe
is in howto.md.
Where product data comes from¶
A .knxprod is a manufacturer's product database for one or more devices. You obtain it
from:
- the manufacturer's service/download site (most publish
.knxprodfiles free), - the MyKNX catalogue (knx.org), or
- an ETS export of a product you already have.
bussard reads these files; it never ships or redistributes them. See the never-redistribute rule below.
To save you hunting for the right file, bussard ships a
pointer index that maps an order number to where its
.knxprod can be downloaded: the URL and a checksum, never the file itself.
bussard import-product --order-number <ORDER> uses it to fetch and verify the file for
a device you saw on the bus.
What is inside a .knxprod¶
A .knxprod is a plain ZIP (no encryption, unlike a password-protected .knxproj). It
contains:
knx_master.xml # global enums: manufacturers, mask versions, DPTs
M-XXXX/ # one folder per manufacturer id, e.g. M-0004 (Jung)
Hardware.xml # order numbers → Hardware2Program → application refs
Catalog.xml # catalogue tree (not used by bussard)
M-XXXX_A-….xml # one ApplicationProgram per programmable variant
*.signature # RSA signatures, ignored (see below)
The signature files authenticate the archive to ETS. They are not access control: they stop third parties from forging files ETS will accept, but they do not stop reading a legitimately downloaded file. bussard skips them.
The ApplicationProgram XML¶
Each M-XXXX_A-….xml is the interesting part. These files are large (20-28 MB is
normal), so bussard streams them with quick-xml and never builds a DOM. It extracts:
- Identity:
Id,ApplicationNumber,ApplicationVersion,MaskVersion,Name(resolved toen-USwhere a translation exists),LoadProcedureStyle, and the XML schema version. - Com-objects: the
ComObjectbase table andComObjectRefoverrides, resolved into effective number / DPT / flags / size / text, exactly as the.knxprojimporter does (the two agree). - Parameter types:
TypeNumber(int min/max/size),TypeRestriction(enum value/text pairs),TypeText(string length),TypeFloat,TypeNone, and any otherType*element preserved by name. - Parameters and parameter refs: name, text, type ref, default value, access, and the
memory location (
CodeSegment+Offset+BitOffset). A parameter-refValue/Accessoverrides the parameter's own. - Code segments:
RelativeSegment/AbsoluteSegmentmetadata only (id, size, address/offset, load-state-machine). The binary payload is dropped. - Load procedure: the
LdCtrl*control script (LdCtrlConnect,LdCtrlUnload,LdCtrlLoad,LdCtrlWriteRelMem,LdCtrlTaskSegment,LdCtrlLoadCompleted,LdCtrlRestart, ...), parsed into a typed op list. Unknown ops are kept verbatim so nothing is lost. The downloader (bussard-download) interprets this list forbussard flash.
What import-product writes¶
In positional mode (bussard import-product <file.knxprod>) the command:
- reads the
.knxprod, - caches the source file byte-identically under
<dir>/vendor/<original-name>(skipping the copy, with a note, if an identical file is already there), - writes one model file per ApplicationProgram to
<dir>/models/<application-id>.yaml, and - creates
<dir>/vendor/.gitignore(*) ifvendor/did not already exist, so the copyrighted originals cannot be committed by accident.
The application id already carries the manufacturer id (M-0004_A-…), so the model
filename is just <application-id>.yaml, with no redundant prefix.
Output is deterministic: running the command twice on the same file produces byte-identical model YAML.
The product-data pointer index¶
Finding the right .knxprod for a device you just scanned means knowing its order
number and then hunting the manufacturer's site. The pointer index does that lookup for
you. It is a small JSON file, data/product-index.json, that ships with bussard and
holds pointers only: a download URL and a checksum for each product database, never the
copyrighted payload. import-product --list shows the index; --order-number looks a
number up.
With --order-number, bussard:
- normalizes the order number (trims whitespace, upper-cases) and looks it up in the index,
- shows you what it found and where it will download from,
- asks for confirmation (a TTY prompt, or
--yes-downloadto skip it; on a non-TTY it refuses unless--yes-downloadis given), - downloads to memory with a hard 100 MiB cap,
- verifies the download's byte size and SHA-256 against the index, where a mismatch is a hard error, since it means the file is not the one the index vouches for (the vendor may have re-published it), and
- caches the verified file under
<dir>/vendor/and runs the normal import on it.
Index schema¶
data/product-index.json is { "entries": [ … ] }, each entry:
| field | type | meaning |
|---|---|---|
manufacturer |
string | Human-readable name, e.g. "MDT". |
manufacturer_id |
string | KNX id as inside the .knxprod, e.g. "M-0083". |
order_numbers |
[string] | Every order number this download serves, verbatim as in Hardware.xml (e.g. "AKK-0216.03"). One file often bundles a whole family. |
name |
string | Product/family display name. |
url |
string | Vendor-hosted download URL for the .knxprod. |
sha256 |
string | Lower-case hex SHA-256 of the download. |
size |
number | Exact byte size of the download. |
filename |
string | Original vendor filename; also the cache name under vendor/. |
application_ref |
string? | Optional: the application-program ref an order number resolves to (documentation only). |
redistributable |
bool | Whether bussard may mirror the file itself. Always false for vendor-hosted copyrighted data. |
notes |
string? | Optional version / date-verified / caveats. |
Order-number matching is case- and whitespace-insensitive but preserves interior
separators: AKK-0216.03 and akk-0216.03 match, but AKK021603 does not, because -
and . distinguish real KNX order numbers.
What is in the index¶
The index seeds a flashability corpus: ~26 bare .knxprod databases across five
manufacturers and a range of device types, each verified by downloading it and
computing the checksum. It exists both to help you fetch a device you scanned and to
back the repeatable flashability sweep in tests-support/product-corpus/ (see
the corpus findings in DESIGN.md).
Coverage by manufacturer:
- MDT (
M-0083): switch actuators (AKK, AKS/AKI), blind/shutter (JAL), dimming / LED controller (AKD), heating (AKH), binary input (BE), glass push button (BE-GT), weather station (SCN-WS), DALI gateway (SCN-DA64x), presence detector (SCN-x360). All bare.knxprodfiles hosted directly at mdt.de. - Zennio (
M-0071): push button (Flat 1), switch/multifunction actuators (MAXinBOX, ALLinBOX), dimmer (DIMinBOX), binary input (BIN 44), fan-coil thermostat, presence sensor (EyeZen), RGB LED controller (Lumento), A/C gateway (KLIC-DI). Hosted on Zennio's CDN (assets.zennio.com/application_program/). - Lingg & Janke (
M-00E1): switch, blind, binary-input and push-button KNX Secure devices (mask0021). Hosted on the vendor's own domain; the URL path contains a literal&, which the fetcher passes through verbatim. - Theben (
M-0048) and Elsner (M-00C9): heating/dimming actuators and a temperature/humidity sensor, hosted onsiblik.com(an official distributor mirror with stable static paths, since theben.de and elsner-elektronik.de themselves ship only zips or gate downloads behind a shop/catalogue).
Mixed masks are deliberate. One MDT switch-actuator .knxprod commonly bundles a 07B0
(System B) app alongside several 0705 (System 7) ones, and the corpus spans 07B0, 0705,
0701, 0021, 0020 and 0012 families on purpose so the flashability sweep shows real
family coverage: only the 07B0 apps produce an executable flash plan today.
The fetch path deliberately handles only bare .knxprod files: the index points at
direct .knxprod downloads, and the fetched bytes are imported as-is. This keeps the
download path simple and the checksum meaningful (it covers the exact file ETS would
read).
Testing against the corpus¶
The index also backs a repeatable flashability check and a wider one-off 220-file sweep (384 application programs, 0 parse failures; only System B apps produce an executable flash plan today, since System 7 and older masks are parsed but not yet flashable). The corpus mechanics, sweep findings, and per-op refusal analysis are maintainer material: see the corpus findings in DESIGN.md.
The model file format¶
A model file describes one application program. It is machine-generated and carries a banner saying so; do not hand-edit it (it is regenerated on re-import). Example (abridged):
# Product model (generated by `bussard import-product`).
# … banner …
identity:
id: M-00FA_A-0001-11-ABCD-O000A
name: Fixture App
application_number: 1
application_version: 17
mask_version: 07B0
load_procedure_style: MergedProcedure
schema_version: '23'
order_numbers:
- TEST-1
com_objects:
0:
text: Switch
function_text: On/Off
dpt: '1.001'
flags: CRWT
ref_id: M-00FA_A-0001-11-ABCD-O000A_O-0_R-1
1:
text: Value
dpt: '9.001'
flags: CRT
ref_id: M-00FA_A-0001-11-ABCD-O000A_O-1_R-1
parameters:
- id: M-00FA_A-0001-11-ABCD-O000A_P-1
name: Threshold
text: Threshold
type: !int
min: 0
max: 100
size: 8
default: '75'
memory:
segment: M-00FA_A-0001-11-ABCD-O000A_RS-4
offset: 3
bit_offset: 0
load_procedure:
- connect
- unload lsm=1
- load lsm=1
- write_rel_mem obj=5 offset=0 size=10 applies_to=full,par
- load_completed lsm=1
- restart
- disconnect
Field notes:
identity: the application program's stable identity.order_numbers: the catalogue part numbers that map to this program (viaHardware.xml). This is the join key: a device file'sapplication_refand itsorder_numberboth point here.com_objects: keyed by com-object number, in the same field style as the device schema.dptandflags(compactCRWTUIstring) are the effective, ref-resolved values.sizeappears only when there is no DPT to imply it.ref_idis the application ref the value was resolved through.parameters: each with its resolvedtype,default, andmemorylocation. Thetypeis a tagged union:!int {min, max, size, signed},!enum {values: [{value, text}]},!text {size},!float {encoding, min, max},!none, or!other {kind, size}.memory(segment+offset+bit_offset) is what the parameter phase needs to place the value into the device's parameter memory.load_procedure: the ordered op summary, a faithful view of the download script.bussard flashexecutes the supported subset (reference.md).
The never-redistribute rule¶
Both <dir>/vendor/ and <dir>/models/ are local-only and git-ignored:
vendor/holds the copyrighted vendor.knxprodverbatim.models/holds files derived from that copyrighted data.
A user's committed repo carries only their own choices (group addresses, links, device
parameter values), never product data. Anyone who clones the repo regenerates their
models from .knxprod files they download themselves. This is the same footing as any
interoperability tool: bussard reads legitimately obtained vendor files to interoperate;
it never hosts or ships them.
ETS version and namespace caveats¶
ApplicationProgram XML declares its schema as the default namespace on the root <KNX>
element, e.g. http://knx.org/xml/project/23 for the ETS 6 generation. bussard parses
namespace-agnostically by local element name, so a file from /20, /21, or /23
reads the same way, and it records the schema version in identity.schema_version for
provenance.
Other caveats:
- Mask version drives behaviour.
mask_version(e.g.07B0,0705,0701,0021) tells the downloader whether the device is property-based (System B) or memory-based (older System 1/2). The reader only records it. - Modules. Complex devices define com-objects and parameters inside reusable module
definitions (
MD-…) that the device instantiates (MD-…_M-n_MI-n_…). The model file lists the application-level refs; the device file maps its instances onto them by dropping the_M-n_MI-ninstance segment. - Translations. Names and texts resolve to
en-USwhen a translation is present, falling back to the file's default language otherwise, matching ETS.