Configuration Fields

Configuration Fields allow you to create static variables that have a product-wide default and can be overwritten per device.


Configuration Fields can be used for example if you have a large fleet of the same devices, where individual devices need to be configured with an individual value, for example a threshold.

Create a Configuration Field

Configuration Fields can be found in the Device's configuration at the bottom of the "Fields" panel. Create a new field by clicking the "Add Configuration Field" button on the top right.
This will open a modal where you can define the properties of the field:


You can choose between Number (which can store Integers as well as Floats), String and Boolean.
Once a field has been created, you can not change the type of the field.


This is the display name of the field, which has no strict requirements about the used characters.


The identifier can only contain letters, numbers and underscores. It is unique per product and by default pre-populated from the entered name.
Once a field has been created, you can not change the identifier of the field.


An optional description, can be used to explain the effect of the value to the user.


An optional unit, can be used to make the expected value more clear.

Default Value

This is the value of every device that has no explicit overwrite.

Using Configuration Fields

Overview of existing configuration fields
In the above example, I have created a field with the identifier TEST_FIELD and a default value of 2. The (x) icon next to the value indicates that this is the default value, and the device has not set an explicit overwrite.

Changing the value for a single device

To set a value for a device different from the default, use the context-menu on the right and choose "Set Value". This will open a modal where you can set a value and also reset the value to the Product's default value.

Using Configuration Fields in en- and decoders

Configuration Values are available both in decoders as well as encoders (to configure downlinks) via the global configurationValues variable. It's an object with the field identifier as key and the value as value.
An example decoder using the previously created variable could look like this:
function Decoder(bytes, port) {
var configuredValue = configurationValues.TEST_FIELD;
// configured value can now be used to modify the payload which we are not doing in this simple example
return [
field: "MY_FIELD",
value: configuredValue,
Configuration Fields can be used on Downlinks for a variety of things. See the following example on how to access those fields in your Downlink Decoder.
The following example is valid for both API, MQTT, iotcreators or LoRaWAN device types.


function Encoder(device, measurements) {
// Read configuration field value
var downlinkSerial = configurationValues["DOWNLINK_SERIAL"]
if (downlinkSerial === "0") {
console.log("Serial is not set for downlinks!")
var status = measurements.CONTROL_FIELD.value;
var payload = {
"serial": downlinkSerial,
"command": 3,
"value": status ? 1:0
return {topic: 'device/down', payload: JSON.stringify(payload)};


Temperature Offset Calibration

Temperatures often need calibration or offset added to the actual temperature value reported by the sensor. You could do this in the decoder hardcoded, but configuration fields are a nicer way when you, for example, work with 100s of devices and they all belong to the same product (and so share a single payload decoder).
But even when working with a single sensor, usage of configuration fields make sense here.


function Decoder(bytes, port) {
var decoded = {};
var temperature = (bytes[0] <<8 | bytes[1]) / 10.0;
var offset = configurationValues.TEMPERATURE_OFFSET;
decoded.temperature = temperature + offset;
return decoded;

Fill Level Offset

When working with Fill Level Sensors you often need to convert or map the value range of the sensor to the actual height that you are measuring to derive the fill level (of the object, container, water level, and so on).
Configuration fields can be used to create a fleet of 100s of fill level sensors and store these settings individually while still having the benefits of a shared product (same dashboard, payload decoder, database fields).


function Decoder(bytes, port) {
var decoded = {};
decoded.battery = ((bytes[0]<<8 | bytes[1]) & 0x3FFF) / 1000;
decoded.distance = bytes[2]<<8 | bytes[3];
try {
var delta = configurationValues.SENSOR_LEVEL_EMPTY - configurationValues.SENSOR_LEVEL_FULL;
var sensorRelative = configurationValues.SENSOR_LEVEL_EMPTY - decoded.distance;
var fillLevel = Math.abs((sensorRelative / delta) * 100);
if (fillLevel > 100) fillLevel = 100;
else if (fillLevel < 0) fillLevel = 0;
decoded.fill_level = fillLevel;
} catch (e) {
try {
decoded.LORA_RSSI = (!!normalizedPayload.gateways && !!normalizedPayload.gateways[0] && normalizedPayload.gateways[0].rssi) || 0;
decoded.LORA_SNR = (!!normalizedPayload.gateways && !!normalizedPayload.gateways[0] && normalizedPayload.gateways[0].snr) || 0;
decoded.LORA_DATARATE = normalizedPayload.data_rate;
} catch (e) {
return decoded;

Field Configuration