This guide shows how Infrafon devices choose, configure, and use networks — from high‑bandwidth (MQTT/JSON over Wi‑Fi/LTE‑M) to low‑bandwidth (compact TLV messages over BLE/LoRa).
Tip: First read the Overview Guide and the DataView Reference.
Create a network.json
and define preferred connections plus fallback:
{
"networks": {
"wifiOffice": {
"type": "wifi",
"auth": { "ssid": "INFRAFON-Office", "wpa2_password": "••••••••" },
"entityMgrServer": { "url": "mqtts://ies.example.tld:8883", "user": "device123", "pass": "device123" },
"checkPeriodSecs": 60
},
"lteFallback": {
"type": "lte",
"auth": { "apn": "iot.1nce.net" },
"entityMgrServer": {
"url": "mqtts://ies.example.tld:8883",
"auth": { "mqttUser": "device123", "mqttPassword": "device123" }
},
"checkPeriodSecs": 120
},
"bleGateway": { "type": "ble" },
"loraCity": {
"type": "lora",
"auth": { "devEUI": "AA...FF", "appEUI": "38B8EBE000000000", "appKey": "AA...FF" },
"checkPeriodSecs": 300,
"tlvmap": true
}
},
"networkOrder": ["wifiOffice", "lteFallback", "bleGateway", "loraCity"],
"retryTimeoutMins": 5
}
Selection & Fallback: The device tries entries in networkOrder
in sequence. If one fails, it moves on; after a timeout it retries from the top.
type: "wifi"
)Fields
auth.ssid
(required)auth.wpa2_password
(PSK) or enterprise fields: wpa2_user
, wpa2_identity
, wpa2_keyfile
, wpa2_certfile
, wpa2_cafile
entityMgrServer.url
(mqtt://
or mqtts://
), optional user
/pass
or auth.*
checkPeriodSecs
(MQTT keepalive/ping)Enterprise example
{
"type": "wifi",
"auth": {
"ssid": "Corp-Secure",
"wpa2_user": "device123",
"wpa2_identity": "device123@corp",
"wpa2_keyfile": "/etc/certs/dev-key.pem",
"wpa2_certfile": "/etc/certs/dev-cert.pem",
"wpa2_cafile": "/etc/certs/ca.pem"
},
"entityMgrServer": { "url": "mqtts://ies.corp.tld:8883" }
}
type: "lte"
)Fields
auth.apn
(e.g., iot.1nce.net
)entityMgrServer.url
, entityMgrServer.auth.mqttUser
, entityMgrServer.auth.mqttPassword
checkPeriodSecs
Example
{
"type": "lte",
"auth": { "apn": "iot.1nce.net" },
"entityMgrServer": {
"url": "mqtts://ies.example.tld:8883",
"auth": { "mqttUser": "device123", "mqttPassword": "device123" }
},
"checkPeriodSecs": 120
}
type: "ble"
)No special fields required in the network
block. Communication via GATT:
EAD20001-F3EA-4A35-A223-9802AC9C53DF
EAD20002-…
(JSON or TLV; ~240 B — increase MTU if needed)EAD20003-…
(0
= queued, 1
= processed)EAD20006-…
(single message)EAD20007-…
Avoid permanent connections; iBeacons signal pending messages (UUID LSB /
major
/minor
).
type: "lora"
)Fields
auth.devEUI
, auth.appEUI
, auth.appKey
checkPeriodSecs
(periodic UL “pings” to open DL windows)tlvmap: true
(enable TLV mapping)Header (UL, compact)
Downlink (example)
{ "app": { "home": { "banner": "Welcome" } }, "ack": true }
Quick test
# adjust topic/host
mosquitto_pub -h ies.example.tld -t devices/<deviceId>/down -m '{"ack":true,"cmd":"ping"}'
mosquitto_sub -h ies.example.tld -t devices/<deviceId>/up -v
Concept: Tag‑Length‑Value — compact, field‑based (ideal for BLE/LoRa).
Mapping (JSON ⇄ TLV)
{
"lang": "tlv_up",
"dict": {
"app.home.alerts.ackyes": "0",
"app.home.alerts.id": "1",
"devdata.accel.orient": "2",
"devdata.power.gauge": "3"
}
}
{
"lang": "tlv_down",
"dict": {
"0": "devcfg.vibr.song",
"1": "devcfg.audioout.alert",
"2": "devcfg.nfc.emul",
"3": "app.home.site_logo",
"4": "app.home.counter"
}
}
Value encoding (short)
null
→ length 0
0..65535
→ 1–2 bytes little‑endianboolean
→ 1 byte (0/1)JSON.stringify
Example (UL JSON → TLV, shortened)
{"pri":1,"devdata":{"power":{"gauge":64},"accel":{"orient":"VU"}}}
33 01 40 32 03 56 55 00
mqtts://
.checkPeriodSecs
> 0; map only needed TLVs.ack:true
and verify the UL confirmation.Distribution: Restricted – share only with partners/clients under contract or NDA Copyright: © Infrafon GmbH 2021–2025
About this document This guide explains how to design DataViews (application UIs) for the Infrafon device and how to exchange messages with the backend via MQTTS. It includes topic conventions, JSON payloads, UI concepts (pages, widgets, dialogs), actions/rules, and configuration examples.
Version | Date | Changes | By |
---|---|---|---|
0.1 | 2021‑11‑24 | Created | A. Wyld |
1.0 | 2022‑01‑03 | Release | B. Wyld |
1.1 | 2022‑06‑20 | Updated topic names; added alert config | B. Wyld |
1.2 | 2022‑10‑28 | Object attributes; onEntry ; questionnaires |
B. Wyld |
1.3 | 2024‑02‑01 | Format/screen sizing; updated topics | B. Wyld |
2.0 | 2025‑04‑02 | Full update for CC2 | B. Wyld |
2.1 | 2025‑05‑16 | v1.0.5 | B. Wyld |
2.2 | 2025‑05‑26 | Updated MQTT topics | B. Wyld |
2.3 | 2025‑07‑07 | v1.0.7 updates | B. Wyld |
Infrafon devices render application UIs called DataViews, composed of pages and widgets, and exchange app data over MQTTS with an Infrafon Entity Server (IES). Each application lifecycle (allocate/unallocate) and device state is represented via JSON config and topic-based messaging.
Term | Meaning |
---|---|
Admin Portal | Web UI for managing users, devices, dataviews. |
Allocation/Enrollment | Assign a configured device to a specific user. |
Application Back‑end | The customer workflow server (visitor control, messaging, etc.). |
DataView | App UI on the device: set of InfoPages with InfoWidgets. |
IES (Infrafon Entity Server) | Core comms and state/config with REST & MQTT. |
DeviceUI Manager | Renders UI pages/widgets; handles input/navigation. |
ApplicationUI Manager | Parses DataView JSON, updates UI from network messages. |
MessageManager | Formats and sends MQTT messages. |
DeviceManager | Hardware/sensors, exposes attributes to UI. |
<entityname>
, device visibility).Subscribe/publish using your entity and device/dispenser IDs:
ife/<entityname>/device/msgs-up/<deviceId> # SUB: data from device
ife/<entityname>/device/msgs-down/<deviceId> # PUB: data to device (update UI / outputs)
ife/<entityname>/dispenser/system-up/<dispId> # SUB: dispenser state/sensors (if applicable)
Every topic uses a common envelope. Include only fields you need.
{
"devcfg": { /* device config object */ },
"devdata": { /* device data attributes */ },
"devwork": { "actions": [ /* device-level actions */ ] },
"app": {
"<app-name>": {
/* uplink app data */
"data": { /* downlink app data for widgets */ },
"actions": [ /* UI/app actions for downlink */ ]
}
}
}
1
or device Home.Buttons also emit press
, release
, double click
, longpress
events used by rules.
A DataView bundles pages (and optional questionnaires). Core attributes:
{
"displayName": "App name",
"displayIcon": "iconRef",
"target_size": {"w":176,"h":264},
"infopages": [ /* pages */ ],
"questionnaires": [ /* optional */ ],
"dicts": [ /* language dicts */ ]
}
Note: If
target_size
differs from device resolution, coordinates scale to fit; verify visually on a target device.
id
(integer). If pages are sequential 1..N, the Forwards/Back buttons cycle them.{
"id": 1,
"displayName": "Overview",
"infowidgets": [ /* widgets */ ]
}
Widgets show text or graphic values and can be static, dynamic, editable, or button.
{
"interaction": "dynamic", // static | dynamic | editable | button
"name": "app.status", // required for dynamic/editable
"region": { "x":16,"y":40,"w":160,"h":40 },
"format": "text", // text | graphic
"formatter": { "name": "string", "font": {"name":"times","sz":22}, "halign":"left","valign":"top", "autobreak": true },
"value": "System ready",
"displayValue": "Status: {}",
"actions": [ { "a": "gotoPage", "p": "2" } ], // for button or after edit
"ded": { "type":"int-keyboard", "title":"Set threshold", "range":{"low":0,"high":100}, "auto_ok":true }
}
Interaction types
Type | Purpose |
---|---|
static |
Never changes. |
dynamic |
Backend updates via MQTT; device refreshes immediately. |
editable |
Opens a DED; new value can be sent to backend. |
button |
Triggers actions when tapped. |
Common formatter names: string
, bool
, number
, percentage
, datetime
/date
/time
, list
, msg
, msglist
.
font
, halign
, valign
, autobreak
, fg_colour
, bg_colour
, outline
, invert
.bool
formatter uses text_true
/ text_false
.number
can round using dp
.percentage
clamps 0–100 and appends %
.msg
/msglist
extract fields f1..f3
with optional widths f1_sz..f3_sz
; msglist.sortby
sorts records.Example (datetime & bool):
{
"format": "text",
"formatter": { "name": "datetime", "halign": "left" },
"value": "2025-08-22T12:00:00Z"
},
{
"format": "text",
"formatter": { "name": "bool", "text_true":"Enabled", "text_false":"Disabled" },
"value": "true"
}
name:any
, weight:regular
, sz:22
; if requested size unavailable, nearest lower size is used.Common: icon
/basic
, bool
(icon_true/icon_false), percentage
(circle
/bar
), star
(0–5), list
(selected option’s text
→ icon ref), qr
.
Example (progress bar):
{
"format": "graphic",
"formatter": { "name": "percentage", "graphictype": "bar" },
"value": "70" // 70% (rounded to 10% steps)
}
Buttons use any formatter; value
supplies text or graphic. Add an outline
to draw a boundary.
Full-screen modals for editing values; key types include:
inp_bool
, inp_1ofn
, msglist
int-keyboard
, float-keyboard
1oflist_4choice
, noflist_4choice
, 1oflist_12choice
, noflist_12choice
bool_slider
, bool_yesno
, int_stepper
, rating_star
, listedit
Example:
"ded": {
"type": "1oflist_12choice",
"title": "Select mode",
"auto_ok": true
}
devdata.power.voltage
).home
with page id 1
to override. Ensure you include navigation to other apps if needed.Device states: unallocated, allocated, dfu, error.
Global settings live in config/global.json
. Each state can load an allocdata JSON with network & DataView configuration.
{
"data": {
"global": {
"dev": {
"<device>": { /* device config overrides */ }
}
},
"network": {
"networks": { "<netName>": { /* config */ } },
"networkOrder": ["<netName>", "..."]
},
"user": {
"visitor": "Jane Doe",
"apps": {
"local:myapp.json": {
"id": "myapp",
"src": "local",
"data": { /* initial widget values per app */ }
}
}
},
"apps": { /* inline DataViews if src:inline */ },
"dicts": [ "config/names.json", "config/locations.json" ]
}
}
{
"displayName": "My App",
"displayIcon": "appIcon",
"infopages": [
{
"id": 1,
"displayName": "Overview",
"infowidgets": [
{
"interaction": "dynamic",
"name": "status",
"region": { "x": 8, "y": 28, "w": 160, "h": 40 },
"format": "text",
"formatter": {
"name": "string",
"font": { "name": "times", "sz": 22 },
"halign": "left",
"valign": "top",
"autobreak": true
},
"displayValue": "Status: {}",
"value": "Ready"
},
{
"interaction": "button",
"region": { "x": 8, "y": 80, "w": 160, "h": 40 },
"format": "graphic",
"formatter": { "name": "percentage", "graphictype": "bar" },
"value": "40",
"actions": [ { "a": "gotoPage", "p": "2" } ]
}
]
}
],
"dicts": [ { "lang":"en", "description":"English", "dict": { "Ready":"Ready" } } ]
}
Provide dictionaries inside your DataView or as external files. All text values are looked up; if missing, the literal is shown.
"dicts": [
{ "lang": "en", "description": "English", "dict": { "mywidgetname": "My Widget" } },
{ "lang": "fr", "description": "Français", "dict": { "mywidgetname": "Mon Widget" } }
]
Set device language via devcfg.ui.lang
or user selection in the System DataView.
Actions can be triggered by widgets, MQTT, or rules.
Action (a) | Parameter (p) | Effect |
---|---|---|
vibr |
song string | Vibrate motor pattern |
beep |
AT1 /AT2 /ABS … |
Play alert tone |
led0 –led3 |
LED action string | Control specific LED |
gotoPage |
"<pageId>" or <dv>:<id> |
Navigate to page |
gotoWidget |
app.<dv>.<widget> |
Open DED for widget |
updateRemote |
<id> or <id>:<value> |
Send value to backend |
updateLocal |
<id>:<value> |
Update widget locally |
updateOutput |
<id>:<value> |
Configure device output |
hide / show |
widget id | Toggle widget visibility |
netact/nd |
network name | Activate/deactivate network |
msg /delmsg |
text / msg id | Show or delete a message |
Device config via devcfg.*
, sensor data via devdata.*
. Typical examples:
{
"devcfg": {
"ui": { "lang": "en", "enable_lock": true, "lock_timeout_secs": 30 },
"audioout": { "alert": "AT1", "durMS": 1000, "vol": 80 },
"wifi": { "connect_timeout_seconds": 12, "connect_retry_seconds": 180 },
"led": { "led0": "F0", "led1": "S0" }
},
"devdata": {
"power": { "voltage": 4.0, "gauge": 78, "isCharging": false },
"fw": { "ver_str": "v1.0.7", "device_id": "ABCDEF123456" }
}
}
Many more attributes exist (BLE scan, Wi‑Fi scan, NFC, accelerometer, duress/alerting, etc.). Consult your device profile for required fields.
Define local rules that react to button, network, or sensor events and run actions.
{
"data": {
"global": {
"dev": {
"rules": {
"onButton": [
{ "id":"okLong", "button":1, "is":"longpress", "do":[ { "a":"gotoPage","p":"system.1" } ] }
],
"onOverLimit": [
{ "id":"lowBattery", "dname":"power.voltage", "limit":4.0,
"active":[ { "a":"msg","p":"Low battery" }, { "a":"beep","p":"AT1" } ],
"clear":[ { "a":"msg","p":"Battery OK" } ]
}
]
}
}
}
}
}
{
"displayName": "Status",
"infopages": [
{
"id": 1,
"infowidgets": [
{
"interaction": "dynamic",
"name": "status",
"region": { "x":10,"y":20,"w":156,"h":28 },
"format": "text",
"formatter": { "name":"string","font":{"name":"times","sz":22},"halign":"left" },
"displayValue": "Status: {}",
"value": "Ready"
},
{
"interaction": "button",
"region": { "x":10,"y":56,"w":156,"h":28 },
"format": "text",
"formatter": { "name":"string","font":{"name":"times","sz":22},"halign":"center","outline":"solid_square" },
"value": "Next",
"actions": [ { "a":"gotoPage","p":"2" } ]
}
]
}
]
}
{
"devdata": {
"power": { "voltage": 4.01, "gauge": 62, "isCharging": false },
"accel": { "orient": "VN" }
},
"app": {
"visitor": {
"data": { "status": "Checked in" }
}
}
}
{
"app": {
"visitor": {
"data": { "status": "Please proceed to Desk 2" },
"actions": [ { "a": "gotoPage", "p": "1" } ]
}
}
}
{
"questionnaires": [
{
"id": "feedback",
"displayName": "Feedback",
"questions": [
{ "name":"q1", "value":"", "ded": { "type": "1oflist_4choice", "title":"Rate service" } }
]
}
]
}