UDP API reference¶
Transport and authorization¶
Send one UTF-8 JSON object per UDP datagram to 127.0.0.1:<Integration API port>, normally 5300. Receive using the same bound socket you send from. Server messages end with a newline; JSON parsers accept it as whitespace.
Use sendto and recvfrom rather than restricting incoming traffic to source port 5300: MATRIC creates separate sending sockets for replies and notifications. UDP provides no delivery, ordering or retry guarantee. Commands have no correlation ID or general success acknowledgement. Keep updates small, tolerate duplicates and use timeouts when waiting for a reply.
| Common field | Meaning |
|---|---|
command |
Command name below |
appName |
Stable application name shown in MATRIC's authorization UI |
appPIN |
PIN string issued by MATRIC when PIN checking is enabled |
clientId |
Destination device for client commands; omitted or null broadcasts to connected clients |
Send CONNECT without a PIN to begin authorization, then resend requests with the issued PIN. There is no PIN or CONNECT-success reply over UDP. The user approves locally; invalid credentials can open another authorization prompt. With PIN checking disabled, commands do not require a PIN.
For notifications, the server retains the first endpoint for a given application name and IP address. Keep a fixed local listening port. If you change it while MATRIC is running, notifications can still go to the old port; restart MATRIC to clear that runtime registration. GETCONNECTEDCLIENTS replies directly to the request's source endpoint.
Commands¶
All examples below show fields to add to the common envelope.
| Command | Additional fields | Result |
|---|---|---|
CONNECT |
None | Starts authorization or registers the endpoint |
GETCONNECTEDCLIENTS |
None | Replies with ClientList |
SETACTIVEPAGE |
pageId |
Selects a page in the client's loaded deck |
SETDECK |
deckId, optional pageId |
Loads a deck and optionally a page |
SETBUTTONPROPS |
buttonId or buttonName, data |
Changes one matched control's visual properties |
SETBUTTONPROPSEX |
data array |
Changes properties of multiple controls |
SETCONTROLSSTATE |
data array |
Changes control runtime state |
SETVARIABLES |
Variables array |
Adds or updates server variables |
SETBUTTONSVISUALSTATE |
data array |
Legacy button state command; prefer SETCONTROLSSTATE |
Use a specific client ID when experimenting. SETVARIABLES is server-wide; clientId does not scope variables to a device. This command set does not enumerate decks/pages, edit action bindings, or provide a general action-execution command.
Button properties¶
{
"command": "SETBUTTONPROPSEX",
"appName": "Hobby status demo",
"appPIN": "YOUR_PIN",
"clientId": "YOUR_CLIENT_ID",
"data": [
{ "buttonName": "Status", "text": "Ready", "backgroundcolorOff": "#164e3c" },
{ "buttonName": "Warning", "text": "", "imageOff": "" }
]
}
In SETBUTTONPROPS, properties go inside data. In SETBUTTONPROPSEX, each array entry contains its target and properties together.
| Property | Value |
|---|---|
text |
Label string |
textcolorOff, textcolorOn |
Normal and pressed text colors |
backgroundcolorOff, backgroundcolorOn |
Normal and pressed background colors |
imageOff, imageOn |
Image references understood by the client, such as deck image filenames |
halign |
left, center, right |
valign |
top, mid, bottom |
padding |
Numeric string; percent of grid cell size, clamped to 0–50 |
fontSize |
Numeric string as percent of grid cell size, or a size name below |
Size names small, medium, large, xlarge, xxlarge, xxxlarge map to 10, 15, 30, 40, 60, 80 percent. Invalid padding is ignored. Omit a property or send null to leave it unchanged. Empty strings clear text, imageOff and imageOn.
An ID takes precedence over a name when both are supplied. The single-property command updates the first name match; the batch command and state command update all name matches. Prefer unique names or IDs. Names are separate from the visible button text.
Control state¶
{
"command": "SETCONTROLSSTATE",
"appName": "Hobby status demo",
"appPIN": "YOUR_PIN",
"clientId": "YOUR_CLIENT_ID",
"data": [
{ "controlName": "Status", "state": { "pressed": true } },
{ "controlName": "Level", "state": { "value": 50 } }
]
}
State is specific to the control type. Buttons accept pressed and toggle Booleans; sliders accept a numeric value. These updates do not simulate user gestures or execute the saved actions. Some controls defer a state update while the user is interacting.
The legacy SETBUTTONSVISUALSTATE uses entries such as {"buttonName":"Status","state":"on"} or "off".
Server variables¶
{
"command": "SETVARIABLES",
"appName": "Hobby status demo",
"appPIN": "YOUR_PIN",
"Variables": [
{
"Name": "hobby_temperature",
"Value": 23.5,
"VariableType": "NUMBER",
"IsPersistent": false,
"IsUserEditable": false
}
]
}
Types are STRING, NUMBER, BOOL and JSONOBJECT. Keep the JSON value consistent with its declared type. Variables and variables are both accepted. The example publishes temporary telemetry; set persistence and editability deliberately if you need another lifetime. Variables are shared across the server, so prefix their names.
Server messages¶
The envelope uses PascalCase keys. MessageData is a JSON-encoded string, requiring a second parse.
{
"MessageType": "ClientList",
"MessageData": "[{\"clientId\":\"device-1\",\"clientName\":\"My tablet\",\"currentDeckId\":null}]"
}
MessageType |
Decoded MessageData |
|---|---|
ClientList |
Array of clients with clientId, clientName, IP, matricVersion, and currentDeckId when available |
ControlInteraction |
Client message containing MessageType, ClientInfo and MessageData describing the interaction |
VariablesChange |
Object with ChangedVariables names and a Variables dictionary of variable definitions, each containing Value |
currentDeckId is device-reported, can be missing or null, and resets on reconnect. It is not proof that a deck has rendered. Request a fresh client list when needed; there is no dedicated client-list subscription command.
A decoded interaction looks like this; extra fields may be present:
{
"MessageType": "controlevent",
"ClientInfo": { "clientId": "device-1", "clientName": "My tablet" },
"MessageData": {
"DeckId": "deck-id",
"PageId": "page-id",
"ControlId": "control-id",
"ControlName": "Status",
"EventName": "press",
"Data": null
}
}
Filter events by client, deck, control and event name before acting. The notifications are not filtered by the clientId in your last command.
Large VariablesChange notifications can be split into separate envelopes at variable boundaries. Merge dictionary entries rather than assuming one message replaces every server variable. A single oversized value is not further fragmented by MATRIC; avoid large payloads.
C# examples and SDK¶
MATRICIntegrationDemo provides runnable raw UDP and SDK examples with their own setup instructions. Use this reference for the message format and that project for the C# application walkthrough.
For an application using MATRIC alongside another data source, explore DCS-BIOS-MATRIC-Middleware, which bridges DCS-BIOS cockpit state and commands.