Profile Format
An add-on profile is a JSON file. It describes a device completely: how the nomos system Controller reaches it, what it can send, which values come back and what of it appears in the app, in automations and in Quick Config. This page describes the format; how to edit it in the Profile Editor is described there. Profiles with their own connection via TCP, UDP, HTTP or serial are described in detail under CommandServer; complete examples for HTTP, TCP (Modbus), UDP, MQTT and KNX are under Example Profiles.
INFO
Every profile in the profile list can be saved as .json with the download icon. An existing profile that is similar to your device is the best starting point.
Structure at a glance
{
"version": "1.0",
"author": "Muster Integration GmbH",
"description": "Wallbox XY",
"manufacturer": "XY",
"model": "Wallbox",
"platform": "XY",
"category": "Energy",
"type": "EV Charger",
"className": "XY_WALLBOX",
"engineType": "",
"structure": { "config": {}, "commands": {}, "mappings": {} },
"polling": {},
"properties": {},
"propertiesMeta": {},
"mappings": {},
"mappingsMeta": {},
"actionTemplates": [],
"triggerTemplates": [],
"hooks": {},
"cameras": [],
"components": {}
}| Block | Content |
|---|---|
| Basic data | Name, manufacturer, category, type, engine type |
structure | CommandServer only: connection, commands and response patterns, see CommandServer |
polling | CommandServer only: commands that are sent regularly |
properties, propertiesMeta | Actions: what can be sent to the device, and their labels |
mappings, mappingsMeta | Feedback values: which values the device reports, and their labels |
actionTemplates, triggerTemplates | Templates for automations and Quick Config |
hooks | Values the device may send itself via HTTP |
cameras | Camera images of the device |
components | Sub profiles: several devices over one connection |
Important for understanding: structure only describes what goes over the wire. The app, automations and stored values work exclusively with properties and mappings. A CommandServer profile therefore needs both: the command in structure.commands and the action in properties, the response pattern in structure.mappings and the feedback value in mappings.
Basic data
| Field | Required | Meaning |
|---|---|---|
version | yes | Version number, e.g. 1.0. Existing devices only take over changes with a higher version, see Changing a profile |
description | yes | Name in the profile list and suggestion for the device name |
author, manufacturer, model | yes | Details of the author and the device |
platform | yes | Origin, usually the manufacturer. KNX for KNX, MQTT for MQTT |
category, type | yes | See Category and type |
engineType | yes | See Engine type |
className | CommandServer, KNX | For CommandServer the name of the connection (only A–Z, 0–9, _, -, 28 characters at most), for KNX always KNX, empty for MQTT and BUS |
supportUrl | no | Help page for the device, appears as an info button |
compatibility | no | Coverage of the device in percent |
nomosCertified | no | true only for profiles that nomos system has checked |
minVersion | no | Minimum version of the controller; older controllers refuse to create a device |
tags | no | Tags, see below |
hideProperties, hideMappings | no | Set by the Profile Editor itself, see Templates |
Tags with an effect: uihidden (device not in the app), voicehidden (not passed on to voice assistants and the Matter bridge). A field name does not belong in the main profile: it would replace the name the user assigns when creating the device.
A dot in the name of the profile becomes _ on import, because when loading, a dot separates profile and sub profile.
Category and type
Category and type determine the icon and control in the app and whether, and as what, the device appears via the Matter bridge. Use the values that the Profile Editor offers, e.g.:
| Category | Types |
|---|---|
Lighting | Lightbulb |
Switches | Switch, Trigger |
Thermostats | Thermostat, Thermostat Variation TA |
Window Coverings | Window Covering, Window Covering Up/Down |
Sunblinds | Sunblind |
Sensors | Temperature Sensor, Humidity Sensor, Contact Sensor, Motion Sensor, CO2 Sensor, Smoke Sensor, Light Sensor, Rain Sensor, Wind Sensor, Weather Station, Binary Sensor, … |
Energy | Inverter, Smart Meter, EV Charger, Heat Pump, Heating Controller, Pellet Boiler, Power Sensor |
Fans, Doors, Garage Door, Valves | Fan, Door, Garage Door Opener, Valve |
Security Systems | Lock, Alarm, Camera, Security System |
Choose the type according to the device's most important value.
Engine type
engineType | Connection | Special features |
|---|---|---|
"" (CommandServer) | Own connection via TCP, UDP, HTTP, HTTPS or serial | structure and polling, see CommandServer |
MQTT | Via the broker of the MQTT skill | Topics per action and feedback value, see MQTT |
KNX | Via the KNX interface | Profile without addresses, group addresses assigned when creating the device, see KNX |
BUS | Values only arrive via webhooks | For devices that report via HTTP on their own |
ZWAVE | Via the Z-Wave skill | Created via the Z-Wave page |
Every device created from a CommandServer, MQTT or BUS profile counts against the number of add-ons your licence allows.
Actions and feedback values
properties (actions) are everything that can be sent to the device. mappings (feedback values) are the values the device reports. A name may appear in both, e.g. state for switching and as the reported state; only then does the app show a switch that reflects the actual state.
"properties": {
"state": {"method": "set", "property": "ENA", "datatype": "bool"},
"switchon": {"method": "set", "property": "ENA", "value": 1, "datatype": "bool", "uihidden": true},
"switchoff": {"method": "set", "property": "ENA", "value": 0, "datatype": "bool", "uihidden": true}
},
"mappings": {
"state": {"method": "get", "property": "ENABLE_USER", "datatype": "bool", "defaultValue": false},
"reachable": {"method": "get", "property": "REACHABLE", "datatype": "bool", "defaultValue": false}
}Fields
| Field | In | Meaning |
|---|---|---|
method | both | Actions: command (send a command), set (set a property), alias (redirect to another action). Feedback values: get |
command | actions | Name of the command with method: "command" |
property | both | With set: name of the property. For feedback values: name of the reported value; for CommandServer the name of a response pattern, for KNX always value |
datatype | both | See Data types |
value | actions | Fixed value, see Fixed value |
defaultValue | both | Actions: value used when none is supplied. Feedback values: initial value until the first report |
valueList | both | Selection values, see Value lists |
min, max, internalMin, internalMax | both | See Scaling |
unit | both | See Units |
stepValue | both | Step size of sliders (not step) |
uihidden | both | Not shown as a separate row in the app |
process | feedback values | See Processing |
customFormat | feedback values | See Display |
simulateFeedback | actions | true: the sent value immediately counts as reported. For devices without feedback |
prefix, suffix | actions | Placed with a comma before or after the value (prefix,value) |
sizeInBit | both | KNX: size of the datapoint. With 1, true/false are sent as 1/0 |
filterDPT | both | KNX: datapoint types offered when assigning the group address |
mqtt, mqttValue, mqttPayload, mqttScale | both | MQTT, see MQTT |
For CommandServer, {"method": "set", "property": "ENA"} becomes the command SETENA, and {"method": "command", "command": "ON"} becomes the command ON. Both must be listed in structure.commands.
Data types
datatype | Meaning |
|---|---|
bool | Yes/no. 0, false, off, aus, offline, close, closed, error, warning count as “off” (case-insensitive), everything else as “on”. A device that reports open is therefore “on” |
int, float | Integer or decimal number (dot as decimal separator) |
string | Text |
null | Action without a value, e.g. a button. A value that is sent along is discarded |
trigger | Action that is only triggered, e.g. stopping a shading device |
Standard names
The app recognises values by their name and shows the matching control for them. Use exactly these names for these values:
| Name | Value | Data type |
|---|---|---|
state | On/off | bool |
level | Brightness 0–100 | int |
color-temperature | Colour temperature in mired | int |
position | Position of a shading device 0–100 | int |
stop | Stop a shading device | trigger |
openclose | Open/close, required for garage doors | bool |
opened | Door or gate open | bool |
temperature, setpoint | Actual and target temperature | float |
hvacmode | Operating mode | int or string |
isheating, heatingpower | Currently heating, heating power in % | bool, int |
humidity, co2, pressure, noise | Measured values | Number |
battery | Battery level in % | int |
reachable | Reachability | bool |
power | Power | float |
pv_power, grid, battery_power, battery_state, e_day, e_total | Energy: PV power, grid, storage, yield today and in total. grid from the house's point of view: feed-in positive, consumption negative | Number |
Other values may have their own names (lower-case letters, digits, _, -); the app shows them as a text row. The Profile Editor suggests all known names for the name.
state, switchon and switchoff
When the app switches a device, the controller does not send state but switchon or switchoff. Automations, on the other hand, use state itself. A switchable device therefore needs all three actions: state with the data type bool, and switchon/switchoff with the same command and the fixed value 1 or 0, both with uihidden. In propertiesMeta, one entry combines the three:
"propertiesMeta": {
"state": {"text": "State", "properties": ["state", "switchon", "switchoff"]}
}Fixed value
value on an action is the value it sends when none is supplied. If a value is supplied, e.g. from the app, that value wins, except with "datatype": "null": then value is always sent. In automations, on the other hand, the fixed value of the profile always wins. For buttons with fixed content (call a scene, press a key), therefore use "datatype": "null" and value.
Value lists
"valueList": [
{"text": "Off", "value": "0"},
{"text": "Low", "value": "1"},
{"text": "High", "value": "2"}
]On an action, the list is also an allowlist: a value that is not in it is rejected. Automations only show the selection if the same list is also in the template; repeat it there.
Scaling
internalMin/internalMax are the value range of the device, min/max the range in nomos (app, automations). The controller converts linearly, in both directions. Example: the wallbox expects the charging current in mA (6000–32000), the app shows A (6–32):
"amperelimit": {"method": "set", "property": "CURR", "datatype": "int", "unit": "A",
"min": 6, "max": 32, "internalMin": 6000, "internalMax": 32000}WARNING
Scaling applies as soon as max is set. Missing limits count as min 0, max 100, internalMin 0, internalMax 100. A "max": 3000 without internalMin/internalMax therefore scales a device value of 0–100 up to 0–3000. Set either all four limits or none.
- The result is rounded to whole numbers. A conversion from W to kW with decimal places therefore does not work via scaling; for CommandServer, use a format (
{%/1000.00}, see Format filters) or output the value in the device's unit. - Sent values are limited to
min/max. - A reversed range is possible, e.g.
"internalMin": 100, "internalMax": 0for a shading device that reports 0 % as closed.
Units
unit is either a category that the app displays and converts appropriately for each user (temperature, percent, luminescence, voltage, current, electric, energy, co2, angle, noise, pressure, currency, bigmetric, smallmetric), or a fixed unit such as W, kW, kWh, Hz, m³/h, which is displayed as it is.
For color-temperature: in nomos the value is always in mired. If the device uses kelvin, specify "internalUnit": "kelvin", the kelvin range with the cold value first ("internalMin": 6500, "internalMax": 2700) and the mired values (154/370) as min/max.
Processing
process on a feedback value processes the value after it is received, among others: invert (reverse the sign), wattHoursToKilowattHours, openCloseToBoolean (words such as open/closed into yes/no), calculateGridPrice, calculatePhotovoltaicsPrice, calculateWaterPrice (value × price from the system variable GRID_PRICE, PV_PRICE or WATER_PRICE). Triggers in automations compare the value before this processing.
Display
customFormat defines how the app shows a value. The key format is an expression in JsonLogic that calculates the displayed value; every further key is a colour that applies when its expression is true.
"grid": {"method": "get", "property": "GRID", "datatype": "float", "unit": "W",
"customFormat": {
"format": {"Math.abs": {"Math.round": {"var": "value"}}},
"red-minus": {"<": [{"var": "value"}, 0]},
"green-plus": {">": [{"var": "value"}, 0]}
}}For format, Math.round, Math.abs and the other Math functions, toFixed1, toFixed2, toFixed3 as well as CustomFormatter.toHHMM and CustomFormatter.toHHMMSS (seconds as time of day) are also available. Colours: green, red, blue, orange, purple, on their own as text colour or with -plus, -minus, -circle, -square as a dot before the value.
Labels and groups
propertiesMeta and mappingsMeta give each action or feedback value its label:
"mappingsMeta": {
"power": {"text": "Power", "group": "Vehicle charging", "properties": ["power"]}
}text: Label. The user can rename it per device.group: Section under which the app shows the value. Only for devices with many values; otherwise leave it out. The sections appear in the order of the profile.properties: Which entries this row combines, e.g.state,switchonandswitchoff. For KNX, every entry inpropertiesMetaandmappingsMetabecomes a field for a group address.
Translation
Labels, groups and texts of value lists and templates are translated if they match exactly a term that nomos knows, e.g. State, Brightness, Power, Temperature, Reachable, Turn On, Is Turned On, Off, Low, Medium, High. Any other text appears in all languages exactly as it is in the profile. Therefore write such texts in the language of the installation, or use the English standard terms that the Profile Editor suggests.
Templates
Templates are the entries that automations and Quick Config offer.
"actionTemplates": [
{"templateid": "switchon", "mapping": "switchon", "text": "Turn On", "icon": "toggle-on"},
{"templateid": "level", "mapping": "level", "text": "Brightness", "icon": "sun-o"}
],
"triggerTemplates": [
{"templateid": "state.on", "mapping": "state", "text": "Is Turned On", "value": "1", "icon": "toggle-on"}
]| Field | Meaning |
|---|---|
templateid | Unique identifier; used in saved automations, so do not change it later |
mapping | The action (for actionTemplates) or feedback value (for triggerTemplates) the template refers to. If it does not exist, the template is dropped |
text, textsuffix | Label and suffix |
icon | Name of a Font Awesome icon without fa-, e.g. toggle-on, bolt, thermometer |
value | Fixed value; the automation then shows no input field |
valueList | Selection in the automation; copy of the list of the action or feedback value |
placeholder | Example text in the empty input field of an action with text |
hideInQuickConfig | true: not in Quick Config, but in automations |
hideProperties: true and hideMappings: true make automations offer only the templates instead of all actions or feedback values. The Profile Editor sets both itself when saving: true as soon as there is at least one template.
Polling
CommandServer only. Each entry sends a command from structure.commands at a fixed interval, and once immediately at startup:
"polling": {
"Status": {"interval": 30, "editableInterval": true, "command": "STATUS"}
}interval: Interval in seconds.editableInterval: true: The interval is requested when the device is created (pre-filled withinterval).valueandeditableValue: optional value that is sent with the command, and whether it is requested when the device is created.
Sub profiles cannot poll; pollings belong to the main profile.
Webhooks
With webhooks, a device reports values itself instead of being polled, e.g. a push button that calls an address with every press. In the profile you specify which feedback values may do this; each entry needs a feedback value with the same name:
"hooks": {"action": {"enabled": true}, "battery": {"enabled": true}},
"mappings": {
"action": {"method": "get", "property": "ACTION", "datatype": "int"},
"battery": {"method": "get", "property": "BATTERY", "datatype": "int", "unit": "percent"}
}When the device is created, the controller shows the address the device should call. It has the form http://<controller IP>/api/v1/hook/<device ID>; the values are passed as parameters in the address (GET) or in the body (POST, as a form or JSON):
http://192.168.1.10/api/v1/hook/C12?action=1&battery=98The controller only accepts parameters that are enabled in hooks and responds with 200 if at least one value was accepted, otherwise with 204.
DANGER
Webhooks have no authentication. Any device in the local network that knows the address can set the enabled values. The address is blocked via remote access. Therefore only enable feedback values that a device actually has to send, and do not use them to trigger security-relevant automations, such as opening a door.
Cameras
"cameras": [
{"type": "mjpeg", "url": "http://%SERVERIP%/mjpegstream.cgi?usr=%USERNAME%&pwd=%PASSWORD%"}
]type: snapshot (single image, default), mjpeg, rtsp or otherhttp. In the URL, placeholders %NAME% are replaced by the values from the communication settings. When the device is created, one camera is created per entry. If the maximum number of video streams has been reached for rtsp or otherhttp, the camera is skipped without a message.
Sub profiles
"components": {
"out1": {"name": "Ausgang 1", "category": "Switches", "type": "Switch",
"properties": {}, "propertiesMeta": {}, "mappings": {}, "mappingsMeta": {}}
}When the device is created, each key becomes a separate device named “Device name Ausgang 1”. All share the connection of the main profile; structure, polling and cameras only exist in the main profile. A sub profile takes missing basic data (version, manufacturer, category, type, engine type) from the main profile. Do not change the key of a sub profile once devices use it.
MQTT
MQTT profiles use the broker set up in the MQTT skill; a profile cannot choose its own broker. When you create the device, you enter an MQTT Topic, which appears in the profile as %mqttTopic%.
"properties": {
"switchon": {"method": "command", "command": "power", "value": 1,
"mqtt": "cmnd/%mqttTopic%/POWER", "datatype": "null", "uihidden": true},
"level": {"method": "command", "command": "brightness",
"mqtt": "cmnd/%mqttTopic%/Dimmer", "datatype": "int", "unit": "percent"}
},
"mappings": {
"level": {"method": "get", "property": "dimmer", "mqtt": "stat/%mqttTopic%/RESULT",
"mqttValue": "Dimmer", "datatype": "int", "unit": "percent"},
"reachable": {"method": "get", "property": "reachable", "mqtt": "tele/%mqttTopic%/LWT",
"mqttValue": "", "datatype": "bool", "defaultValue": true}
}| Field | Meaning |
|---|---|
mqtt | Topic. For feedback values, + and # are allowed as wildcards |
command | Actions: name of the command. Actions with the same command must have the same topic, like switchon and switchoff |
mqttPayload | Actions: payload with \# as the place for the value, e.g. {"brightness":\#}. Without mqttPayload, the value is sent on its own |
mqttValue | Feedback values: which part of a JSON payload is the value. With a dot, a path (ENERGY.Power); without a dot, the first field with this name; for an array, a position. Empty: the whole payload |
mqttScale | Feedback values: appended to the value as a unit, but does not convert. Only useful together with "unit": "energy" (kW becomes W) |
- Messages are sent with QoS 0 and without retain.
%mqttTopic%is replaced inmqtt,commandandproperty, not inmqttPayload.- Without the feedback value
reachable, the device always counts as reachable. With the device's LWT topic (Online/Offline), the reachability is correct.
Ready-made MQTT templates and a Node-RED guide for connecting any device are described on the page MQTT Templates (in German) of the add-on library.
KNX
A KNX profile contains no addresses. It defines which values a device has and how large they are on the bus; you assign the group addresses when you create the device. Create device opens the dialog of the KNX skill with the profile for this.
"className": "KNX", "engineType": "KNX", "platform": "KNX",
"properties": {
"state": {"method": "set", "property": "value", "datatype": "bool", "sizeInBit": 1, "filterDPT": ["1.001"]},
"switchon": {"method": "set", "property": "value", "value": 1, "datatype": "bool", "sizeInBit": 1, "uihidden": true},
"switchoff": {"method": "set", "property": "value", "value": 0, "datatype": "bool", "sizeInBit": 1, "uihidden": true}
},
"propertiesMeta": {"state": {"text": "State", "properties": ["state", "switchon", "switchoff"]}},
"mappings": {
"state": {"method": "get", "property": "value", "datatype": "bool", "sizeInBit": 1, "filterDPT": ["1.001"]}
},
"mappingsMeta": {"state": {"text": "State", "properties": ["state"]}}classNameandplatformare alwaysKNX,propertyis alwaysvalue.- Every entry in
propertiesMetabecomes a field for the group address for switching, every entry inmappingsMetaone for the status address. The key itself must be the name of an action or feedback value. The address forstatealso applies toswitchonandswitchoff. sizeInBitmust match the datapoint type (1 bit for switching, 8 bit for percentages and levels, 16 bit for temperatures);filterDPTrestricts the selection when assigning. The unit comes from the datapoint type of the group address.- A value without a group address does nothing and does not appear in the app.
- A feedback value
reachableis not needed; the reachability follows the KNX connection.
The KNX skill already includes many device types (light, dimmer, shading, thermostat, sensors). A profile of your own is worthwhile for devices that are missing there. Notes on group addresses and datapoint types are on the page KNX Templates (in German) of the add-on library.
Common mistakes
- Values stay empty: For CommandServer, the feedback value is missing in
mappings, or itspropertydoes not match the name of the response pattern instructure.mappings. - Switch jumps back: There is no feedback value
state, or the device does not report its state. - App does not switch:
switchon/switchoffare missing; the app never sendsstateitself. - Numbers scaled incorrectly:
maxwithoutinternalMin/internalMax(see Scaling). - Automation does not offer a value: There are templates, but none for this value (see Templates).
- Device always reachable: For CommandServer,
CONNECTEVENT/DISCONNECTEVENTare missing; for MQTT, the feedback valuereachable(see Reachability). - A second profile
…_2: It is only created if you choose As a copy for a profile changed in the Profile Editor. Otherwise, uploading or importing again replaces the existing profile (see Updates from the Online Library).