2026-08-06
etsknxtooling

The ETS 6 group address import format, explained

The table already exists

By the time anyone opens ETS, the addresses are usually already written down — in the project spreadsheet, in the tender documents, in a list the client sent. Typing two thousand of them in by hand costs a day and introduces mistakes that surface months later on site.

ETS imports them from a CSV in a second. The obstacle is that the file has to have exactly the shape ETS expects, and that shape is poorly documented.

Nine columns

The file is semicolon-separated with a fixed nine-column layout:

#ColumnPurpose
1MainName, on main group rows only
2MiddleName, on middle group rows only
3SubName, on group address rows only
4Address"1/-/-", "1/0/-" or "1/0/3"
5CentralCentral function flag, normally empty
6UnfilteredRouting flag, normally empty
7DescriptionFree text, optional
8DatapointTypee.g. "DPST-1-1" — optional, but see below
9Security"Auto" or "Off"

The one detail everyone gets wrong

The level of an entry is encoded by which column carries the name. Not by indentation, not by a separate type field, not by the address alone. Three rows show the whole rule:

Main group     "Lighting"; ; ;"1/-/-";"";"";"";"";"Off"
Middle group    ; "Switch"; ;"1/0/-";"";"";"";"";"Auto"
Group address   ; ;"Kitchen ceiling";"1/0/3";"";"";"";"";"Auto"

Put the name in the wrong column and ETS will either reject the row or create it at a level you did not intend. This is the single most common reason a hand-written export fails to import cleanly.

The pitfalls worth knowing before you generate 2 000 rows

  • Line endings must be CRLF. A file written with bare LF will not import.
  • Quotes inside a name are escaped by doubling them, the usual CSV rule.
  • Ranges: main group 0–31, middle group 0–7, group address 0–255. Nothing warns you if you exceed them in a spreadsheet.
  • Set the datapoint type at import time. It is technically optional, and skipping it means walking back through every address in ETS later — an empty type is a future bug.
  • Encoding: the file below is UTF-8 with no byte-order mark. If your group names are pure ASCII this never matters. If they carry umlauts or dashes, run one small import first and look at how the names land, before you generate the full file.

Describe the tree once, then feed it addresses

The generator splits the job in two. A schema describes the shape of the group address tree — which main groups exist, which middle groups sit inside them, what datapoint type each carries. The project table then supplies the addresses. Nothing about the tree is repeated per row.

That separation is what makes the naming consistent for free: every middle group keeps its meaning across the whole project, because it is declared once.

const schema = [{
  index: 1,
  name: 'Lighting — ground floor',
  middle: [
    { index: 0, name: 'Switch',        field: 'switch',       dpt: 'DPST-1-1', suffix: 'On/Off' },
    { index: 1, name: 'Switch status', field: 'switchStatus', dpt: 'DPST-1-1', suffix: 'On/Off St' },
    { index: 2, name: 'Dimming',       field: 'dim',          dpt: 'DPST-3-7', suffix: 'Dim' },
  ],
}];

Validation is the part hand work does not have

Generating the file is the easy half. The half that pays for itself is refusing to generate a broken one. Four faults in a source table, and what comes back:

- Lighting / Switch / Hall downlights: address 1/0/1 already used by "Kitchen ceiling On/Off"
- Lighting / Switch / Terrace: address 1/9/3 sits in middle group 9, but the schema places it in 0
- Lighting / Switch / ?: missing device name
- Lighting / Switch / Study: address 1/0/999 exceeds the 0–255 sub range

The first of those is the expensive one. Two group objects on one address is legal in KNX and occasionally intended, but far more often it is a copy-paste slip in the spreadsheet. Found here it costs nothing. Found on site it costs a visit, because the symptom is two circuits that switch together and nothing in the project looks wrong.

The whole pass

A table of seven devices, one command: the output below is exactly what the published example produces — 26 addresses across two main groups, verified byte for byte against the sample file in the repository.

"Lighting — ground floor"; ; ;"1/-/-";"";"";"";"";"Off"
 ;"Switch"; ;"1/0/-";"";"";"";"";"Auto"
 ; ;"Kitchen ceiling On/Off";"1/0/1";"";"";"";"DPST-1-1";"Auto"
 ; ;"Kitchen worktop On/Off";"1/0/2";"";"";"";"DPST-1-1";"Auto"
 ;"Switch status"; ;"1/1/-";"";"";"";"";"Auto"
 ; ;"Kitchen ceiling On/Off St";"1/1/1";"";"";"";"DPST-1-1";"Auto"

In ETS: Group Addresses → Import → CSV.

What this does not do

The import creates group addresses. It does not link them to the communication objects of your devices — that remains manual work in ETS, and mass linking is only reachable through the ETS API.

The format here is what ETS 6 accepts. ETS 5 uses a different column set, so do not assume the file carries over.

One limit inside the tool: the address pattern accepts a middle group of 0–9, while KNX allows 0–7. A wrong middle group is caught when it disagrees with the schema, as in the example above — but declare index 8 in the schema itself and nothing will object. The 0–255 sub range is checked explicitly.

Take it

No dependencies, Node 18 or newer, MIT licence. Adapt the schema to your own naming and it will run as it stands.

ets-group-addresses.js — MITWhat to put in those names: structuring 2 000 group addressesA project built on this structure, with the full exportKNX programming as a service

Discuss a Project

Discuss Project