Duress DV (duress.json)
This is the Device View shown when a staff member opens the Duress app on the CC2 badge.
It displays incoming duress alerts with the subject’s name and location, lets the user configure alert feedback (LED, vibration, sound), and shows a detailed view of a single alert for acknowledgement.
File: /dvs/duress.json
Full JSON
Section titled “Full JSON”Click to expand
{ "displayIcon": "ic_bug_report_black_24dp", "displayName": "duress", "infopages": [ { "displayName": "Alert Home", "id": "1", "infowidgets": [ { "interaction": "static", "region": { "h": 100, "w": 100, "x": 35, "y": 20 }, "value": "alert_bell", "format": "graphic", "formatter": { "name": "basic", "outline": "solid_rounded", "outline_sz": 2, "halign": "c", "valign": "c" } }, { "name": "alerts", "region": { "h": 40, "w": 156, "x": 10, "y": 130 }, "format": "text", "interaction": "editable", "onEntry": "updateRemote", "value": [ { "id": "1", "subj": "Brian", "location": "Room 101", "resp": 0 }, { "id": "2", "subj": "Toto", "location": "Room 102", "resp": 0 }, { "id": "3", "subj": "Tata", "location": "Room 103", "resp": 0 } ], "formatter": { "name": "text", "autobreak": true, "font": { "sz": 34, "weight": "normal" }, "outline": "solid_rounded", "outline_sz": 1, "halign": "c", "valign": "c" }, "ded": { "type": "alerts", "dv": "duress", "ip": "ded_alert_skel" } } ] }, { "id": "2", "infowidgets": [ { "interaction": "static", "region": { "x": 5, "y": 0, "w": 165, "h": 30 }, "value": "Config Duress", "format": "text", "formatter": { "name": "basic", "valign": "center", "halign": "center", "autobreak": true, "font": { "sz": 22 } } }, { "interaction": "button", "name": "devcfg.alert.showFlash", "region": { "x": 5, "y": 40, "w": 50, "h": 50 }, "value": true, "onEntry": "updateLocal", "format": "text", "formatter": { "name": "bool", "valign": "center", "halign": "center", "autobreak": true, "text_true": "Flash LEDs", "text_false": "No LEDs", "outline": "solid_rounded", "outline_sz": 1, "font": { "sz": 22 } }, "ded": { "type": "bool_inplace" } }, { "interaction": "button", "name": "devcfg.alert.showVibr", "region": { "x": 60, "y": 40, "w": 50, "h": 50 }, "value": true, "onEntry": "updateLocal", "format": "text", "formatter": { "name": "bool", "valign": "center", "halign": "center", "autobreak": true, "text_true": "Vibr ON", "text_false": "Vibr OFF", "outline": "solid_rounded", "outline_sz": 1, "font": { "sz": 22 } }, "ded": { "type": "bool_inplace" } }, { "interaction": "editable", "name": "devcfg.alert.showSound", "region": { "x": 115, "y": 40, "w": 50, "h": 50 }, "value": true, "onEntry": "updateLocal", "format": "text", "formatter": { "name": "bool", "valign": "center", "halign": "center", "autobreak": true, "text_true": "Audio ON", "text_false": "Audio OFF", "outline": "solid_rounded", "outline_sz": 1, "font": { "sz": 22 } }, "ded": { "type": "bool_inplace" } }, { "interaction": "button", "name": "play_vibr", "region": { "x": 5, "y": 100, "w": 50, "h": 50 }, "displayValue": "Vibr test", "value": "V10S10V10S10V10", "onEntry": "updateOutput", "target": "devcfg.vibr.song", "format": "text", "formatter": { "name": "basic", "valign": "center", "halign": "center", "autobreak": true, "outline": "solid_rounded", "outline_sz": 1, "font": { "sz": 22 } } }, { "interaction": "editable", "name": "led_colour", "region": { "x": 60, "y": 100, "w": 50, "h": 50 }, "onEntry": "updateOutput", "target": "devcfg.led.led0", "value": "S1:LED0 ON:0,S0:LED0 OFF:0,F0:LED0 SLOW:0,F1:LED0 FAST:1,B0:LED0 BLINKS:0,B1:LED0 BLINKF:0", "format": "text", "formatter": { "name": "list", "halign": "center", "valign": "center", "autobreak": true, "outline": "solid_rounded", "outline_sz": 1, "font": { "sz": 22 } }, "ded": { "type": "1ofN_inplace" } }, { "interaction": "button", "name": "play_alert", "region": { "x": 115, "y": 100, "w": 50, "h": 50 }, "displayValue": "Audio test", "value": "ABF", "onEntry": "updateOutput", "target": "devcfg.audioout.alert", "format": "text", "formatter": { "name": "basic", "valign": "center", "halign": "center", "autobreak": true, "outline": "solid_rounded", "outline_sz": 1, "font": { "sz": 22 } } }, { "interaction": "editable", "name": "devcfg.nfc.emul", "region": { "x": 5, "y": 160, "w": 50, "h": 50 }, "value": false, "format": "text", "formatter": { "name": "bool", "valign": "center", "halign": "center", "autobreak": true, "text_true": "NFC ON", "text_false": "NFC OFF", "outline": "solid_rounded", "outline_sz": 1, "font": { "sz": 22 } }, "ded": { "type": "bool_inplace" } } ] }, { "displayName": "Alert", "id": "ded_alert_skel", "infowidgets": [ { "name": "isRead", "region": { "h": 40, "w": 156, "x": 10, "y": 5 }, "format": "bool", "formatter": { "text_true": "Alert", "text_false": "**Alert**", "autobreak": true, "font": { "sz": 34, "weight": "normal" }, "halign": "c", "outline": "solid_rounded", "outline_sz": 2, "valign": "c" }, "interaction": "static", "value": "Alert" }, { "name": "msgIdx", "region": { "h": 20, "w": 30, "x": 55, "y": 50 }, "format": "number", "formatter": { "autobreak": false, "dp": 0, "font": { "sz": 14, "weight": "bold" }, "halign": "r", "outline": "none", "valign": "c" }, "interaction": "dynamic", "value": "-" }, { "region": { "h": 20, "w": 20, "x": 85, "y": 50 }, "format": "text", "formatter": { "autobreak": false, "font": { "sz": 14, "weight": "bold" }, "halign": "c", "outline": "none", "valign": "c" }, "interaction": "static", "value": "/" }, { "name": "nMsgs", "region": { "h": 20, "w": 30, "x": 105, "y": 50 }, "format": "number", "formatter": { "autobreak": false, "dp": 0, "font": { "sz": 14, "weight": "bold" }, "halign": "l", "outline": "none", "valign": "c" }, "interaction": "dynamic", "value": "-" }, { "name": "subj", "region": { "h": 30, "w": 156, "x": 10, "y": 75 }, "format": "text", "formatter": { "autobreak": true, "font": { "sz": 26, "weight": "normal" }, "halign": "c", "outline": "none", "outline_sz": 2, "valign": "c" }, "interaction": "dynamic", "value": "" }, { "region": { "h": 20, "w": 156, "x": 10, "y": 110 }, "format": "text", "formatter": { "autobreak": true, "font": { "sz": 14, "weight": "bold" }, "halign": "c", "outline": "none", "outline_sz": 2, "valign": "c" }, "interaction": "static", "value": "location" }, { "name": "location", "region": { "h": 40, "w": 156, "x": 10, "y": 130 }, "format": "text", "formatter": { "autobreak": true, "font": { "sz": 26, "weight": "normal" }, "halign": "c", "outline": "none", "underline": true, "valign": "c" }, "interaction": "dynamic", "value": "" }, { "name": "ackyes", "region": { "h": 60, "w": 60, "x": 10, "y": 180 }, "format": "graphic", "formatter": { "halign": "center", "name": "basic", "outline": "solid_rounded", "outline_sz": 2, "valign": "center" }, "interaction": "button", "value": "ic_done_black_24dp", "actions": [{ "a": "updateRemote", "p": "yes" }] }, { "name": "resp", "region": { "h": 30, "w": 40, "x": 80, "y": 180 }, "format": "number", "formatter": { "autobreak": true, "dp": 0, "font": { "sz": 26, "weight": "normal" }, "halign": "c", "outline": "none", "valign": "c" }, "interaction": "dynamic", "value": "" }, { "name": "iresp", "region": { "h": 30, "w": 40, "x": 80, "y": 210 }, "format": "bool", "formatter": { "text_true": "YES", "text_false": "NO", "autobreak": true, "font": { "sz": 14, "weight": "bold" }, "halign": "c", "outline": "none", "valign": "c" }, "interaction": "dynamic", "value": false }, { "name": "del", "region": { "h": 60, "w": 40, "x": 130, "y": 180 }, "format": "graphic", "formatter": { "halign": "center", "name": "basic", "outline": "solid_rounded", "outline_sz": 2, "valign": "center" }, "interaction": "button", "value": "bin_closed", "actions": [{ "a": "delmsg" }] } ] } ]}Page 1: Alert Home (id: "1")
Section titled “Page 1: Alert Home (id: "1")”| Widget | Type | Interaction | Purpose |
|---|---|---|---|
alert_bell (static) | graphic | static | Alert bell icon decoration |
alerts | msglist | editable | Shows active duress alerts – each with subj, location, resp. Tap opens detail DED. |
Value set by: duress_appMQTT app.duress command.
The initial static array [ { "id":"1", "subj":"Brian", ... } ] is only a placeholder; real alerts come from the portal.
Page 2: Alert Config (id: "2")
Section titled “Page 2: Alert Config (id: "2")”| Widget | Type | Interaction | Purpose |
|---|---|---|---|
| (label) “Config Duress” | text | static | Page title |
devcfg.alert.showFlash | bool_inplace | button (toggle) | Enable/disable LED flash on alert |
devcfg.alert.showVibr | bool_inplace | button (toggle) | Enable/disable vibration on alert |
devcfg.alert.showSound | bool_inplace | button (toggle) | Enable/disable audio on alert |
play_vibr | button | button | Test vibration pattern (sends updateOutput to devcfg.vibr.song) |
led_colour | 1ofN_inplace | editable | Change LED0 behaviour (list of P/S/B/F commands) |
play_alert | button | button | Test audio alert tone (sends updateOutput to devcfg.audioout.alert) |
devcfg.nfc.emul | bool_inplace | button (toggle) | Toggle NFC emulation |
Page 3: Alert Detail Skeleton (id: "ded_alert_skel")
Section titled “Page 3: Alert Detail Skeleton (id: "ded_alert_skel")”| Widget | Type | Interaction | Purpose |
|---|---|---|---|
isRead | bool | static | Shows read/unread status (bold if unread) |
msgIdx | number | dynamic | Current message index (e.g., 1 of 3) |
| (separator) | text | static | A / separator between index and total |
nMsgs | number | dynamic | Total number of messages |
subj | text | dynamic | The person who triggered the alert – populated by duress_app |
| (label) “location” | text | static | Static label “location” |
location | text | dynamic | The location string – populated by duress_app |
ackyes | graphic (button) | button | Acknowledge alert – sends updateRemote to yes |
resp | number | dynamic | Responder count |
iresp | bool | dynamic | Whether the alert was acknowledged (YES/NO) |
del | graphic (button) | button | Delete alert – sends delmsg |
Value set by: the portal’s app.duress MQTT command populates subj, location, resp, and other alert fields.
The device’s own user data (vname, etc.) is not used for these widgets.
duress_app/ MQTT Interaction
Section titled “duress_app/ MQTT Interaction”The alerts widget and the detail skeleton are populated exclusively by the portal when a duress is triggered. The duress_appsends:
{ "app": { "duress": { "data": { "alerts": [ { "id": "deviceId", "subj": "duress_appAssociated User", "location": "duress_applocation string", "resp": 0 } ] }, "actions": [{ "a": "gotoWidget", "p": "duress.alerts" }] } }}The subj and location fields become the notification text visible to the receiving staff member.
The device’s own vname or duresshome user data never appears here.
Related
Section titled “Related”- Device Views Overview – list of all DVs
- Duress Home DV – the wearer’s home screen
- duress_appuser association – how the portal’s Associated User controls
subj - MQTT app commands – the command structure used to update alerts