eDIDIO S10 Protocol v1.3.2

eDIDIO S10 Protocol APIv1.3.2

Google Protocol Buffer message reference for the eDIDIO S10 controllers and the ADDICT V3 — Getting started (README) · Changelog · Repository

At a glance

New here? Start with Requests and replies.

Requests and replies

How a request works

Examples

Each request with its frame as sent on the socket (start byte and length included).

The three you will use most - a DALI command, DMX levels and an external trigger - can be built in SpektraPlus: Device Tools → Message Generator. Fill in the fields and it gives the bytes, start byte and length included, as decimal or hex, ready to paste into another system.

Set a DALI arc level

A command: the device answers with an AckMessage.

Request
EdidioMessage {
  message_id: 1
  dali_message {
    line_mask: 0b0001        // line 1
    address: 5               // short address
    custom_command: DALI_ARC_LEVEL
    arg: 200                 // arc level 0-254
  }
}
cd 00 0e 08 01 92 01 09 08 01 10 05 30 00 48 c8 01
Reply
EdidioMessage {
  message_id: 1
  ack { payload: SUCCESS }
}
cd 00 06 08 01 12 02 08 05

A field holding its default (0, false, "", the first enum value) is normally not sent at all. custom_command is the exception here: it is one choice of the action oneof, and a oneof field is always sent once chosen - so DALI_ARC_LEVEL (0) appears as 30 00.

Set DMX levels

A dmx_message sets consecutive channels on one or more universes, with an optional fade. channel is the first channel (1-512); level holds one value per channel and is repeated repeat times - here one RGB fixture set to red over 250 ms.

Request
EdidioMessage {
  message_id: 2
  dmx_message {
    universe_mask: 0b0001    // universe 1
    channel: 1               // first channel, 1-based
    repeat: 1                // one fixture
    level: [255, 0, 0]       // R, G, B
    fade_time_by_10ms: 25    // 250 ms
  }
}
cd 00 13 08 02 a2 01 0e 10 01 18 01 20 01 2a 04 ff 01 00 00 30 19
Reply
EdidioMessage {
  message_id: 2
  ack { payload: SUCCESS }
}
cd 00 06 08 02 12 02 08 05

Fire a trigger

An external_trigger runs any action a button or schedule could: the TriggerMessage names the TriggerType, and target_index / value / line_mask mean what that type says. Here it starts list 0 (lists count from 0).

Request
EdidioMessage {
  message_id: 3
  external_trigger {
    trigger {
      type: LIST_START
      target_index: 0        // list 0
    }
  }
}
cd 00 09 08 03 aa 01 04 0a 02 08 09
Reply
EdidioMessage {
  message_id: 3
  ack { payload: SUCCESS }
}
cd 00 06 08 03 12 02 08 05

Read a property

An AdminMessage GET comes back as an AdminMessage with the value filled in - here the device name, in data.string_data (the admin property table says which field each property uses).

Request
EdidioMessage {
  message_id: 4
  admin_message {
    command: GET
    target: DEVICE_NAME
  }
}
cd 00 07 08 04 8a 02 02 08 01
Reply
EdidioMessage {
  message_id: 4
  admin_message {
    command: GET
    target: DEVICE_NAME
    data { string_data: "Lobby" }
  }
}
cd 00 10 08 04 8a 02 0b 08 01 1a 07 1a 05 4c 6f 62 62 79

Change a property

A SET carries the new value in the same field and is answered with an AckMessage; INVALID_PARAMS if the value is refused.

Request
EdidioMessage {
  message_id: 5
  admin_message {
    command: SET
    target: DEVICE_NAME
    data { string_data: "Foyer" }
  }
}
cd 00 0e 08 05 8a 02 09 1a 07 1a 05 46 6f 79 65 72
Reply
EdidioMessage {
  message_id: 5
  ack { payload: SUCCESS }
}
cd 00 06 08 05 12 02 08 05

Ask what the device supports

A diag_message of type DIAGNOSTIC_SYSTEM_INFO returns diag_system: firmware and hardware versions, how many lists, alarms, sensors and so on it has, and proto_version - the protocol version it was built against.

Request
EdidioMessage {
  message_id: 6
  diag_message {
    type: DIAGNOSTIC_SYSTEM_INFO
  }
}
cd 00 05 08 06 82 02 00
Reply
EdidioMessage {
  message_id: 6
  diag_system {
    firmware: "..."
    proto_version: 0x010302   // 1.3.2
    ...
  }
}

Gate a feature on the protocol version: if (proto_version >= 0x010302) (1.3.2). Decode it as major = v >> 16 & 0xFF, minor = v >> 8 & 0xFF, patch = v & 0xFF. 0 means the firmware predates the field.

Read configuration back

A read_device request comes back as the payload for the ReadType asked for - here the physical inputs of profile 0, as inputs.

Request
EdidioMessage {
  message_id: 7
  read_device {
    type: INPUTS
    profile: 0
  }
}
cd 00 05 08 07 8a 01 00
Reply
EdidioMessage {
  message_id: 7
  inputs { ... }   // InputMultiMessage
}

EdidioMessage payloads

Field number, the payload field to set, its message type, and what the device sends back.

#FieldTypeWhat it doesReplyRoleDevices
2ackAckMessageThe answer to a request that returns no data: success, or why it was refused (type and detail).sent by the deviceeDIDIO, ADDICT
3inputsInputMultiMessageConfigure the physical inputs of one profile; also the reply to read_device INPUTS.AckMessageCONFIGeDIDIO
4outputsOutputMultiMessageConfigure the outputs of one profile; also the reply to read_device OUTPUTS.AckMessageCONFIGeDIDIO
5irsIRMultiMessageConfigure the IR codes of one profile (deprecated); also the reply to read_device IR.AckMessageCONFIGeDIDIO
6sensorSensorMessageConfigure one DALI-2 sensor; also the reply to read_device SENSOR.AckMessageCONFIGeDIDIO
8listListMessageConfigure a list - up to 32 steps, the rest follow in list_extended; also the reply to read_device LIST.AckMessageCONFIGeDIDIO
10alarmAlarmMessageConfigure one alarm (a scheduled action).AckMessageCONFIGeDIDIO
11alarmsAlarmMultiMessageConfigure every alarm at once; also the reply to read_device ALARMS.AckMessageCONFIGeDIDIO
12burn_insBurnInMultiMessageConfigure the burn-ins; also the reply to read_device BURN_IN.AckMessageCONFIGeDIDIO
13sensor_commandSensorCommandMessageMute, unmute or override a sensor.AckMessageCONTROLeDIDIO
14change_profileChangeProfileMessageChange the active profile (this resets the sensors).AckMessageCONTROLeDIDIO
15identify_messageIdentifyMessageShow information on the device's screen to help find it.AckMessageCONTROLeDIDIO
16update_timeUpdateTimeMessageSet the device clock.AckMessageCONFIGeDIDIO
17read_deviceReadDeviceMessageRead configuration back; the reply is the payload for the ReadType asked for.see ReadTypeCONTROLeDIDIO
18dali_messageDALIMessageSend a DALI command or query on one or more lines.AckMessage for a command, dali_query for a queryCONTROLeDIDIO, ADDICT
19dali_queryDALIQueryResponseA DALI query's answer, tagged with the line and address.sent by the deviceeDIDIO, ADDICT
20dmx_messageDMXMessageSet DMX levels on one or more universes, with an optional fade.AckMessageCONTROLeDIDIO, ADDICT
21external_triggerExternalTriggerMessageFire a trigger action from another system.AckMessageCONTROLeDIDIO
22spektra_settingsSpektraSettingMessageConfigure a Spektra zone; also the reply to spektra_read SETTINGS.AckMessageCONTROLeDIDIO
23spektra_sequenceSpektraSequenceConfigMessageStore a Spektra sequence; also the reply to spektra_read SEQUENCE.AckMessageCONTROLeDIDIO
24spektra_calendarSpektraCalendarMessageAssign a sequence or theme to calendar days.AckMessageCONFIGeDIDIO
25spektra_themeSpektraThemeConfigMessageStore a Spektra theme; also the reply to spektra_read THEME.AckMessageCONTROLeDIDIO
26spektra_readSpektraReadMessageRead Spektra data: SETTINGS gives spektra_settings, SEQUENCE spektra_sequence, THEME spektra_theme, CALENDAR spektra_calendar_overview, LIVE spektra_live, and with manifest set spektra_manifest.see the type asked forCONTROLeDIDIO
27spektra_controlSpektraControlMessageStart, stop or pause a sequence or theme, or save the Spektra settings.AckMessageCONTROLeDIDIO
28dmx_translatorDMXProtocolTranslationConfigure the DMX to DALI translation objects; also the reply to read_device DMX_TRANSLATIONS.AckMessageADMINeDIDIO
29input_requestInputStateMessageAsk for the live state of the physical inputs.input_responseCONTROLeDIDIO
30input_responseInputStateResponseThe live input state mask.sent by the deviceeDIDIO
31diag_systemDiagnosticSystemInfoResponseThe device's capabilities, firmware, hardware and protocol version (proto_version): the reply to diag_message DIAGNOSTIC_SYSTEM_INFO.sent by the deviceeDIDIO, ADDICT
32diag_messageDiagnosticMessageAsk for a diagnostic report; the reply depends on the type asked for.see DiagnosticMessageTypeCONTROLeDIDIO, ADDICT
33admin_messageAdminMessageGet, set or run a device property.admin_message for a GET, else AckMessagesee AdminPropertyTypeeDIDIO, ADDICT
34eventEventMessageADDICT: a filter starts or stops DALI bus monitoring, and each frame seen arrives as an event. On an eDIDIO, live events are event_stream (77).AckMessageNONEADDICT
35secure_device_settingsSecureDeviceSettingsMessageChange the secure-login settings (AES encrypted).AckMessageADMINeDIDIO
36firmware_newFirmwareMetaMessageStart a firmware update: describes the image, and erases the one stored.AckMessageADMINeDIDIO, ADDICT
37firmware_controlFirmwareControlMessageFirmware update control (verify, apply, ...) from the client, and the device's verify result.firmware_control or AckMessageADMINeDIDIO, ADDICT
38firmware_chunkFirmwareChunkMessageOne chunk of the firmware image.AckMessageADMINeDIDIO, ADDICT
39level_cache_responseLevelCacheResponseA page of 64 cached DALI or DMX levels: the reply to a diag_message level-cache request.sent by the deviceeDIDIO, ADDICT
41list_extendedExtendedListMessageThe steps of a list beyond the first 32; also the reply to read_device LIST_EXTENDED.AckMessageCONFIGeDIDIO
42ayt_messageAytMessage"Are you there?" keep-alive: send one within 20 s or the connection is closed.ayt_messageCONTROLeDIDIO, ADDICT
43rdm_messageRDMMessageSend an RDM GET or SET to a fixture.AckMessage, then rdm_response_messageCONTROLeDIDIO, ADDICT
44rdm_response_messageRDMResponseMessageA fixture's RDM response.sent by the deviceeDIDIO, ADDICT
45logic_messageLogicMultiMessageConfigure the logic rules; also the reply to read_device LOGIC.AckMessageCONFIGeDIDIO
46secure_loginAdminSecureLoginMessageLog in to a role, answering the nonce from AdminMessage NONCE.AckMessage (detail = the role granted)NONEeDIDIO
47device_state_messageDeviceStateMessageAsk for the live state: uptime, clock, next alarm, inputs, lists and burn-ins.device_state_messageCONTROLeDIDIO, ADDICT
48spektra_calendar_daySpektraCalendarDayMessageNot sent on its own: a calendar's days arrive inside spektra_calendar_overview.unusedeDIDIO
49spektra_calendar_overviewSpektraCalendarOverviewMessageThe calendar: the reply to spektra_read CALENDAR.sent by the deviceeDIDIO
50inputs_daliDALIInputMultiMessageConfigure the DALI inputs of one profile; also the reply to read_device DALI_INPUTS.AckMessageCONFIGeDIDIO
51logs_readSystemLogReadMessageRead up to 32 system log entries from a start index.logs_readCONFIGeDIDIO
52metadata_readSystemMetaDataReadMessageRead system metadata for debugging.metadata_readCONTROLeDIDIO
53dali_addressing_messageDALIAddressingMessageRun DALI addressing on a line.dali_addressing_messageCONFIGeDIDIO, ADDICT
54dali_remapping_messageDALIRemappingMessageMove DALI devices to other short addresses.AckMessageCONFIGeDIDIO, ADDICT
58rdm_discoveryRDMDiscoveryMessageDiscover the RDM fixtures on a universe.rdm_discovery_replyCONFIGeDIDIO, ADDICT
59rdm_discovery_replyRDMDiscoveryReplyMessageUp to 128 discovered RDM fixtures; isNext asks for more.sent by the deviceeDIDIO, ADDICT
60dali_identify_duplicatesDALIIdentifyDuplicatesMessageFind DALI devices sharing a short address.dali_identify_duplicatesCONFIGeDIDIO, ADDICT
61spektra_liveSpektraLiveMessageWhat Spektra is playing now, per zone: the reply to spektra_read LIVE.sent by the deviceeDIDIO
62sensor_querySensorsQueryRead the sensors' live state, up to 20 per request (page with offset).sensor_queryCONTROLeDIDIO
63data_aliasesDataAliasesGet or set the names of profiles, inputs, lists, sensors and so on.data_aliases for a get, AckMessage for a setCONFIGeDIDIO
64sd_dir_listSdDirListMessageList an SD card directory, a page at a time (6-pole).sd_dir_listCONFIGeDIDIO
65sd_file_readSdFileReadMessageRead a chunk of a file on the SD card (6-pole).sd_file_readCONFIGeDIDIO
66sd_file_writeSdFileWriteMessageWrite a chunk of an upload to the SD card (6-pole).sd_file_writeCONFIGeDIDIO
67sd_file_controlSdFileControlMessageSD card file operations: stat, free space, delete, upload begin / end / abort / resume (6-pole).sd_file_controlCONFIGeDIDIO
68sd_log_configSdLogConfigMessageEnable or disable log categories (6-pole).sd_log_configCONFIGeDIDIO
69sd_log_streamSdLogStreamMessageDeprecated: the v1 event stream, replaced by event_stream (77). Tag 69 stays reserved.unusedeDIDIO
70crash_logCrashLogMessageRead the crash / reset record captured in backup RAM at boot.crash_logADMINeDIDIO, ADDICT
71sd_log_policySdLogPolicyMessageGet or set the SD log rotation policy (6-pole).sd_log_policyCONFIGeDIDIO
72connection_statusConnectionStatusMessageThe device's client connections: slot counts and per-connection details.connection_statusADMINeDIDIO, ADDICT
73provision_get_stateProvisionGetStateMessageRead the device identity state (all public).provision_get_stateADMINeDIDIO
74provision_install_identityProvisionInstallIdentityMessageInstall the device identity, in chunks; accepted only while unprovisioned.provision_install_identityADMINeDIDIO
75provision_popProvisionProofOfPossessionMessageProve the device holds its key: it signs the nonce sent.provision_popADMINeDIDIO
76provision_decommissionProvisionDecommissionMessageReturn the device to unprovisioned.provision_decommissionADMINeDIDIO
77event_streamEventStreamMessageSubscribe to the live event / log stream; events then arrive as event_stream.event_streamCONFIGeDIDIO, ADDICT
78spektra_manifestSpektraManifestMessageWhich Spektra slots hold data, with a CRC for each: the reply to spektra_read with manifest set.sent by the deviceeDIDIO

Admin properties

An admin_message names a target property and a command. Payload is the AdminMessage field the value travels in, both ways; for data it is the PayloadMessage field used. Actions (RUN, RESET, ADD, REMOVE) carry none and are answered with an AckMessage.

#PropertyCommandsPayloadRoleDevicesDescription
0DEVICE_NAMEGET, SETdata.string_dataCONFIGeDIDIO, ADDICTThe device name that appears on the network. Limited to 16 characters.string_data.
1PROJECT_NAMEGET, SETdata.string_dataCONFIGeDIDIOUsed for documentation. Limited to 32 characters.string_data.
2LONGITUDEGET, SETdata.float_dataCONFIGeDIDIOUsed for calculating astronomical sunrise / sunset.float_data.
3LATITUDEGET, SETdata.float_dataCONFIGeDIDIOUsed for calculating astronomical sunrise / sunset.float_data.
4LOCAL_UTC_OFFSETGET, SETdata.float_dataCONFIGeDIDIOUsed for calculating astronomical sunrise / sunset.float_data.
5DAYLIGHT_SAVINGSGET, SETdata.uint_dataCONFIGeDIDIOUsed for calculating astronomical sunrise / sunset.uint_data.
6POLL_ACTIVEGET, SETdata.uint_dataCONFIGeDIDIOWhether or not to poll the current level of DALI devices to keep an in-memory cache up-to-date.uint_data.
7DHCP_ENABLEDGET, SETdata.uint_dataADMINeDIDIOWhether or not the device should use a static IP or expect a DHCP server to provide it with an IP.uint_data.
8IP_ADDRGET, SETdata.string_dataADMINeDIDIOThe static IP address to use if DHCP_ENABLED is FALSE.string_data.
9MAC_ADDRGET, SETdata.string_dataADMINeDIDIOThe MAC Address of the device. Expected format: [40:D8:55:1B:XX:XX].string_data.
10GATEWAY_IPGET, SETdata.string_dataADMINeDIDIOThe IP address of the gateway for the network this device will be installed on.string_data.
11NETWORK_PROPERTIESGET, SETnetwork_propertiesADMINeDIDIO, ADDICTContains numerous properties such as DHCP, NTP, Gateway, IP, MAC.
12SYSTEM_PROPERTIESGET, SETproject_propertiesCONFIGeDIDIOContains numerous properties such as Device Name (documentation only; not network hostname), Project Name, Latitude, Longitude, UTC Offset, DLS, Polling.
13CONTROLLER_LINESGET, SETcontroller_linesCONFIGeDIDIOAllows you to specify the daughterboards installed in the device [NONE, DALI, DMX, DMX_IN].
14EEPROM_FULL_CHIPRESETnoneADMINeDIDIOAllows you to request a reset to default values for all data stored in EEPROM.
15CONFIG_DATARESETnoneADMINeDIDIOAllows you to request a reset to default values for the Config Data stored in EEPROM.
16SPEKTRA_DATARESETnoneADMINeDIDIOAllows you to request a reset to default values for the Spektra Data stored in EEPROM.
17DEVICE_STATUSGETdevice_statusCONTROLeDIDIO, ADDICTCan be used to request the Device Status: Temperature and Battery Voltage.
18CONFIG_STATUSGETconfig_statusCONTROLeDIDIOCan be used to request the Config Status: Active Alarm, List States, Sensor States, Burn-in States.
19DEVICE_TIMEGET, SETdevice_timeCONTROL for GET, CONFIG for SETeDIDIOGet or Set the RTC time on the device.
20NTP_DETAILSGET, SETnetwork_propertiesCONFIGeDIDIOAllows you to Get or Set the NTP parameters (i.e. NTP Server) used for maintaining the RTC via NTP updates.
21DALI_SENSORSADD, REMOVE, RESETnoneCONFIGeDIDIOProvides actions for DALI Sensor control: "ADD" to un-mute all. "REMOVE" to mute all. "RESET" to clear all (unprogram).
22SECURE_SESSIONGET, SETdata.uint_dataCONTROL for GET, ADMIN for SETeDIDIOAllows you to Get or Set the "Secure Session" status of the device.uint_data.
23NONCEGETdata.string_dataNONEeDIDIOAllows you to request a Nonce to perform a Secure Login.string_data.
24DALI_SENSOR_TYPEGETdali_sensor_typeCONFIGeDIDIOThe type of DALI frame (24 or 25-bit) for eDALI packets to/from motion sensors.
25DEVICE_REBOOTRUNnoneADMINeDIDIO, ADDICTWill reboot the device when used with the 'RUN' AdminCommandType.
26SYSTEM_LOGGINGGET, RESETdata.uint_dataCONFIGeDIDIOWill reset the system logs when used with a 'RESET' AdminCommandType.uint_data.
27SUBNETGET, SETdata.string_dataADMINeDIDIOThe Subnet of the Device.string_data.
28DNSGET, SETdns_serversADMINeDIDIOThe Primary and Secondary DNS, both ways in dns_servers. eDIDIO firmware before 1.6.3 refused a SET with INVALID_PARAMS and answered a GET in the wrong arm - use NETWORK_PROPERTIES (DNS_Primary / DNS_Secondary) for those.
29LINKGET, SETdata.uint_dataADMINeDIDIOWhether or not the UDP Link state is active.uint_data.
30LINK_TYPEGET, SETdata.uint_dataADMINeDIDIOType of Link to enable, based on ReadType.uint_data.
31LINK_MASKGET, SETdata.uint_dataADMINeDIDIOLink Index Mask for above.uint_data.
32LINK_NETMASKGET, SETdata.uint_dataADMINeDIDIONetmask for Link to create Network groups for UDP messaging.uint_data.
33DALI_RX_TOLERANCEGET, SETdata.uint_dataCONFIGeDIDIOThe tolerance for DALI RX (where 10 is 10% above and below nominal half bit time of 416us).uint_data.
34DALI_TX_HALF_BIT_TIMEGET, SETdata.uint_dataCONFIGeDIDIODefault value is 416us.uint_data.
35DMX_TIMINGGET, SETdmx_timing_modeCONFIGeDIDIO, ADDICTDMX Timing (I.e. 44Hz).
36DMX_PROPERTIESGET, SETdmx_line_propsCONFIGeDIDIO, ADDICTDMX Line Properties. Channel Mapping, 16 bit, slot count.
37MEMORY_DIAGNOSTICSGETmemory_diagnosticsCONTROLeDIDIO, ADDICTGET-only. Returns per-task stack high-water-marks, system-stack HWM, and SRAM/CCMRAM static-section usage. Use with the 'GET' AdminCommandType. Used for tuning FreeRTOS task stack sizes and monitoring runtime RAM headroom.
38ETHERNET_DIAGNOSTICSGETethernet_diagnosticsCONTROLeDIDIOGET-only. Returns Ethernet PHY register snapshot, Ethernet MAC counters, resolved link state, and a ring buffer of recent link-state transitions. Use with the 'GET' AdminCommandType. Used to diagnose link/auto-negotiation/duplex-mismatch issues without an SD card.
39LINE_DIAGNOSTICSGETline_diagnosticsCONTROLeDIDIOGET-only. Per-line readout of configured-vs-probed daughterboard type plus a coarse OK/FAULTY/EMPTY/MISCONFIGURED verdict. Briefly perturbs each line (a DALI half-bit pulse and/or a DMX RX-mode window) — fire on demand, not on a hot loop. Use with the 'GET' AdminCommandType.
40TIME_DIAGNOSTICSGETtime_diagnosticsCONTROLeDIDIOGET-only. RTC/NTP/DST observability: LSE crystal ppm measurement, lifetime NTP success/failure counts, last sync details, time-set audit trail, backup-domain boot counter, DST visibility. Use with the 'GET' AdminCommandType.
41RTC_TEMP_COMP_ENABLEDGET, SETdata.uint_dataCONFIGeDIDIOGET/SET. Enable/disable the temperature-driven smooth calibration of the RTC. Persisted in BKPSRAM (reset on battery loss). Default 1.uint_data.
42RTC_PPM_MANUAL_OVERRIDEGET, SETdata.float_dataCONFIGeDIDIOGET/SET. When enabled (override flag in PayloadMessage), the RTC smooth calibration is set to a fixed signed ppm value at every hour boundary, bypassing temp comp. Persisted in BKPSRAM.float_data.
43NTP_FORCE_SYNCRUNnoneCONTROLeDIDIORUN. Triggers an immediate NTP sync attempt.
44NTP_POLL_PERIOD_SECONDSGET, SETdata.uint_dataCONFIGeDIDIOGET/SET. Override the NTP poll period. 0 means use the existing NTP_DETAILS.NTPTimeout from config. Non-zero is persisted in BKPSRAM.uint_data.
45NTP_MAX_ACCEPTABLE_DELTA_SECONDSGET, SETdata.uint_dataCONFIGeDIDIOGET/SET. NTP corrections whose |delta| exceeds this value are rejected (treated as a sanity-check failure). Default 3600 (1 hour). Persisted in BKPSRAM.uint_data.
46TIME_DIAG_MEASURE_LSERUNnoneCONTROLeDIDIORUN. Triggers an on-demand LSE-vs-HSE ppm measurement (~250 ms). Result is cached and returned on the next GET TIME_DIAGNOSTICS.
47BACKUP_DOMAIN_RESET_CANARYRUNnoneCONFIGeDIDIORUN. Resets the boots_since_last_backup_loss counter to 0. Use after a deliberate battery replacement so the counter reflects only post-replacement boots.
48DALI_STATUSGETdali_statusCONTROLeDIDIO, ADDICTGET-only. Returns the DALI system status summary (per-line online/fault device counts, bus-power errors, lowest faulting address, and missing/comms-error device bitmaps) — the same data the on-device Logic system evaluates for "any DALI error" actions. Use with the 'GET' AdminCommandType.
49USER_ACCOUNTSETuser_accountADMINeDIDIOSET-only (ADMIN clearance). Provisions a role's login secret (see AdminUserAccountMessage). Write-only — secrets are never returned by a GET.
50STORAGE_DIAGNOSTICSGETstorage_diagnosticsCONTROLeDIDIOGET-only. Health of the shared SPI storage bus and everything on it: bus stall/reset counters, NOR flash program/erase fault state and presence/identity verdict, and — on variants fitted with an SD card — mount state, probe response, deadline-abort counters and the removal/power-cycle escalation state. Side-effect-free: every value is read from a RAM latch, nothing is probed. Use with the 'GET' AdminCommandType. Not in eDIDIO firmware 1.6.3, which answers UNEXPECTED_TYPE.
51WIFI_SETTINGSGET, SETwifi_settingsNONEADDICTGET/SET. Wi-Fi of a device with an ESP32 co-processor (ADDICT V3): access point only or access point + station, the station network and the access point channel. The station password is write-only - a GET never returns it. A SET replies before the device reconnects its Wi-Fi. See AdminWifiSettingsMessage.
52WIFI_STATUSGETwifi_statusNONEADDICTGET-only. Live Wi-Fi state: station link and IP, the device's own access point (SSID, IP, connected clients) and both MACs. See AdminWifiStatusMessage.
53WIFI_DIAGNOSTICSGETwifi_diagnosticsNONEADDICTGET-only. Wi-Fi link quality (station RSSI, channel, BSSID), co-processor version and restart counters, and command-pipeline health counters. Side-effect-free: every value is cached. See AdminWifiDiagnosticsMessage.

Read types (read_device)

#ReadTypeReplyDevicesDescription
0INPUTSinputseDIDIOThe physical inputs of one profile (profile).
1OUTPUTSoutputseDIDIOThe outputs of one profile (profile).
2IRirseDIDIOThe IR codes of one profile (profile; deprecated).
3SENSORsensoreDIDIOOne sensor (index) of one profile (profile).
5LISTlisteDIDIOOne list (index): its first 32 steps.
7ALARMSalarmseDIDIOEvery alarm.
8BURN_INburn_inseDIDIOEvery burn-in.
9PROJECTAckMessage (INDEX_OUT_OF_BOUNDS)eDIDIONot supported - use AdminMessage SYSTEM_PROPERTIES.
10NETWORKAckMessage (INDEX_OUT_OF_BOUNDS)eDIDIONot supported - use AdminMessage NETWORK_PROPERTIES.
11DEVICEAckMessage (INDEX_OUT_OF_BOUNDS)eDIDIONot supported - use diag_message DIAGNOSTIC_SYSTEM_INFO.
12POLL_DATAAckMessage (INDEX_OUT_OF_BOUNDS)eDIDIONot supported - use diag_message DALI_LEVEL_CACHE.
13LIST_EXTENDEDlist_extendedeDIDIOSteps beyond the first 32 of one list (index), from block secondary_index.
14LOGIClogic_messageeDIDIOEvery logic rule.
15DALI_INPUTSinputs_dalieDIDIOThe DALI inputs of one profile (profile).
16DMX_TRANSLATIONSdmx_translatoreDIDIOEvery DMX to DALI translation object.

Diagnostic types (diag_message)

#DiagnosticMessageTypeReplyDevicesDescription
0DIAGNOSTIC_SYSTEM_INFOdiag_systemeDIDIO, ADDICTCan be used to retrieve a large number of properties that describe the capabilities of the device. (Number of supported Lists, Alarms, etc.).
1DIAGNOSTIC_INPUT_STATUSdiag_systemeDIDIO, ADDICTNot currently supported (will default to SYSTEM_INFO).
2DALI_LEVEL_CACHElevel_cache_response (64 levels of line)eDIDIOCan be used to retrieve the current entries of the in-memory DALI values cache.
3DMX_LEVEL_CACHElevel_cache_response (64 levels of line, from page x 64)eDIDIO, ADDICTCan be used to retrieve the current entries of the in-memory DMX levels cache. Results must be paginated due to size of DMX universe (512).
4ROOM_JOINSAckMessage (INDEX_OUT_OF_BOUNDS)eDIDIORemoved: the "Joined Rooms" state no longer exists.
5DALI_STATUS_CACHElevel_cache_response (64 status bytes of line)eDIDIOCan be used to retrieve the current entries of the in-memory DALI status cache.

EdidioMessage

EdidioMessage

Every message to and from a device is one EdidioMessage carrying exactly one payload. On TCP it is

framed as [0xCD, length MSB, length LSB, protobuf bytes] - the length counts the protobuf bytes only.

Each payload field below says what the device replies ("Reply:"), or that only the device sends it,

and the login role it needs when the device's secure session is on ("Role:"; with it off nothing is

checked). "Devices:" lists the products that handle it; without one it is eDIDIO only.

Retired payload numbers - never reuse: 7 (SensorMultiMessage), 9 (ListMultiMessage),

40 (JoinedRoomsMessage), 55-57 (Spektra show messages).

FieldTypeLabelDescription
message_id uint32

Chosen by the client and echoed in the reply, so replies can be matched to requests. Not unique across clients.

ack AckMessage

The answer to a request that returns no data: success, or why it was refused (type and detail). Sent by the device. Devices: eDIDIO, ADDICT.

inputs InputMultiMessage

Configure the physical inputs of one profile; also the reply to read_device INPUTS. Reply: AckMessage. Role: CONFIG.

outputs OutputMultiMessage

Configure the outputs of one profile; also the reply to read_device OUTPUTS. Reply: AckMessage. Role: CONFIG.

irs IRMultiMessage

Configure the IR codes of one profile (deprecated); also the reply to read_device IR. Reply: AckMessage. Role: CONFIG.

sensor SensorMessage

Configure one DALI-2 sensor; also the reply to read_device SENSOR. Reply: AckMessage. Role: CONFIG.

list ListMessage

Configure a list - up to 32 steps, the rest follow in list_extended; also the reply to read_device LIST. Reply: AckMessage. Role: CONFIG.

alarm AlarmMessage

Configure one alarm (a scheduled action). Reply: AckMessage. Role: CONFIG.

alarms AlarmMultiMessage

Configure every alarm at once; also the reply to read_device ALARMS. Reply: AckMessage. Role: CONFIG.

burn_ins BurnInMultiMessage

Configure the burn-ins; also the reply to read_device BURN_IN. Reply: AckMessage. Role: CONFIG.

sensor_command SensorCommandMessage

Mute, unmute or override a sensor. Reply: AckMessage. Role: CONTROL.

change_profile ChangeProfileMessage

Change the active profile (this resets the sensors). Reply: AckMessage. Role: CONTROL.

identify_message IdentifyMessage

Show information on the device's screen to help find it. Reply: AckMessage. Role: CONTROL.

update_time UpdateTimeMessage

Set the device clock. Reply: AckMessage. Role: CONFIG.

read_device ReadDeviceMessage

Read configuration back; the reply is the payload for the ReadType asked for. Reply: see ReadType. Role: CONTROL.

dali_message DALIMessage

Send a DALI command or query on one or more lines. Reply: AckMessage for a command, dali_query for a query. Role: CONTROL. Devices: eDIDIO, ADDICT.

dali_query DALIQueryResponse

A DALI query's answer, tagged with the line and address. Sent by the device. Devices: eDIDIO, ADDICT.

dmx_message DMXMessage

Set DMX levels on one or more universes, with an optional fade. Reply: AckMessage. Role: CONTROL. Devices: eDIDIO, ADDICT.

external_trigger ExternalTriggerMessage

Fire a trigger action from another system. Reply: AckMessage. Role: CONTROL.

spektra_settings SpektraSettingMessage

Configure a Spektra zone; also the reply to spektra_read SETTINGS. Reply: AckMessage. Role: CONTROL.

spektra_sequence SpektraSequenceConfigMessage

Store a Spektra sequence; also the reply to spektra_read SEQUENCE. Reply: AckMessage. Role: CONTROL.

spektra_calendar SpektraCalendarMessage

Assign a sequence or theme to calendar days. Reply: AckMessage. Role: CONFIG.

spektra_theme SpektraThemeConfigMessage

Store a Spektra theme; also the reply to spektra_read THEME. Reply: AckMessage. Role: CONTROL.

spektra_read SpektraReadMessage

Read Spektra data: SETTINGS gives spektra_settings, SEQUENCE spektra_sequence, THEME spektra_theme, CALENDAR spektra_calendar_overview, LIVE spektra_live, and with manifest set spektra_manifest. Reply: see the type asked for. Role: CONTROL.

spektra_control SpektraControlMessage

Start, stop or pause a sequence or theme, or save the Spektra settings. Reply: AckMessage. Role: CONTROL.

dmx_translator DMXProtocolTranslation

Configure the DMX to DALI translation objects; also the reply to read_device DMX_TRANSLATIONS. Reply: AckMessage. Role: ADMIN.

input_request InputStateMessage

Ask for the live state of the physical inputs. Reply: input_response. Role: CONTROL.

input_response InputStateResponse

The live input state mask. Sent by the device.

diag_system DiagnosticSystemInfoResponse

The device's capabilities, firmware, hardware and protocol version (proto_version): the reply to diag_message DIAGNOSTIC_SYSTEM_INFO. Sent by the device. Devices: eDIDIO, ADDICT.

diag_message DiagnosticMessage

Ask for a diagnostic report; the reply depends on the type asked for. Reply: see DiagnosticMessageType. Role: CONTROL. Devices: eDIDIO, ADDICT.

admin_message AdminMessage

Get, set or run a device property. Reply: admin_message for a GET, else AckMessage. Role: see AdminPropertyType. Devices: eDIDIO, ADDICT.

event EventMessage

ADDICT: a filter starts or stops DALI bus monitoring, and each frame seen arrives as an event. On an eDIDIO, live events are event_stream (77). Reply: AckMessage. Role: NONE. Devices: ADDICT.

secure_device_settings SecureDeviceSettingsMessage

Change the secure-login settings (AES encrypted). Reply: AckMessage. Role: ADMIN.

firmware_new FirmwareMetaMessage

Start a firmware update: describes the image, and erases the one stored. Reply: AckMessage. Role: ADMIN. Devices: eDIDIO, ADDICT.

firmware_control FirmwareControlMessage

Firmware update control (verify, apply, ...) from the client, and the device's verify result. Reply: firmware_control or AckMessage. Role: ADMIN. Devices: eDIDIO, ADDICT.

firmware_chunk FirmwareChunkMessage

One chunk of the firmware image. Reply: AckMessage. Role: ADMIN. Devices: eDIDIO, ADDICT.

level_cache_response LevelCacheResponse

A page of 64 cached DALI or DMX levels: the reply to a diag_message level-cache request. Sent by the device. Devices: eDIDIO, ADDICT.

list_extended ExtendedListMessage

The steps of a list beyond the first 32; also the reply to read_device LIST_EXTENDED. Reply: AckMessage. Role: CONFIG.

ayt_message AytMessage

"Are you there?" keep-alive: send one within 20 s or the connection is closed. Reply: ayt_message. Role: CONTROL. Devices: eDIDIO, ADDICT.

rdm_message RDMMessage

Send an RDM GET or SET to a fixture. Reply: AckMessage, then rdm_response_message. Role: CONTROL. Devices: eDIDIO, ADDICT.

rdm_response_message RDMResponseMessage

A fixture's RDM response. Sent by the device. Devices: eDIDIO, ADDICT.

logic_message LogicMultiMessage

Configure the logic rules; also the reply to read_device LOGIC. Reply: AckMessage. Role: CONFIG.

secure_login AdminSecureLoginMessage

Log in to a role, answering the nonce from AdminMessage NONCE. Reply: AckMessage (detail = the role granted). Role: NONE.

device_state_message DeviceStateMessage

Ask for the live state: uptime, clock, next alarm, inputs, lists and burn-ins. Reply: device_state_message. Role: CONTROL. Devices: eDIDIO, ADDICT.

spektra_calendar_day SpektraCalendarDayMessage

Not sent on its own: a calendar's days arrive inside spektra_calendar_overview. Unused.

spektra_calendar_overview SpektraCalendarOverviewMessage

The calendar: the reply to spektra_read CALENDAR. Sent by the device.

inputs_dali DALIInputMultiMessage

Configure the DALI inputs of one profile; also the reply to read_device DALI_INPUTS. Reply: AckMessage. Role: CONFIG.

logs_read SystemLogReadMessage

Read up to 32 system log entries from a start index. Reply: logs_read. Role: CONFIG.

metadata_read SystemMetaDataReadMessage

Read system metadata for debugging. Reply: metadata_read. Role: CONTROL.

dali_addressing_message DALIAddressingMessage

Run DALI addressing on a line. Reply: dali_addressing_message. Role: CONFIG. Devices: eDIDIO, ADDICT.

dali_remapping_message DALIRemappingMessage

Move DALI devices to other short addresses. Reply: AckMessage. Role: CONFIG. Devices: eDIDIO, ADDICT.

rdm_discovery RDMDiscoveryMessage

Discover the RDM fixtures on a universe. Reply: rdm_discovery_reply. Role: CONFIG. Devices: eDIDIO, ADDICT.

rdm_discovery_reply RDMDiscoveryReplyMessage

Up to 128 discovered RDM fixtures; isNext asks for more. Sent by the device. Devices: eDIDIO, ADDICT.

dali_identify_duplicates DALIIdentifyDuplicatesMessage

Find DALI devices sharing a short address. Reply: dali_identify_duplicates. Role: CONFIG. Devices: eDIDIO, ADDICT.

spektra_live SpektraLiveMessage

What Spektra is playing now, per zone: the reply to spektra_read LIVE. Sent by the device.

sensor_query SensorsQuery

Read the sensors' live state, up to 20 per request (page with offset). Reply: sensor_query. Role: CONTROL.

data_aliases DataAliases

Get or set the names of profiles, inputs, lists, sensors and so on. Reply: data_aliases for a get, AckMessage for a set. Role: CONFIG.

sd_dir_list SdDirListMessage

List an SD card directory, a page at a time (6-pole). Reply: sd_dir_list. Role: CONFIG.

sd_file_read SdFileReadMessage

Read a chunk of a file on the SD card (6-pole). Reply: sd_file_read. Role: CONFIG.

sd_file_write SdFileWriteMessage

Write a chunk of an upload to the SD card (6-pole). Reply: sd_file_write. Role: CONFIG.

sd_file_control SdFileControlMessage

SD card file operations: stat, free space, delete, upload begin / end / abort / resume (6-pole). Reply: sd_file_control. Role: CONFIG.

sd_log_config SdLogConfigMessage

Enable or disable log categories (6-pole). Reply: sd_log_config. Role: CONFIG.

sd_log_stream SdLogStreamMessage

Deprecated. Deprecated: the v1 event stream, replaced by event_stream (77). Tag 69 stays reserved. Unused.

crash_log CrashLogMessage

Read the crash / reset record captured in backup RAM at boot. Reply: crash_log. Role: ADMIN. Devices: eDIDIO, ADDICT.

sd_log_policy SdLogPolicyMessage

Get or set the SD log rotation policy (6-pole). Reply: sd_log_policy. Role: CONFIG.

connection_status ConnectionStatusMessage

The device's client connections: slot counts and per-connection details. Reply: connection_status. Role: ADMIN. Devices: eDIDIO, ADDICT.

provision_get_state ProvisionGetStateMessage

Read the device identity state (all public). Reply: provision_get_state. Role: ADMIN.

provision_install_identity ProvisionInstallIdentityMessage

Install the device identity, in chunks; accepted only while unprovisioned. Reply: provision_install_identity. Role: ADMIN.

provision_pop ProvisionProofOfPossessionMessage

Prove the device holds its key: it signs the nonce sent. Reply: provision_pop. Role: ADMIN.

provision_decommission ProvisionDecommissionMessage

Return the device to unprovisioned. Reply: provision_decommission. Role: ADMIN.

event_stream EventStreamMessage

Subscribe to the live event / log stream; events then arrive as event_stream. Reply: event_stream. Role: CONFIG. Devices: eDIDIO, ADDICT.

spektra_manifest SpektraManifestMessage

Which Spektra slots hold data, with a CRC for each: the reply to spektra_read with manifest set. Sent by the device.

Fields with deprecated option

Name Option
sd_log_stream

true

General

AckMessageType

The result in an AckMessage: SUCCESS, or why the request was not done.

NameNumberDescription
DECODE_FAILED 0

May indicate an issue with the protocol (e.g. a mismatch in expected fields between clients). Ensure both parties are using the latest version.

INDEX_OUT_OF_BOUNDS 1

A resource was requested beyond the amount available.

UNEXPECTED_TYPE 2

The provided message was not able to be handled or processed (likely due to a lack of enough information or incorrect values).

ENCODE_FAILED 3

Not currently in use.

KEY_MISMATCH 4

Not currently in use.

SUCCESS 5

The message was decoded and handled successfully.

INVALID_PARAMS 6

The message was decoded but had invalid data for the intended outcome.

UNEXPECTED_COMMAND 7

The message was decoded but the requested action was not valid for current the state of the device.

COMMUNICATION_FAILED 8

The message could not be received or sent due to an internal issue.

COMMUNICATION_TIMEOUT 9

May indicate contention for a shared resource or that an existing task is taking longer than expected and the latest request has timed-out.

DATA_TOO_LONG 10

May indicate too much data was in the request or the required reply would be too big to handle.

UNEXPECTED_CASE 11

May indicate that the message is out of context (e.g. an "end" command for a process that is not running) or that the message requests a feature that is not yet implemented.

SLOTS_FULL 12

Typically indicates that a request was valid, but the relevant content is "full" and thus elements must be removed before continuing.

UNAUTHORISED 13

The message could not be actioned because the connection has not been authorised.

PARTIAL_SUCCESS 14

Can be returned in the case where some but not all Lines in a line_mask successfully sent

COMMAND_FAILED 15

For whatever reason, the intended command did not complete

DEPRECATED 16

For message which is no longer supported by this Firmware

FORBIDDEN 17

The connection is authenticated but its role lacks the clearance required for this operation (distinct from UNAUTHORISED, which means not authenticated at all).

AckMessage

Sent in Response to another message.

FieldTypeLabelDescription
payload AckMessageType

Will either indicate 'Success' or a particular Error as specified by "AckMessageType"

detail uint32

Optional context. Interpretation depends on payload type: for PARTIAL_SUCCESS on a DALI multi-line command it is the bitmask of lines that succeeded; for an ERROR payload (e.g. INVALID_PARAMS) it is a RejectReason code naming the specific reason (0 = unspecified); for a SUCCESS ack to a secure login it is the granted clearance level (0=NONE, 1=CONTROL, 2=CONFIG, 3=ADMIN).

RejectReason

Refines an ERROR AckMessageType with a specific, machine-readable reason, carried in AckMessage.detail

(detail stays a uint32 - for SUCCESS / PARTIAL_SUCCESS it keeps its existing meaning, e.g. a line bitmask).

0 = unspecified so older firmware (detail defaults to 0) gracefully degrades to the generic ack message.

The CLIENT owns the human-readable strings; this enum is the shared code<->meaning contract so firmware and

app never drift. Values are allocated in 1000-wide blocks per subsystem - add new reasons to the owning

block, never renumber (gaps are free). uint32/varint: a value stays 2 wire-bytes up to 16383, and the field

itself reaches ~4.29e9, so the block scheme is effectively open-ended.

1-999 general / protocol (cross-cutting)

1000-1999 sensors

2000-2999 inputs

3000-3999 outputs

4000-4999 lists

5000-5999 schedules / alarms

6000-6999 zones

7000-7999 sequences / themes / colour

8000-8999 DALI commissioning / addressing

9000-9999 network / config

10000-10999 admin

11000-11999 firmware update / apply

NameNumberDescription
REJECT_UNSPECIFIED 0

No specific reason (older firmware, or a generic reject)

GENERAL_REQUIRES_NEWER_FIRMWARE 1

The controller firmware is older than the requested feature needs

GENERAL_UNSUPPORTED_ON_VARIANT 2

Not supported on this hardware variant

SENSOR_BAD_LINE 1000

V4: a sensor must sit on exactly one valid DALI line

SENSOR_ADDRESS_OUT_OF_RANGE 1001

V4: sensor short address must be 0-63

SENSOR_CONTROL_LINE_INVALID 1002

V4: control line mask falls outside the available lines

SENSOR_CONTROL_TARGET_INVALID 1003

V4: control group/address is out of range

SENSOR_TIMER_OUT_OF_RANGE 1004

V8: a timer value would overflow once stored/scaled

SENSOR_LEGACY_GROUPING 1005

V7': non-zero legacy motion_sensors (an OLD client) - update the app

SENSOR_LEADER_WITHOUT_GROUP 1006

V9: Leader role set without a cooperation group

SENSOR_GROUP_ID_INVALID 1007

V9: cooperation group id is too large

SENSOR_HARVEST_NO_CONTROL_LINE 1008

V1: a daylight-harvesting sensor must drive at least one line

SENSOR_HARVEST_QUERY_ADDR_INVALID 1009

V1: the harvesting seed query address must be a single 0-63 device

SENSOR_HARVEST_NO_SETPOINT 1010

V1: the harvesting setpoint must be greater than 0

SENSOR_GROUP_MIXED_TARGET 1011

V2': ACTIVE members of one group must share the control target

SENSOR_DUPLICATE_ADDRESS 1012

V10: another programmed sensor already uses this (short address, DALI line) - one physical sensor's events would drive multiple slots

FIRMWARE_APPLY_NO_IMAGE 11000

No firmware image is staged in the target slot

FIRMWARE_APPLY_CHECKSUM_FAILED 11001

Staged image failed the XOR checksum verify (corrupt or incomplete upload)

FIRMWARE_APPLY_BAD_STRUCTURE 11002

Staged image geometry is not cleanly flashable (bad/misaligned chunk addressing) - would brick on handoff

FIRMWARE_APPLY_UNSIGNED 11003

No image signature was present - device rejects as unsigned

FIRMWARE_APPLY_SIGNATURE_INVALID 11004

Image signature present but did not verify (wrong key, tampered, or content mismatch)

FIRMWARE_APPLY_INCOMPLETE 11005

A staged chunk could not be read back (blank/unreadable page) even after retries - the staged image is incomplete/corrupt in flash, NOT a geometry problem. Re-upload.

FIRMWARE_UPLOAD_SLOT_NOT_ERASED 11006

Upload: the target page already held DIFFERENT data (the slot was not cleanly erased) - abort and restart the upload

FIRMWARE_UPLOAD_WRITE_FAILED 11007

Upload: the post-write read-back did not match what was sent (flash write did not take) - retry the chunk / upload

FIRMWARE_SESSION_BUSY 11008

Another connection already owns the firmware update session (single-owner) - wait for it to finish or disconnect, then retry

FIRMWARE_APPLY_NO_CONF_KEY 11009

V3: the image is encrypted but the device has no key to decrypt it - provision the device first

FIRMWARE_APPLY_DECRYPT_FAILED 11010

V3: image decryption failed - image not applied

FIRMWARE_APPLY_BOOTLOADER_INCOMPATIBLE 11011

The staged image needs a firmware format this device's bootloader cannot decode - provide a compatible image

PayloadMessage

Contains a payload. Used in multiple message types. Incorrect payload type will result in AckMessage Unexpected Type.

FieldTypeLabelDescription
uint_data uint32

Binary Flags set with 0 (FALSE) and 1 (TRUE)

float_data float

Decimal values (latitude, longitude, UTC offset, ppm)

string_data string

Every PayloadMessage will contain String data, with optional uint or float data

AytMessage

"Are You There" Message with some supplementary values for debugging. "Are you there?" messages should be sent within 20 seconds to maintain a connection. However, any received message will reset this timer.

FieldTypeLabelDescription
timesinceboot uint32

Device uptime in seconds

temperature float

Current Temp on the device internals

time TimeClockMessage

Current Time of the RTC

DeviceStateMessage

This message contains the 'variable state' for the Device

FieldTypeLabelDescription
uptime uint32

Uptime (seconds since boot)

temp float

Temperature

vbat float

Battery voltage

clock TimeClockMessage

RTC Time on device

next_alarm uint32

Index of next alarm

next_alarm_time TimeClockMessage

Time of next alarm

input_state uint32

Input state mask

list_states uint32 repeated

State of each List (DISABLED / ENABLED / LOOPING)

burn_in_states uint32 repeated

State of each Burn-in (RUNNING / NOT RUNNING)

sensor_states uint32 repeated

State of each DALI Sensor (IDLE / DISABLED / WARNING / OCCUPANCY)

zone_states uint32 repeated

State of each Spektra Zone (OFF / SEQUENCE / THEME / STATIC)

zone_sleep_states uint32 repeated

Sleep State of each Spektra Zone (TRUE / FALSE)

zone_indexes uint32 repeated

Index of the selected Sequence, Theme, or Static colour for each Zone

dali_input_state uint64

DALI Input state mask

output_state uint32

Output state mask

Configuration

TriggerOperationType

How an input or output behaves: momentary or latching, and whether it is enabled.

NameNumberDescription
MOMENTARY 0

A Short Press occurs when a button is pressed for less than 250ms (and at least 50ms). A Long Press occurs when a button is pressed for longer than 650ms. Holding the button down will repeat the Long Press action every 400ms.

LATCHING 1

Instantaneous on short to ground (debounced to 50ms). Trigger occurs once upon entering this state (LOW) and once upon leaving this state (HIGH).

MOMENTARY_OUTPUT 2

A temporary output signal

LATCHING_OUTPUT 3

A continuous output signal

ROTARY 4

Rotary device, DALI input device

MOMENTARY_DISABLED 128

Used to track the enabled/disabled state of an I/O

LATCHING_DISABLED 129

Used to track the enabled/disabled state of an I/O

TriggerType

What a trigger does (TriggerMessage.type): set DALI or DMX levels, start or stop lists, sequences and themes, change profiles, control sensors, and so on. target_index and value mean what each type says.

NameNumberDescription
DALI_ARC 0

For controlling DALI Arc Levels (0 to 254) and 255 for MASK

DALI_COMMAND 1

See (https://en.wikipedia.org/wiki/Digital_Addressable_Lighting_Interface#Commands_for_control_gear) for a list of common DALI commands

DMX_CHANNELS_SPLIT_LOW 2

Sets DMX channel directly. Expects 1-based channel number (1-512)

DMX_CHANNELS_SPLIT_HIGH 3

Sets DMX channel directly. Expects 1-based channel number (1-512)

DMX_MULTICAST_CHANNELS_SPLIT_LOW 4

Sets DMX channel relative to the Zone's configured start address. Expects 0-based offset index

DMX_MULTICAST_CHANNELS_SPLIT_HIGH 5

Sets DMX channel relative to the Zone's configured start address. Expects 0-based offset index

DMX_BROADCAST 6

Affects all DMX lights as per the Spektra Settings (number of lights and channels per light)

DIDIO 7

DEPRECATED

FADE_UP_WITH_MIN 8

DALI Fade Up Command - Query level and set Minimum if Off

LIST_START 9

Start a List action once

LIST_START_CONTINUOUS 10

Start a List action with repeat

LIST_STOP 11

Stop a List

SPEKTRA_START_SEQ 12

Start a Spektra Sequence

SPEKTRA_STOP_SEQ 13

Stop a playing Spektra Sequence

SPEKTRA_THEME 14

Apply a Spektra Theme

SPEKTRA_STATIC 15

DEPRECATED

SPEKTRA_SCHEDULE 16

Start the scheduled Spektra item

LINK_START 17

Enables the UDP Link State - If Configured

LINK_STOP 18

Temporarily disables the UDP Link State

STOP_BURN_IN 19

Stop a Burn-In

START_BURN_IN 20

Start a Burn-In

ON_OFF_TOG 21

Turn a Group/Address On/Off based on queried arc level. For DALI_GROUP_ALL (broadcast), uses internal toggle state flag

MIN_MAX_TOG 22

On/Off Toggle replaced by Min/Max

ENABLE_INPUT 23

Enable Input - If latching, Input will trigger immediately based on current state

DISABLE_INPUT 24

Disable Input

ENABLE_TOG_INPUT 25

Toggle Enable/Disable Input

OUTPUT_TOG 26

Toggle Output State between High (~22Vdc) and Low (0Vdc)

OUTPUT_HIGH 27

Set Output HIGH

OUTPUT_LOW 28

Set Output LOW

OUTPUT_TRIG 29

Set Output to trigger momentarily based on configuration

PROFILE_CHANGE 30

Change Profile - This action will reset sensor state

FADE_LONG_PRESS 31

Long Press Fade based on Toggle Flag

SYNCRO 32

Command sets clock to 11:59PM. Used for hardware time update by external Timeclock

PRESET_CODE 33

Preset Code - Executes a predefined action sequence stored on the device (index 0-N based on preset_code_count)

CUSTOM_CODE 34

Project Specific Custom Code - Contact Control Freak for support

SPEKTRA_SLEEP 35

Pause Spektra sequence

SPEKTRA_RESUME 36

Resume Spektra sequence

DEVICE_RESET 37

Admin Command for Hardware Reset

DEVICE_SAVE 38

Admin Command for manual device memory save

USER_LEVEL_STORE_NEW 39

Store Current Level to Variable

USER_LEVEL_SET_DEFAULT 40

Reset User Level Variable

USER_LEVEL_RECALL 41

Recall User Level Variable

ROOM_JOIN 43

DEPRECATED

ROOM_UNJOIN 44

DEPRECATED

TYPE8_TC_WARMER 45

DALI Type 8 Warmer Command. 1 Mirek increments

TYPE8_TC_COOLER 46

DALI Type 8 Cooler Command. 1 Mirek increments

TYPE8_TC_ACTUAL 47

DALI Type 8 Set Colour to Mirek value

LOGIC_OPERATION 48

Execute a conditional logic rule (see LogicMessage)

ALARM_ENABLE 49

Enable Alarm at Index

ALARM_DISABLE 50

Disable Alarm at Index

DALI_CONTROL_SENSOR_OVERRIDE 51

Puts the DALI Sensor in 'override mode', which means it will no longer control the lighting until occupancy has timed-out or control is manually resumed

DALI_CONTROL_SENSOR_TEMP_DISABLE 52

Sets the occupancy timer to zero and puts the DALI Sensor in a temporary 'disable mode' (duration depends on Sensor configuration: 'Disable Period')

DALI_CONTROL_SENSOR_RESUME 53

Takes the DALI Sensor out of 'override mode'

DALI_ARC_OVERRIDE 54

For controlling DALI Arc Levels (0 to 254) and 255 for MASK - Sets associated group to override mode

DALI_COMMAND_OVERRIDE 55

For sending DALI commands - Sets associated group to override mode

FADE_UP_WITH_MIN_OVERRIDE 56

Non-native DALI command override (sets associated group to override mode)

ON_OFF_TOG_OVERRIDE 57

Non-native DALI command override (sets associated group to override mode)

MIN_MAX_TOG_OVERRIDE 58

Non-native DALI command override (sets associated group to override mode)

MAX_OFF_TOG 59

Reserved - Toggle between MAX level and OFF

MAX_OFF_TOG_OVERRIDE 60

Reserved - Toggle between MAX level and OFF with sensor override

FADE_LONG_PRESS_OVERRIDE 61

Non-native DALI command override (sets associated group to override mode)

USER_LEVEL_RECALL_OVERRIDE 62

Non-native DALI command override (sets associated group to override mode)

DMX_ZONE_FADE_UP 63

DMX Spektra Zone Fade UP

DMX_ZONE_FADE_DOWN 64

DMX Spektra Zone Fade DOWN

LOGGING_LEVEL 65

Enable Logging to EEPROM to be read by configurator

SPEKTRA_SHOW_CONTROL 66

DEPRECATED

CIRCADIAN_TEMPERATURE 67

Automatically adjusts DALI Type 8 colour temperature based on time of day (warmer in morning/evening, cooler midday)

DALI_CONTROL_SENSOR_MUTE 68

Mute Sensor at Index (or all with Index 255)

DALI_CONTROL_SENSOR_UNMUTE 69

Unmute to Sensor at Index (or all with Index 255)

SPEKTRA_INTENSITY 70

Allow you to specify the maximum Spektra Sequence or Theme output intensity (10 to 100)%

ENABLE_INPUT_NO_ACTION 71

Allow you to enable an input (Latching), but not trigger the action.

SET_DALI_FADE_TIME 72

Sets the DALI Fade Time

NO_COMMAND 254

This TriggerType should always be at the bottom of the list. Add any new TriggerTypes above it (up to 253).

AlarmRepeatType

Whether an alarm repeats. Which days it runs on comes from repeat_day_bitmask and repeat_month_bitmask.

NameNumberDescription
ALARM_NO_REPEAT 0

Once, on the date in start_time

ALARM_REPEAT_DAILY 1

Repeats - on the weekdays in repeat_day_bitmask and months in repeat_month_bitmask (set all days)

ALARM_REPEAT_WORK_DAY 2

Repeats - on the weekdays in repeat_day_bitmask (set Monday to Friday)

ALARM_REPEAT_WEEKLY 3

Repeats - on the weekday(s) in repeat_day_bitmask

ALARM_REPEAT_MONTHLY 4

Repeats - in the months in repeat_month_bitmask. The firmware treats every type but NO_REPEAT alike: the bitmasks decide

AlarmAstroType

Whether an alarm's start or end is a clock time, or sunrise / sunset with the time as an offset.

NameNumberDescription
ALARM_NO_ASTRO 0

At the clock time given

ALARM_SUNRISE 1

At sunrise (from LATITUDE / LONGITUDE), moved by the time given as an offset

ALARM_SUNSET 2

At sunset, moved by the time given as an offset

LogicComparisonType

How a logic rule compares its variable with comparison_value. It runs trigger A when the comparison holds, else trigger B.

NameNumberDescription
LESS_THAN 0

A runs if the variable < comparison_value, else B

LESS_THAN_OR_EQUALS 1

A runs if the variable <= comparison_value, else B

EQUALS 2

A runs if the variable == comparison_value, else B

MORE_THAN 3

A runs if the variable > comparison_value, else B

MORE_THAN_OR_EQUALS 4

A runs if the variable >= comparison_value, else B

NOT_EQUAL 5

A runs if the variable != comparison_value, else B

BIT_OR 6

A runs if (variable | comparison_value) is non-zero, else B

BIT_AND 7

A runs if (variable & comparison_value) is non-zero - any of the masked bits set - else B

BIT_XOR 8

A runs if (variable ^ comparison_value) is non-zero - they differ - else B

TriggerMessage

Trigger Message Structure. Stores all information for Trigger Type Actions

FieldTypeLabelDescription
type TriggerType

The type of Trigger

zone uint32

Which Zone (Spektra)

line_mask uint32

Which Line(s) to perform this trigger on (if applicable)

target_index uint32

Index to target (context depends on TriggerType)

value uint32

Value for this trigger (if applicable)

query_index uint32

Index to query (if applicable)

TimeClockMessage

Date/Time Message Structure. Year is 0-99. Month is 1 (Jan) - 12 (Dec), Date is day of the month, Day is Weekday with 1 (Monday) - 7 (Sunday)

FieldTypeLabelDescription
date uint32

Year | Month | Date | Day

time uint32

<Empty> | Hour | Minute | Second

BurnInBitsMessage

Message to describe the two Burn-In objects

FieldTypeLabelDescription
light_state uint32

Tracks when a Light is 'On' and "burning in"

running_flag uint32

Whether or not the burn-in is currently counting down

enable_flag uint32

Whether or not the burn-in should count down

IOInputMessage

Message to describe the 12 or 24 Physical Inputs. Not sent natively, see InputMultiMessage

FieldTypeLabelDescription
index uint32

Which Input is this (0 - 11) on 4 Pole and (0 - 23) on 9 Pole

button_state TriggerOperationType

How will this Input be triggered? Momentary (short/long press) or Latching (low/high)

short_press TriggerMessage

What action should occur on short/low

long_press TriggerMessage

What action should occur on long/high

IOOutputMessage

Message to describe the 4 or 8 Physical Outputs. Not sent natively, see OutputMultiMessage

FieldTypeLabelDescription
index uint32

Which Output is this? (0 - 3) on 4 Pole and (0 - 7) on 9 Pole. Note: Actual Pin numbers are (9 - 12) and (21 - 24) respectively.

initial_level uint32

Will the Output be Low or High at startup?

time_trigger_is_active uint32

How long should a 'Trigger Output' command last?

type TriggerOperationType

Is this a continuous (latching) trigger or momentary output?

DALIInputMessage

Message to describe the (Up to) 40 DALI 2 Input Devices. Not sent natively, see DALIInputMultiMessage

FieldTypeLabelDescription
index uint32

Which index for this Input

address uint32

The eDALI Address of this Input

dali_line uint32

The DALI Line this Input is on

button_state TriggerOperationType

How will this Input be triggered? Momentary (short/long press) or Latching (low/high)

short_press TriggerMessage

What action should occur on short/low

long_press TriggerMessage

What action should occur on long/high

instance uint32

What instance of the device? If it has multiple inputs

IOIRMessage

Message to describe the Infrared Input (DEPRECATED)

FieldTypeLabelDescription
index uint32

IR slot, 0-based

action TriggerMessage

The trigger the code fires

codes uint32

The IR code to match

SensorMessage

Message to describe the (Up to) 40 DALI 2 Sensors. Not sent natively, see SensorMultiMessage

FieldTypeLabelDescription
profile uint32

Under which Profile is this Sensor active?

index uint32

The index for this Sensor

sensor_address uint32

The eDALI Address of this Sensor (assumes address of "L" (Light) component with "M" (Motion) at L + 1)

sensor_dali_line uint32

The DALI Line this Sensor is on

address_query uint32

The DALI Address to query for Group-based control

control_dali_line uint32

The DALI Line (mask) to control

control_group uint32

The DALI Group Address to control

light_setpoint uint32

The Lux level to maintain during Daylight Harvesting

warning_setpoint uint32

DEPRECATED (superseded by warning_trigger) - The Arc level to set during the Warning Period

motion_only uint32

Is this Sensor used for motion detection only? If False, Daylight Harvesting will be in effect

timeout_values uint32

Occupancy hold time in MINUTES (firmware multiplies by 60 internally) - duration after last motion detection before entering Warning Period

warning_values uint32

Warning period duration in seconds - time spent in dimmed state before transitioning to Idle/Off

disable_values uint32

Deadtime period in seconds - delay after timeout before the Sensor resumes motion detection

input_1_pm uint32

DEPRECATED - The first Input button used for Two-Button Programming

input_2_pm uint32

DEPRECATED - The second Input button used for Two-Button Programming

sensor_states uint32

DEPRECATED (firmware-internal, not configuration) - Used to keep track of the Motion Sensor state

motion_sensors uint32

DEPRECATED since FW 1.3.0 (Phase 3): legacy 32-bit grouping bitmask. New firmware REJECTS a non-zero value here with INVALID_PARAMS - re-push from an updated SpektraPlus. See coop_group/coop_leader.

lux_sensors uint32

DEPRECATED (firmware-internal, not configuration) - Used to keep track of the Light (Lux) Sensor state

off_flag uint32

DEPRECATED (firmware-internal, not configuration) - Used to keep track of the Control Group's state

is_programmed bool

Set to 'True' when the Firmware receives a SensorMessage with this Index

detection_trigger TriggerMessage

The action to perform upon initial detection

warning_trigger TriggerMessage

The action to perform upon transitioning to the Warning Period

idle_trigger TriggerMessage

The action to perform upon transitioning to the Idle (disable) Period

coop_group uint32

Cooperative directional group ID (1..0x7FFFFFFF; 0 = standalone). Replaces motion_sensors. Members of the same non-zero group cooperate; Leader members propagate occupancy & share lux.

coop_leader uint32

1 = Leader member (its motion keeps the group on; shares the daylight-harvest mean with other Leader members). 0 = Follower (kept on by Leader members; fires its own triggers; harvests its own zone).

SensorQuery

Message to Query running sensor data

FieldTypeLabelDescription
timer uint32

Time Remaining in seconds

light_state uint32

Light Group State

motion_sensor_state uint32

Motion Sensor State

lux_sensor_state uint32

Lux Sensor State

last_lux uint32

Last reported lux (sensor device-relative units, not absolute lux)

last_commanded_arc uint32

Last DALI arc level (0-254) commanded by daylight harvesting

is_group_master bool

TRUE when this sensor is the active controller of its cooperative harvesting group

control_group uint32

Effective control target: group/address the sensor maintains

control_dali_line uint32

Effective control target: DALI line mask the sensor controls

lux_seeded bool

FALSE while the harvest loop is awaiting its first real 304 reading after occupancy (last_lux / last_commanded_arc are still the previous occupancy's values until TRUE)

light_setpoint uint32

The DEVICE-resident daylight-harvest setpoint the loop actually regulates against (active profile). Lets the app draw the set-point line from the device, not its own config, so a device/app divergence is visible.

group_mean_lux uint32

The blended lux the harvest master regulates on (mean of active Leader members of this sensor's cooperative group). Equals last_lux for a standalone/Follower sensor.

SensorsQuery

The sensors' live state, a page of up to 20 at a time: send offset, read sensors and total_count, then ask for the next page.

FieldTypeLabelDescription
sensors SensorQuery repeated

A page of up to 20 SensorQuery entries starting at 'offset' (device holds 40; see nanopb max_count)

offset uint32

Request: absolute index of the first sensor to return (0-based; 0 = first page). Response: echoes the offset of this page so the client can place the entries at absolute slots.

total_count uint32

Response only: total number of sensors on the device. Lets the client page until offset + sensors.length >= total_count. Omitted (0) on older firmware, which returns every sensor in one page.

ListStepMessage

List Step Structure for List Actions

FieldTypeLabelDescription
step_index uint32

Index of Step in List

action TriggerMessage

Action to perform

time_seconds uint32

Time in seconds between steps, uint16_t value

AlarmMessage

Message to describe Scheduled Actions. Not sent natively, see AlarmMultiMessage

FieldTypeLabelDescription
index uint32

Alarm Index from 0 - 9

enabled bool

Enabled Flag - FALSE (0) or TRUE (1)

start_time TimeClockMessage

Time to Start Action, or Astro Offset

end_time TimeClockMessage

Time to Stop Action, or Astro Offset

start_trigger TriggerMessage

Trigger Action to perform at start time

end_trigger TriggerMessage

Trigger Action to perform at end time

astro_start AlarmAstroType

Start Time Type

astro_end AlarmAstroType

End Time Type

repeat AlarmRepeatType

Alarm Repeat Type

repeat_day_bitmask uint32

1 to trigger on this day. LSB (0) = Monday, MSB (6) = Sunday

repeat_month_bitmask uint32

1 to trigger during this month. LSB (0) = January, MSB (11) = December

yearly bool

Should this Alarm happen each year?

start_offset_is_before bool

E.g. 10 minutes BEFORE or AFTER the start astro event?

end_offset_is_before bool

E.g. 10 minutes BEFORE or AFTER the end astro event?

BurnInMessage

Message to describe the two Burn-In Actions. While Burn-In is active, the system will check associated DALI line and group and prevent any action other than 100% or 0%. Any value set over 1% will be forced to 100%. Not sent natively, see BurnInMultiMessage

FieldTypeLabelDescription
index uint32

Burn-in, 0-based

line uint32

DALI line mask the burn-in drives

address uint32

DALI address held at full while burning in (RECALL MAX LEVEL)

query_address uint32

DALI address queried to see whether the lights are on (the timer only runs while they are)

time uint32

Burn-in duration, minutes. Setting it restarts the countdown

remaining uint32

Minutes left (read only)

states BurnInBitsMessage

Its live state

ExternalTriggerMessage

This message will allow an externally connected device to send a Trigger action

FieldTypeLabelDescription
trigger TriggerMessage

Can be used to action Triggers via the network instead of via a hardware input or on-board alarm

InputMultiMessage

Message used to send all Physical Inputs, for a specific profile

FieldTypeLabelDescription
profile uint32

The profile these inputs belong to, 0-based

inputs IOInputMessage repeated

Every physical input, in index order

OutputMultiMessage

Message used to send all Outputs, for a specific profile

FieldTypeLabelDescription
profile uint32

The profile these outputs belong to, 0-based

outputs IOOutputMessage repeated

Every output, in index order

DALIInputMultiMessage

Message used to send all DALI Inputs, for a specific profile

FieldTypeLabelDescription
profile uint32

The profile these DALI inputs belong to, 0-based

input_index_offset uint32

To support paginated results (0-9, 10-19, 20-29, 30-39)

inputs DALIInputMessage repeated

Every DALI input, in index order

IRMultiMessage

DEPRECATED

FieldTypeLabelDescription
profile uint32

The profile these IR codes belong to, 0-based

irs IOIRMessage repeated

Every IR slot, in index order

ListMessage

Message used to send a List. If more than 32 steps in the list, the ExtendedListMessage is used repeatedly to send the remainder.

FieldTypeLabelDescription
list_index uint32

Which list, 0-based

step ListStepMessage repeated

Limited to 32 for this Message Type; you must use ExtendedListMessage to configure more than 32 steps per List

list_state uint32

Typically will be 'DISABLED' to start with (requires a 'START LIST' trigger to begin)

total_step_count uint32

Can be greater than 32, but you must use ExtendedListMessage to send the rest

ExtendedListMessage

This Message must be used when the List has more than 32 steps

FieldTypeLabelDescription
list_index uint32

Which List do these steps belong to?

step_index_offset uint32

0 for the first ExtendedListMessage; offset by 32 for every ExtendedListMessage beyond the first

step ListStepMessage repeated

Up to 32 steps, from step_index_offset

AlarmMultiMessage

Message used to send the Alarms

FieldTypeLabelDescription
alarm AlarmMessage repeated

Every alarm, in index order

BurnInMultiMessage

Message used to send the Burn-Ins

FieldTypeLabelDescription
burnin BurnInMessage repeated

Every burn-in, in index order

LogicMessage

Defines a conditional logic rule that evaluates a condition and executes an action based on the result

FieldTypeLabelDescription
index uint32

Index of this logic rule (0 to logic_count-1)

enabled bool

Whether this logic rule is active

comparison_object TriggerMessage

The source value to evaluate (e.g., DALI level, input state)

comparison_value uint32

The threshold/setpoint value to compare against

comparison_type LogicComparisonType

How to compare: equals, less than, greater than, etc.

actionA TriggerMessage

Action to execute if comparison evaluates to TRUE

actionB TriggerMessage

Action to execute if comparison evaluates to FALSE

LogicMultiMessage

Container for multiple logic rules (used when reading/writing all logic rules at once)

FieldTypeLabelDescription
logic LogicMessage repeated

Array of logic rules (max logic_count entries)

System

ReadType

What a read_device request reads. Each value says which EdidioMessage payload comes back. Also used to say where an event came from.

NameNumberDescription
INPUTS 0

The physical inputs of one profile (profile). Reply: inputs.

OUTPUTS 1

The outputs of one profile (profile). Reply: outputs.

IR 2

The IR codes of one profile (profile; deprecated). Reply: irs.

SENSOR 3

One sensor (index) of one profile (profile). Reply: sensor.

LIST 5

One list (index): its first 32 steps. Reply: list.

ALARMS 7

Every alarm. Reply: alarms.

BURN_IN 8

Every burn-in. Reply: burn_ins.

PROJECT 9

Not supported - use AdminMessage SYSTEM_PROPERTIES. Reply: AckMessage (INDEX_OUT_OF_BOUNDS).

NETWORK 10

Not supported - use AdminMessage NETWORK_PROPERTIES. Reply: AckMessage (INDEX_OUT_OF_BOUNDS).

DEVICE 11

Not supported - use diag_message DIAGNOSTIC_SYSTEM_INFO. Reply: AckMessage (INDEX_OUT_OF_BOUNDS).

POLL_DATA 12

Not supported - use diag_message DALI_LEVEL_CACHE. Reply: AckMessage (INDEX_OUT_OF_BOUNDS).

LIST_EXTENDED 13

Steps beyond the first 32 of one list (index), from block secondary_index. Reply: list_extended.

LOGIC 14

Every logic rule. Reply: logic_message.

DALI_INPUTS 15

The DALI inputs of one profile (profile). Reply: inputs_dali.

DMX_TRANSLATIONS 16

Every DMX to DALI translation object. Reply: dmx_translator.

SensorCommandType

What a SensorCommandMessage does.

NameNumberDescription
INITIALISE 0

Applies default settings to all Sensors (broadcast) and resets their detection state

MUTE 1

Stops a Sensor from sending DALI packets

UNMUTE 2

Allows a Sensor to send DALI packets

OVERRIDE 3

Puts a Sensor in 'Override Mode' which prevents it from adjusting the Light Level (until after the occupancy timeout occurs)

IDENTIFY 4

Starts the 'Identify' behaviour of a Sensor (typically this involves rapid flashing of the status LED for several seconds)

SensorCommandMessage

Message used to send specific sensor commands, such as Mute, Unmute and Override. Mute will stop the sensor from talking until; Unmute, Profile Change, or Program. Override will prevent the sensor from changing the currently selected level until it has timed-out

FieldTypeLabelDescription
command uint32

DEPRECATED: Use 'type' instead

index uint32

Which sensor, 0-based (INITIALISE ignores it: it is broadcast)

type SensorCommandType

What to do

ChangeProfileMessage

Message used to change Profiles. Note that changing the profile will cause the sensors to reset

FieldTypeLabelDescription
profile uint32

The profile to make active, 0-based

IdentifyMessage

Message used to show information on screen to aid with physical identification

FieldTypeLabelDescription
MAC uint64

Not used: the device shows its own name, IP and MAC

IP uint64

Not used: the device shows its own name, IP and MAC

UpdateTimeMessage

Message to update the device time. Message will be affected by Day Light Savings (If selected) and will refresh currently selected schedules

FieldTypeLabelDescription
time TimeClockMessage

The new date and time (local time)

ReadDeviceMessage

Message used to request device information, such as inputs, lists, sensors, etc

FieldTypeLabelDescription
profile uint32

Profile to read, for INPUTS, DALI_INPUTS, OUTPUTS, IR and SENSOR

type ReadType

What to read - each ReadType says which payload comes back

index uint32

Which item, for SENSOR, LIST and LIST_EXTENDED

secondary_index uint32

For LIST_EXTENDED: which block of steps after the first 32

SecureDeviceSettingsMessage

Message used to send a secure login settings message. AES Encryption Required

FieldTypeLabelDescription
payload string

Encrypted payload of a PB message.

DALI

Type8CommandType

Standard DALI Type 8 Commands - See DALI Standard

NameNumberDescription
SET_TEMP_X_COORD 0

IEC 62386-209 command 224: SET TEMPORARY X-COORDINATE (DTR1:DTR0)

SET_TEMP_Y_COORD 1

IEC 62386-209 command 225: SET TEMPORARY Y-COORDINATE (DTR1:DTR0)

ACTIVATE 2

IEC 62386-209 command 226: ACTIVATE - apply the temporary colour

X_COORD_STEP_UP 3

Activate Not Required

X_COORD_STEP_DOWN 4

Activate Not Required

Y_COORD_STEP_UP 5

Activate Not Required

Y_COORD_STEP_DOWN 6

Activate Not Required

SET_TEMP_COLOUR_TEMPERATURE 7

DTR1 | DTR as Mirek Value

COLOUR_TEMPERATURE_STEP_COOLER 8

Activate Not Required

COLOUR_TEMPERATURE_STEP_WARMER 9

Activate Not Required

SET_TEMP_PRI_N_DIMLEVEL 10

IEC 62386-209 command 234: SET TEMPORARY PRIMARY N DIMLEVEL (DTR1:DTR0, primary N in DTR2)

SET_TEMP_RGB_DIMLEVEL 11

IEC 62386-209 command 235: SET TEMPORARY RGB DIMLEVEL (DTR0, DTR1, DTR2)

SET_TEMP_WAF_DIMLEVEL 12

IEC 62386-209 command 236: SET TEMPORARY WAF DIMLEVEL (DTR0, DTR1, DTR2)

SET_TEMP_RGBWAF_CONTROL 13

IEC 62386-209 command 237: SET TEMPORARY RGBWAF CONTROL (DTR0)

COPY_REPORT_TEMPORARY 14

IEC 62386-209 command 238: COPY REPORT TO TEMPORARY

STORE_TY_PRI_N 16

IEC 62386-209 command 240: STORE TY PRIMARY N (DTR1:DTR0, N in DTR2)

STORE_XY_COORD_PRI_N 17

IEC 62386-209 command 241: STORE XY-COORDINATE PRIMARY N (N in DTR2)

STORE_COLOUR_TEMPERATURE_LIMIT 18

IEC 62386-209 command 242: STORE COLOUR TEMPERATURE TC LIMIT (DTR1:DTR0, which limit in DTR2)

STORE_GEAR_FEATURES_STATUS 19

IEC 62386-209 command 243: STORE GEAR FEATURES / STATUS (DTR0)

ASSIGN_COLOR_LINKED_CH 21

IEC 62386-209 command 245: ASSIGN COLOUR TO LINKED CHANNEL (DTR0)

START_AUTO_CAL 22

IEC 62386-209 command 246: START AUTO CALIBRATION

ENABLE_DEVICE_TYPE8 48

ENABLE DEVICE TYPE 8 (special command C1 08) - sent before each DT8 command

SET_XY_COORDINATE 50

Manufacturer Specific combined XY command

Type8QueryType

Standard DALI Type 8 Queries - See DALI Standard

NameNumberDescription
TYPE8_QUERY_NULL 0

Required as the first "default" element for the Protocol. Will not perform any action.

TYPE8_QUERY_GEAR_FEATURES_STATUS 1

247

TYPE8_QUERY_COLOUR_STATUS 2

248

TYPE8_QUERY_COLOUR_TYPE_FEATURES 3

249

TYPE8_QUERY_COLOUR_VALUE 4

250

TYPE8_QUERY_RGBWAF_CONTROL 5

251

TYPE8_QUERY_ASSIGNED_COLOUR 6

252

TYPE8_QUERY_EXT_VERSION_NUM 8

254

DALI24DeviceSetting

Standard DALI 24 Bit Commands - See DALI Standard

NameNumberDescription
COMMAND_IDENTIFY 0

IEC 62386-103 opcode 0x00: IDENTIFY DEVICE

COMMAND_RESET_POWER_CYCLE_SEEN 1

IEC 62386-103 opcode 0x01: RESET POWER CYCLE SEEN

COMMAND_RESET 16

IEC 62386-103 opcode 0x10: RESET

COMMAND_RESET_MEMORY_BANK 17

IEC 62386-103 opcode 0x11: RESET MEMORY BANK (DTR0)

COMMAND_SET_SHORT_ADDRESS 20

IEC 62386-103 opcode 0x14: SET SHORT ADDRESS (DTR0)

COMMAND_ENABLE_WRITE_MEMORY 21

IEC 62386-103 opcode 0x15: ENABLE WRITE MEMORY

COMMAND_ENABLE_APP_CONTROLLER 22

IEC 62386-103 opcode 0x16: ENABLE APPLICATION CONTROLLER

COMMAND_DISABLE_APP_CONTROLLER 23

IEC 62386-103 opcode 0x17: DISABLE APPLICATION CONTROLLER

COMMAND_SET_OPERATING_MODE 24

IEC 62386-103 opcode 0x18: SET OPERATING MODE (DTR0)

COMMAND_ADD_TO_DEVICE_GROUPS_0_15 25

IEC 62386-103 opcode 0x19: ADD TO DEVICE GROUPS 0-15 (DTR2:DTR1)

COMMAND_ADD_TO_DEVICE_GROUPS_15_32 26

IEC 62386-103 opcode 0x1A: ADD TO DEVICE GROUPS 16-31 (DTR2:DTR1)

COMMAND_REMOVE_FROM_GROUPS_0_15 27

IEC 62386-103 opcode 0x1B: REMOVE FROM DEVICE GROUPS 0-15 (DTR2:DTR1)

COMMAND_REMOVE_FROM_GROUPS_16_32 28

IEC 62386-103 opcode 0x1C: REMOVE FROM DEVICE GROUPS 16-31 (DTR2:DTR1)

COMMAND_START_QUIESCENT_MODE 29

IEC 62386-103 opcode 0x1D: START QUIESCENT MODE

COMMAND_STOP_QUIESCENT_MODE 30

IEC 62386-103 opcode 0x1E: STOP QUIESCENT MODE

COMMAND_ENABLE_POWER_CYCLE_NOTIF 31

IEC 62386-103 opcode 0x1F: ENABLE POWER CYCLE NOTIFICATION

COMMAND_DISABLE_POWER_CYCLE_NOTIF 32

IEC 62386-103 opcode 0x20: DISABLE POWER CYCLE NOTIFICATION

COMMAND_SAVE_PERSISTENT_VARIABLES 33

IEC 62386-103 opcode 0x21: SAVE PERSISTENT VARIABLES

SET_EVENT_PRIORITY 97

IEC 62386-103 opcode 0x61: instance command SET EVENT PRIORITY (DTR0)

ENABLE_INSTANCE 98

IEC 62386-103 opcode 0x62: instance command ENABLE INSTANCE

DISABLE_INSTANCE 99

IEC 62386-103 opcode 0x63: instance command DISABLE INSTANCE

SET_PRIMARY_INSTANCE_GROUP 100

IEC 62386-103 opcode 0x64: instance command SET PRIMARY INSTANCE GROUP (DTR0)

SET_INSTANCE_GROUP_1 101

IEC 62386-103 opcode 0x65: instance command SET INSTANCE GROUP 1 (DTR0)

SET_INSTANCE_GROUP_2 102

IEC 62386-103 opcode 0x66: instance command SET INSTANCE GROUP 2 (DTR0)

SET_EVENT_SCHEME 103

IEC 62386-103 opcode 0x67: instance command SET EVENT SCHEME (DTR0)

SET_EVENT_FILTER 104

IEC 62386-103 opcode 0x68: instance command SET EVENT FILTER (DTR2:DTR1:DTR0)

DALI24InstanceType

Standard DALI 24 Bit Instance Types - See DALI Standard

NameNumberDescription
DEFAULT 0

Not an instance type: no instance selected

INPUT 1

IEC 62386-301 push button

ROTARY_INPUT 2

IEC 62386-302 absolute input (slider, rotary, switch)

MOTION_SENSOR 3

IEC 62386-303 occupancy sensor

LIGHT_SENSOR 4

IEC 62386-304 light sensor

DALI24OpCode

Standard DALI 24 Bit Device Op Codes - See DALI Standard

NameNumberDescription
OPCODE_NULL 0

No Action

SENSOR_MOTION_SET_HOLD_TIMER 33

Motion Sensor

SENSOR_MOTION_SET_REPORT_TIMER 34

IEC 62386-303 SET REPORT TIMER (DTR0)

SENSOR_MOTION_SET_DEADTIME_TIMER 35

IEC 62386-303 SET DEADTIME TIMER (DTR0)

SENSOR_MOTION_CANCEL_HOLD_TIMER 36

IEC 62386-303 CANCEL HOLD TIMER

SENSOR_LIGHT_SET_REPORT_TIMER 48

Light Sensor

SENSOR_LIGHT_SET_HYSTERESIS 49

IEC 62386-304 SET HYSTERESIS (DTR0)

SENSOR_LIGHT_SET_DEADTIME_TIMER 50

IEC 62386-304 SET DEADTIME TIMER (DTR0)

SENSOR_LIGHT_SET_HYSTERESIS_MIN 51

IEC 62386-304 SET HYSTERESIS MIN (DTR0)

DALIQueryType

Standard DALI Queries - See DALI Standard

NameNumberDescription
DALI_QUERY_NULL 0

Required as the first "default" element for the Protocol. Will not perform any action.

DALI_QUERY_STATUS 144

IEC 62386-102 command 144: QUERY STATUS (see DALIStatusType)

DALI_QUERY_BALLAST 145

IEC 62386-102 command 145: QUERY CONTROL GEAR PRESENT

DALI_QUERY_LAMP_FAILURE 146

IEC 62386-102 command 146: QUERY LAMP FAILURE

DALI_QUERY_LAMP_POWER_ON 147

IEC 62386-102 command 147: QUERY LAMP POWER ON

DALI_QUERY_LIMIT_ERROR 148

IEC 62386-102 command 148: QUERY LIMIT ERROR

DALI_QUERY_RESET_STATE 149

IEC 62386-102 command 149: QUERY RESET STATE

DALI_QUERY_MISSING_SHORT_ADDRESS 150

IEC 62386-102 command 150: QUERY MISSING SHORT ADDRESS

DALI_QUERY_VERSION_NUMBER 151

IEC 62386-102 command 151: QUERY VERSION NUMBER

DALI_QUERY_DTR0 152

IEC 62386-102 command 152: QUERY CONTENT DTR0

DALI_QUERY_DEVICE_TYPE 153

IEC 62386-102 command 153: QUERY DEVICE TYPE

DALI_QUERY_PHYSICAL_MIN 154

IEC 62386-102 command 154: QUERY PHYSICAL MINIMUM

DALI_QUERY_POWER_FAILURE 155

IEC 62386-102 command 155: QUERY POWER FAILURE

DALI_QUERY_DTR1 156

IEC 62386-102 command 156: QUERY CONTENT DTR1

DALI_QUERY_DTR2 157

IEC 62386-102 command 157: QUERY CONTENT DTR2

DALI_QUERY_OPERATING_MODE 158

IEC 62386-102 command 158: QUERY OPERATING MODE

DALI_QUERY_LIGHTSOURCE_TYPE 159

IEC 62386-102 command 159: QUERY LIGHT SOURCE TYPE

DALI_QUERY_ACTUAL_LEVEL 160

IEC 62386-102 command 160: QUERY ACTUAL LEVEL

DALI_QUERY_MAX_LEVEL 161

IEC 62386-102 command 161: QUERY MAX LEVEL

DALI_QUERY_MIN_LEVEL 162

IEC 62386-102 command 162: QUERY MIN LEVEL

DALI_QUERY_POWER_ON_LEVEL 163

IEC 62386-102 command 163: QUERY POWER ON LEVEL

DALI_QUERY_SYSTEM_FAILURE_LEVEL 164

IEC 62386-102 command 164: QUERY SYSTEM FAILURE LEVEL

DALI_QUERY_FADETIME_FADERATE 165

IEC 62386-102 command 165: QUERY FADE TIME / FADE RATE

DALI_QUERY_MANUFACTURER_SPECIFIC_MODE 166

IEC 62386-102 command 166: QUERY MANUFACTURER SPECIFIC MODE

DALI_QUERY_NEXT_DEVICE_TYPE 167

IEC 62386-102 command 167: QUERY NEXT DEVICE TYPE

DALI_QUERY_EXTENDED_FADE_TIME 168

IEC 62386-102 command 168: QUERY EXTENDED FADE TIME

DALI_QUERY_CONTROL_GEAR_FAILURE 170

IEC 62386-102 command 170: QUERY CONTROL GEAR FAILURE

DALI_QUERY_SCENE_X_LEVEL 176

IEC 62386-102 command 176: QUERY SCENE LEVEL 0 (add the scene number for scenes 1-15)

DALI_QUERY_GROUPS_0_7 192

IEC 62386-102 command 192: QUERY GROUPS 0-7

DALI_QUERY_GROUPS_8_15 193

IEC 62386-102 command 193: QUERY GROUPS 8-15

DALI_QUERY_RANDOM_ADDRESS_H 194

IEC 62386-102 command 194: QUERY RANDOM ADDRESS (H)

DALI_QUERY_RANDOM_ADDRESS_M 195

IEC 62386-102 command 195: QUERY RANDOM ADDRESS (M)

DALI_QUERY_RANDOM_ADDRESS_L 196

IEC 62386-102 command 196: QUERY RANDOM ADDRESS (L)

DALI_QUERY_READ_DTR_0_1 197

IEC 62386-102 command 197: READ MEMORY LOCATION (DTR1 bank, DTR0 location)

DALI_QUERY_APP_EXT_COMMANDS 224

IEC 62386-102 command 224: the first application extended command (device-type specific; DT8 queries are DALIMessage.type8_reply)

DALI_QUERY_EXT_VERSION_NUMBER 255

IEC 62386-102 command 255: QUERY EXTENDED VERSION NUMBER (of the device type selected with ENABLE DEVICE TYPE). An ordinary query, not a special command

DALI_QUERY_COMPARE 260

IEC 62386-102 special command COMPARE (frame A9 00). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit_reply.

DALI_QUERY_VERIFY_SHORT_ADDRESS 268

IEC 62386-102 special command VERIFY SHORT ADDRESS (frame B9 xx). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit_reply.

DALI_QUERY_SHORT_ADDRESS 269

IEC 62386-102 special command QUERY SHORT ADDRESS (frame BB 00). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit_reply.

DALICommandType

Standard DALI Commands - See DALI Standard

NameNumberDescription
DALI_OFF 0

IEC 62386-102 command 0: OFF

DALI_FADE_UP 1

IEC 62386-102 command 1: UP - fade up for 200 ms at the fade rate

DALI_FADE_DOWN 2

IEC 62386-102 command 2: DOWN - fade down for 200 ms at the fade rate

DALI_STEP_UP 3

IEC 62386-102 command 3: STEP UP

DALI_STEP_DOWN 4

IEC 62386-102 command 4: STEP DOWN

DALI_MAX_LEVEL 5

IEC 62386-102 command 5: RECALL MAX LEVEL

DALI_MIN_LEVEL 6

IEC 62386-102 command 6: RECALL MIN LEVEL

DALI_STEP_DOWN_OFF 7

IEC 62386-102 command 7: STEP DOWN AND OFF

DALI_ON_STEP_UP 8

IEC 62386-102 command 8: ON AND STEP UP

DALI_ENABLE_DAPC_SEQ 9

IEC 62386-102 command 9: ENABLE DAPC SEQUENCE

DALI_RECALL_LAST_ACTIVE_LEVEL 10

IEC 62386-102 command 10: GO TO LAST ACTIVE LEVEL

DALI_CONTINUOUS_UP 11

IEC 62386-102 command 11: CONTINUOUS UP

DALI_CONTINUOUS_DOWN 12

IEC 62386-102 command 12: CONTINUOUS DOWN

DALI_RECALL_SCENE_0 16

IEC 62386-102 command 16: GO TO SCENE 0

DALI_RECALL_SCENE_1 17

IEC 62386-102 command 17: GO TO SCENE 1

DALI_RECALL_SCENE_2 18

IEC 62386-102 command 18: GO TO SCENE 2

DALI_RECALL_SCENE_3 19

IEC 62386-102 command 19: GO TO SCENE 3

DALI_RECALL_SCENE_4 20

IEC 62386-102 command 20: GO TO SCENE 4

DALI_RECALL_SCENE_5 21

IEC 62386-102 command 21: GO TO SCENE 5

DALI_RECALL_SCENE_6 22

IEC 62386-102 command 22: GO TO SCENE 6

DALI_RECALL_SCENE_7 23

IEC 62386-102 command 23: GO TO SCENE 7

DALI_RECALL_SCENE_8 24

IEC 62386-102 command 24: GO TO SCENE 8

DALI_RECALL_SCENE_9 25

IEC 62386-102 command 25: GO TO SCENE 9

DALI_RECALL_SCENE_10 26

IEC 62386-102 command 26: GO TO SCENE 10

DALI_RECALL_SCENE_11 27

IEC 62386-102 command 27: GO TO SCENE 11

DALI_RECALL_SCENE_12 28

IEC 62386-102 command 28: GO TO SCENE 12

DALI_RECALL_SCENE_13 29

IEC 62386-102 command 29: GO TO SCENE 13

DALI_RECALL_SCENE_14 30

IEC 62386-102 command 30: GO TO SCENE 14

DALI_RECALL_SCENE_15 31

IEC 62386-102 command 31: GO TO SCENE 15

DALI_RESET 32

IEC 62386-102 command 32: RESET

DALI_STORE_ACTUAL_LEVEL_DTR0 33

IEC 62386-102 command 33: STORE ACTUAL LEVEL IN DTR0

DALI_SAVE_PERSISTENT_VARS 34

IEC 62386-102 command 34: SAVE PERSISTENT VARIABLES

DALI_SET_OPERATING_MODE 35

IEC 62386-102 command 35: SET OPERATING MODE (DTR0)

DALI_RESET_MEMORY_BANK 36

IEC 62386-102 command 36: RESET MEMORY BANK (DTR0)

DALI_IDENTIFY_DEVICE 37

IEC 62386-102 command 37: IDENTIFY DEVICE

DALI_SET_MAX_LEVEL 42

IEC 62386-102 command 42: SET MAX LEVEL (DTR0)

DALI_SET_MIN_LEVEL 43

IEC 62386-102 command 43: SET MIN LEVEL (DTR0)

DALI_SET_SYSTEM_FAILURE_LEVEL 44

IEC 62386-102 command 44: SET SYSTEM FAILURE LEVEL (DTR0)

DALI_SET_POWER_ON_LEVEL 45

IEC 62386-102 command 45: SET POWER ON LEVEL (DTR0)

DALI_SET_FADE_TIME 46

IEC 62386-102 command 46: SET FADE TIME (DTR0)

DALI_SET_FADE_RATE 47

IEC 62386-102 command 47: SET FADE RATE (DTR0)

DALI_SET_EXT_FADE_TIME 48

IEC 62386-102 command 48: SET EXTENDED FADE TIME (DTR0)

DALI_SET_SCENE_0 64

IEC 62386-102 command 64: SET SCENE 0 (DTR0)

DALI_SET_SCENE_1 65

IEC 62386-102 command 65: SET SCENE 1 (DTR0)

DALI_SET_SCENE_2 66

IEC 62386-102 command 66: SET SCENE 2 (DTR0)

DALI_SET_SCENE_3 67

IEC 62386-102 command 67: SET SCENE 3 (DTR0)

DALI_SET_SCENE_4 68

IEC 62386-102 command 68: SET SCENE 4 (DTR0)

DALI_SET_SCENE_5 69

IEC 62386-102 command 69: SET SCENE 5 (DTR0)

DALI_SET_SCENE_6 70

IEC 62386-102 command 70: SET SCENE 6 (DTR0)

DALI_SET_SCENE_7 71

IEC 62386-102 command 71: SET SCENE 7 (DTR0)

DALI_SET_SCENE_8 72

IEC 62386-102 command 72: SET SCENE 8 (DTR0)

DALI_SET_SCENE_9 73

IEC 62386-102 command 73: SET SCENE 9 (DTR0)

DALI_SET_SCENE_10 74

IEC 62386-102 command 74: SET SCENE 10 (DTR0)

DALI_SET_SCENE_11 75

IEC 62386-102 command 75: SET SCENE 11 (DTR0)

DALI_SET_SCENE_12 76

IEC 62386-102 command 76: SET SCENE 12 (DTR0)

DALI_SET_SCENE_13 77

IEC 62386-102 command 77: SET SCENE 13 (DTR0)

DALI_SET_SCENE_14 78

IEC 62386-102 command 78: SET SCENE 14 (DTR0)

DALI_SET_SCENE_15 79

IEC 62386-102 command 79: SET SCENE 15 (DTR0)

DALI_REMOVE_FROM_SCENE_0 80

IEC 62386-102 command 80: REMOVE FROM SCENE 0

DALI_REMOVE_FROM_SCENE_1 81

IEC 62386-102 command 81: REMOVE FROM SCENE 1

DALI_REMOVE_FROM_SCENE_2 82

IEC 62386-102 command 82: REMOVE FROM SCENE 2

DALI_REMOVE_FROM_SCENE_3 83

IEC 62386-102 command 83: REMOVE FROM SCENE 3

DALI_REMOVE_FROM_SCENE_4 84

IEC 62386-102 command 84: REMOVE FROM SCENE 4

DALI_REMOVE_FROM_SCENE_5 85

IEC 62386-102 command 85: REMOVE FROM SCENE 5

DALI_REMOVE_FROM_SCENE_6 86

IEC 62386-102 command 86: REMOVE FROM SCENE 6

DALI_REMOVE_FROM_SCENE_7 87

IEC 62386-102 command 87: REMOVE FROM SCENE 7

DALI_REMOVE_FROM_SCENE_8 88

IEC 62386-102 command 88: REMOVE FROM SCENE 8

DALI_REMOVE_FROM_SCENE_9 89

IEC 62386-102 command 89: REMOVE FROM SCENE 9

DALI_REMOVE_FROM_SCENE_10 90

IEC 62386-102 command 90: REMOVE FROM SCENE 10

DALI_REMOVE_FROM_SCENE_11 91

IEC 62386-102 command 91: REMOVE FROM SCENE 11

DALI_REMOVE_FROM_SCENE_12 92

IEC 62386-102 command 92: REMOVE FROM SCENE 12

DALI_REMOVE_FROM_SCENE_13 93

IEC 62386-102 command 93: REMOVE FROM SCENE 13

DALI_REMOVE_FROM_SCENE_14 94

IEC 62386-102 command 94: REMOVE FROM SCENE 14

DALI_REMOVE_FROM_SCENE_15 95

IEC 62386-102 command 95: REMOVE FROM SCENE 15

DALI_ADD_TO_GROUP_0 96

IEC 62386-102 command 96: ADD TO GROUP 0

DALI_ADD_TO_GROUP_1 97

IEC 62386-102 command 97: ADD TO GROUP 1

DALI_ADD_TO_GROUP_2 98

IEC 62386-102 command 98: ADD TO GROUP 2

DALI_ADD_TO_GROUP_3 99

IEC 62386-102 command 99: ADD TO GROUP 3

DALI_ADD_TO_GROUP_4 100

IEC 62386-102 command 100: ADD TO GROUP 4

DALI_ADD_TO_GROUP_5 101

IEC 62386-102 command 101: ADD TO GROUP 5

DALI_ADD_TO_GROUP_6 102

IEC 62386-102 command 102: ADD TO GROUP 6

DALI_ADD_TO_GROUP_7 103

IEC 62386-102 command 103: ADD TO GROUP 7

DALI_ADD_TO_GROUP_8 104

IEC 62386-102 command 104: ADD TO GROUP 8

DALI_ADD_TO_GROUP_9 105

IEC 62386-102 command 105: ADD TO GROUP 9

DALI_ADD_TO_GROUP_10 106

IEC 62386-102 command 106: ADD TO GROUP 10

DALI_ADD_TO_GROUP_11 107

IEC 62386-102 command 107: ADD TO GROUP 11

DALI_ADD_TO_GROUP_12 108

IEC 62386-102 command 108: ADD TO GROUP 12

DALI_ADD_TO_GROUP_13 109

IEC 62386-102 command 109: ADD TO GROUP 13

DALI_ADD_TO_GROUP_14 110

IEC 62386-102 command 110: ADD TO GROUP 14

DALI_ADD_TO_GROUP_15 111

IEC 62386-102 command 111: ADD TO GROUP 15

DALI_REMOVE_FROM_GROUP_0 112

IEC 62386-102 command 112: REMOVE FROM GROUP 0

DALI_REMOVE_FROM_GROUP_1 113

IEC 62386-102 command 113: REMOVE FROM GROUP 1

DALI_REMOVE_FROM_GROUP_2 114

IEC 62386-102 command 114: REMOVE FROM GROUP 2

DALI_REMOVE_FROM_GROUP_3 115

IEC 62386-102 command 115: REMOVE FROM GROUP 3

DALI_REMOVE_FROM_GROUP_4 116

IEC 62386-102 command 116: REMOVE FROM GROUP 4

DALI_REMOVE_FROM_GROUP_5 117

IEC 62386-102 command 117: REMOVE FROM GROUP 5

DALI_REMOVE_FROM_GROUP_6 118

IEC 62386-102 command 118: REMOVE FROM GROUP 6

DALI_REMOVE_FROM_GROUP_7 119

IEC 62386-102 command 119: REMOVE FROM GROUP 7

DALI_REMOVE_FROM_GROUP_8 120

IEC 62386-102 command 120: REMOVE FROM GROUP 8

DALI_REMOVE_FROM_GROUP_9 121

IEC 62386-102 command 121: REMOVE FROM GROUP 9

DALI_REMOVE_FROM_GROUP_10 122

IEC 62386-102 command 122: REMOVE FROM GROUP 10

DALI_REMOVE_FROM_GROUP_11 123

IEC 62386-102 command 123: REMOVE FROM GROUP 11

DALI_REMOVE_FROM_GROUP_12 124

IEC 62386-102 command 124: REMOVE FROM GROUP 12

DALI_REMOVE_FROM_GROUP_13 125

IEC 62386-102 command 125: REMOVE FROM GROUP 13

DALI_REMOVE_FROM_GROUP_14 126

IEC 62386-102 command 126: REMOVE FROM GROUP 14

DALI_REMOVE_FROM_GROUP_15 127

IEC 62386-102 command 127: REMOVE FROM GROUP 15

DALI_SET_SHORT_ADDRESS 128

IEC 62386-102 command 128: SET SHORT ADDRESS (DTR0)

DALI_ENABLE_WRITE_MEMORY 129

IEC 62386-102 command 129: ENABLE WRITE MEMORY

DALI_TERMINATE 255

IEC 62386-102 special command TERMINATE (frame A1 00). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit.

DALI_INITIALISE 258

IEC 62386-102 special command INITIALISE (frame A5 xx). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit.

DALI_RANDOMISE 259

IEC 62386-102 special command RANDOMISE (frame A7 00). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit.

DALI_WITHDRAW 261

IEC 62386-102 special command WITHDRAW (frame AB 00). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit.

DALI_SEARCH_ADDR_H 264

IEC 62386-102 special command SEARCHADDRH (frame B1 xx). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit.

DALI_SEARCH_ADDR_M 265

IEC 62386-102 special command SEARCHADDRM (frame B3 xx). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit.

DALI_SEARCH_ADDR_L 266

IEC 62386-102 special command SEARCHADDRL (frame B5 xx). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit.

DALI_PROGRAM_SHORT_ADDRESS 267

IEC 62386-102 special command PROGRAM SHORT ADDRESS (frame B7 xx). The device sends it as that frame, with arg as the data byte (eDIDIO 1.6.3, ADDICT 3.9.3). Earlier firmware sent only the value's low byte - for those, send the frame with frame_16_bit.

CustomDALICommandType

Non-native DALI Commands provided as quality-of-life functions.

NameNumberDescription
DALI_ARC_LEVEL 0

DALI Arc level (0 - 254)

DALI_DAPC_LEVEL 1

Runs a DALI_ENABLE_DAPC_SEQUENCE if needed. // DEPRECATED

DALI_GROUP_ARC_LEVEL 2

Specified by Group ID (0 - 15) // DEPRECATED

DALI_BROADCAST_SCENE 3

No specific Address required, sent to all Devices // DEPRECATED

DALI_SCENE_ON_GROUP 4

Specified by Group ID (0 - 15) // DEPRECATED

DALI_SCENE_ON_ADDRESS 5

Specified by Address (0 - 63) // DEPRECATED

DALI_QUERY_MULTI_TYPES 6

Query multi-device types, returned as a bitmask

DALIStatusType

DALI status query response bitmask values - See DALI Standard

IEC 62386-102 control-GEAR status byte (reply to the 16-bit QUERY STATUS, for lamps/drivers).

NOTE: this is NOT the IEC 62386-103 control-DEVICE deviceStatus (reply to the 24-bit QUERY DEVICE STATUS

used for input devices/sensors). For a SENSOR power cycle, powerCycleSeen is deviceStatus bit5 (0x20), not

the bit7 (=128) below.

NameNumberDescription
LAMP_OFF 0

Not technically in DALI. But this is the default when mask = 0b00000000

CONTROL_GEAR_FAILURE 1

Bit 0: control gear failure

LAMP_FAILURE 2

Bit 1: lamp failure

LAMP_ON 4

Bit 2: lamp on (arc power above 0)

LIMIT_ERROR 8

Bit 3: limit error - the last level asked for was outside min / max

FADE_RUNNING 16

Bit 4: a fade is running

RESET_STATE 32

Bit 5: in the reset state

SHORT_ADDRESS 64

Bit 6: short address is MASK (no short address)

POWER_CYCLE_SEEN 128

Bit 7: power cycle seen since the last reset

DALIRXStatusFlag

DALI Receive Flag

NameNumberDescription
WAITING 0

Internal Idle State - Should not be received

RECEIVING_FRAME 1

DALI Frame being Received

NO_RECEIVED_FRAME 2

Frame was recorded - Empty Data

RECEIVED_8_BIT_FRAME 3

Frame was recorded - 8 Bit Reply

RECEIVED_16_BIT_FRAME 4

Frame was recorded - 16 Bit - Standard Message

RECEIVED_24_BIT_FRAME 5

Frame was recorded - 24 Bit - eDALI Message

RECEIVED_PARTIAL_FRAME 6

Frame was recorded - Unusual Bit count

IDLE 7

DALI System Idle

CALIBRATION 8

Inhouse DALI Calibration

ERROR_WHILE_SENDING 254

Error while trying to Transmit DALI - Possibly no Bus Power

ERROR_WHILE_RECEIVING 255

Error while trying to Receive - Invalid Frame Data, or no response

DTRPayloadMessage

DALI DTR Message structure.

FieldTypeLabelDescription
dtr uint32 repeated

For DALI, you can use 2 bytes, for eDALI 3. Format - DTR0 | DTR1 << 8 | DTR2 << 16

DALIMessage

Message to send a DALI command using various DALI frame types.

FieldTypeLabelDescription
line_mask uint32

Binary mask; e.g. selecting line 1 out of 4 looks like 0b0001. For non queries, line_mask can contain multiple valid lines

address uint32

DALI Address

frame_25_bit uint32

Older eDALI commands are manufacturer specific, so we have to take a raw value.

frame_25_bit_reply uint32

Older eDALI commands can have a reply.

command DALICommandType

A standard DALI command (IEC 62386-102) to address. From DALI_TERMINATE (255) up the values are special commands, sent without an address; a value there that is not one is refused with INVALID_PARAMS (eDIDIO 1.6.3, ADDICT 3.9.3)

custom_command CustomDALICommandType

A command the device builds itself (arc level, fade, ...), with arg

query DALIQueryType

A standard DALI query to address; the reply is dali_query. Above DALI_QUERY_EXT_VERSION_NUMBER (255) the values are special queries, sent without an address; a value there that is not one is refused with INVALID_PARAMS (eDIDIO 1.6.3, ADDICT 3.9.3)

type8 Type8CommandType

A DT8 colour command; the device sends ENABLE DEVICE TYPE 8 and the DTRs first

frame_16_bit uint32

Standard DALI Frame data - Don't use arg

frame_16_bit_reply uint32

Standard DALI Frame data with reply - Don't use arg

frame_24_bit uint32

Standard 24 Bit DALI Frame data - Don't use arg

frame_24_bit_reply uint32

Standard 24 Bit DALI Frame data with reply - Don't use arg

type8_reply Type8QueryType

A DT8 colour query; the reply is dali_query

device24_setting DALI24DeviceSetting

Settings for DALI 24 Bit Devices

arg uint32

Context-dependent value: scene number (0-15), arc level (0-254), XY coordinates packed as (X << 16) | Y, or a special command's data byte as sent on the bus (INITIALISE: 0x00 all, 0xFF unaddressed, 0AAAAAA1 one device; SEARCHADDR H / M / L: the byte; PROGRAM / VERIFY SHORT ADDRESS: 0AAAAAA1, 0xFF to delete)

dtr DTRPayloadMessage

DTR0 / DTR1 / DTR2 values written before the command

instance_type DALI24InstanceType

Instance for 24 bit device - Commands are sent via Type

op_code DALI24OpCode

OpCode for 24 bit device

send_twice bool

Should this command be sent twice on the DALI Line(s)?

DALIStatusFlagMessage

Message reply for DALI Status Flag

FieldTypeLabelDescription
flags DALIStatusType repeated

The status bits that are set

DALIQueryResponse

DALI Response is tagged with the line and DALI address.

FieldTypeLabelDescription
status_flags DALIStatusFlagMessage

Deprecated: the answer to QUERY STATUS as flags

data PayloadMessage

Deprecated: the answer byte in data.uint_data

dali_flag DALIRXStatusFlag

New Query Method

response_data PayloadMessage

The answer byte in response_data.uint_data, when dali_flag says one was received

DALIAddressingError

DALI Response for Addressing Error

NameNumberDescription
NO_ERROR 0

Device found and Addressed

VERIFY 1

Device was found, address was set, but verification failed

SEARCH 2

Device was found, issue with long address

NO_NEW_DEVICE 3

No device found

DALIAddressingType

DALI Addressing Type

NameNumberDescription
ADDRESS_NEW 0

Only Address New devices which have their address set to MASK (255)

READDRESS_ALL 1

Address everything on the line (Standard or 24 bit) - USE CAREFULLY

DALIAddressingMessage

Message to invoke DALI Addressing

FieldTypeLabelDescription
type DALIAddressingType

New or All

initialisation bool

First Address (TRUE) or Next Address (FALSE)

line_mask uint32

Line to Address - Must be singular

is24Bit bool

24 Bit DALI (TRUE) or Standard (FALSE)

error DALIAddressingError

Response -> Error while Addressing

index uint32

Response -> Index of Set Address

DALIRemappingMessage

Message to invoke DALI remapping

FieldTypeLabelDescription
from_address uint32

DALI Address to change

to_address uint32

New address for device. If populated, this address will change to the from_address

line_mask uint32

Affected DALI Line

is24Bit bool

24 bit DALI (TRUE) or Standard (FALSE)

DALIAddressableObject

A DALI device: its line and short address.

FieldTypeLabelDescription
line uint32

Which DALI Line is this Device on?

address uint32

What is the Short Address of this Device?

DALIIdentifyDuplicatesMessage

Find DALI devices that may share a short address. Send line_mask (and is24Bit); the reply lists the suspects.

FieldTypeLabelDescription
line_mask uint32

Which DALI Line(s) to check

is24Bit bool

Use 24-bit DALI (DALI v2) or standard 16-bit DALI if FALSE

possible_duplicates DALIAddressableObject repeated

A collection of DALI Devices which *may* be using duplicated Short Addresses

DMX

DMXMessage

Message to send DMX on requested DMX line(s)

FieldTypeLabelDescription
zone uint32

For Spektra (default of 0 is fine if not applicable)

universe_mask uint32

Which DMX Universes to apply the values to. Specified as a binary mask. Can be sent to multiple.

channel uint32

The actual channel number (not zero-based index)

repeat uint32

The number of times to repeat the data given (e.g. start from DMX channel 30 and set the RGB channel values (levels) of the next 3 lights, so repeat would be 3 with 3 levels provided)

level uint32 repeated

The actual channel values/levels to send

fade_time_by_10ms uint32

The DMX Fade Task runs every 10ms, so a value of 25 will fade over 250ms

RDM

RDMMessage

Message to send a DMX command with/without a response (Getset)

FieldTypeLabelDescription
universe_mask uint32

Universe Mask - Must be a single universe.

uid uint64

UID of device to send the message to. Can be Multi/Broadcast

pid uint32

RDM PID - See Standard

getset uint32

Expects [DMX_RDM_GET_COMMAND = 0x20] or [DMX_RDM_SET_COMMAND = 0x30]

datalength uint32

Length of Data to send

data uint32 repeated

Data

RDMResponseMessage

RDM Response message - source UID, PID, datalength and data

FieldTypeLabelDescription
uid uint64

UID of requested device

pid uint32

Message PID

datalength uint32

Length of Data to receive

data uint32 repeated

Data

RDMDiscoveryMessage

RDM Discovery Message - Invokes Discovery with reply as RDMDiscoveryReplyMessage. isNext flag allows for more than 128 devices to be discovered in additional messages.

FieldTypeLabelDescription
universe_mask uint32

Universe Mask - Must be a single universe

isNext bool

If true, RDM module will search for additional or 'next' 128 RDM devices. If false (empty), RDM module will re-init search for up to 128 devices

RDMDiscoveryReplyMessage

RDM Discovery Reply with up to 128 devices

FieldTypeLabelDescription
discovery_count uint32

How many UIDs were found in total

uid uint64 repeated

The RDM UIDs (48-bit) found, up to 128 per reply

error_code uint32

Non-zero if discovery failed

Spektra

SpektraTargetType

Which kind of Spektra data a request or action is about.

NameNumberDescription
SETTINGS 0

A zone's settings (SpektraSettingMessage)

SEQUENCE 1

A stored sequence

THEME 2

A stored theme

STATIC 3

DEPRECATED

CALENDAR 4

The calendar

SHOW 5

DEPRECATED

LIVE 6

Live Update of the Spektra settings

SpektraActionType

What to do with a sequence or theme (SpektraControlMessage).

NameNumberDescription
START 0

Start playing

STOP 1

Stop

PAUSE 2

Pause, keeping the current colours

SAVE 3

Save the Spektra data (settings, calendar) to non-volatile memory

SpektraUnscheduledBehaviourType

What a Spektra zone does on a day the calendar gives it nothing.

NameNumberDescription
RUN_RANDOM_COLOURED_SEQUENCE 0

Unless otherwise specified, this is a rotate sequence with random colours rotating every 5 seconds

RUN_SEQUENCE_1 1

Can be used to set a 'Default Sequence' with a known pattern and colour combination

RESUME_PREVIOUS 2

Resume the last Sequence or Theme that Spektra had active

RUN_THEME_1 3

Resume to Theme 1

RUN_SHOW_1 4

Resume to Show 1

DO_NOTHING 254

Left as the last possible type, fill between 0 and 253 as necessary

LineAddressingType

How DMX addresses count across lines.

NameNumberDescription
INDEPENDENT 0

Control Lines are independently addressed (e.g. DMX 1 to 512 per line)

CONSECUTIVE 1

Control Lines are consecutively addressed (e.g. DMX 1 to 512 on the first line, 513 to 1024 on the next, etc.)

SpektraTransitionType

How a sequence moves from one colour to the next.

NameNumberDescription
BLEND 0

Blended colour transitions. Example: Transition between red and green will go through yellow.

SNAP 1

Instant colour transitions.

FADE_TO_BLACK 2

Example: Transition between red and green will fade the light off then on between colours. Not currently supported.

SpektraSettingMessage

Message for Spektra Setting Information

FieldTypeLabelDescription
zone uint32

Determine Spektra zone from 0-9

start_address uint32

DMX or DALI Start Address. Typically RED on the first fixture.

line_or_universe_mask uint32

Which DALI Line(s) or DMX Universe(s) to control

protocol uint32

E.g. DMX or DALI

number_of_lights uint32

Number of DALI or DMX fixtures connected. If more than available channels, the 'consecutive' option can be selected which will use multiple lines, starting from the first line specified above

channels_per_light uint32

E.g. 4 for RGBW

channel_colours uint32 repeated

What colour is assigned to each channel (e.g. Red, Green, etc.)

unscheduled_behaviour SpektraUnscheduledBehaviourType

0 = Random colours rotate sequence, 1 = Run default sequence (seq 1)

channel_mapping uint32 repeated

Channel mapping for DALI or future DMX virtual 'grouping'

line_addressing LineAddressingType

Independent or Consecutive

zone_scale_factor float

Zone Scale Factor - Float 0 to 1.0f

SpektraColourConfigMessage

Spektra Colour Channel Config Structure

FieldTypeLabelDescription
channel_value uint32 repeated

Include as many values as there are channels, e.g. [0, 255, 0] would be Green for an RGB light (3 channel values)

SpektraSequenceConfigMessage

Spektra Sequence Configuration Message. Up to 144 sequences can be stored

FieldTypeLabelDescription
index uint32

Index of sequence - 0 to 143

type uint32

BLEND / SIMPLE CHASE / SHADOW CHASE / COMET / ROTATE / TWINKLE / BUILD-UP / CRASH / FIREWORKS

transition SpektraTransitionType

BLEND / SNAP / FADE_TO_BLACK

fade_time_by_10ms uint32

Correlates to blend transitions

time_per_colour uint32

How long each colour should be shown

time_per_colour_unit uint32

MILLISECONDS / SECONDS / MINUTES / HOURS

time_per_step uint32

How long each sequence type 'animation' takes (e.g. speed of the chase)

time_per_step_unit uint32

MILLISECONDS / SECONDS / MINUTES / HOURS

range uint32

Number of lights per repeating segment. 0 = no segmentation (all lights as one group). Values > 0 divide lights into groups of this size for pattern repetition

colour uint64 repeated

DEPRECATED - Use the 'colours' field (SpektraColourConfigMessage array) instead

is_randomised_type uint32

Will randomly select (from random_types_mask) one of the Sequence Types

random_types_mask uint32

A bitmask of Sequence Types

is_reverse_direction uint32

Animate the sequence in reverse light order

is_cycle_direction uint32

Animate the sequence in alternating light order from forward to reverse

title string

The name of the Sequence

has_random_colour_order bool

Randomly pick the next colour out of the chosen colours

colours SpektraColourConfigMessage repeated

The colours used in the Sequence

args uint32 repeated

Function specific arguments * 5

SpektraCalendarMessage

Message to define Spektra Calendar message. Zone options available in SpektraSettingsMessage to define what will happen if no action is scheduled on a calendar day.

FieldTypeLabelDescription
type SpektraTargetType

Spektra Type (e.g. Sequence or Theme)

index uint32

Index (i.e. which Sequence or Theme)

days bool repeated

Boolean array to specify when this Target Index is active (up to the number of days in a year)

isOverride bool

Boolean isOverride. If override, only run once

SpektraCalendarDayMessage

Spektra Calendar Day Structure

FieldTypeLabelDescription
day_index uint32

Index of this day (0 to 365, 366 days total)

type SpektraTargetType

Spektra Type for this day (e.g. Sequence or Theme)

target_index uint32

Index of the specified Type (i.e. which Sequence or Theme)

isOverride bool

Boolean isOverride. If override, only run once

SpektraCalendarOverviewMessage

Message to handle Spektra Calendar Read - This is the reply message to the read request

FieldTypeLabelDescription
day_offset uint32

Offset to start counting days from (0 is the first day of the year)

days SpektraCalendarDayMessage repeated

Schedule information for each day; supports up to 90 days per Message

SpektraThemeConfigMessage

Message to define Spektra Theme. Up to 16 Themes

FieldTypeLabelDescription
index uint32

Theme slot, 0-based

colour uint64 repeated

DEPRECATED - Use the 'colours' field (SpektraColourConfigMessage array) instead

title string

The name of the Theme

colours SpektraColourConfigMessage repeated

The colours used in the Theme (will repeat colours if less colours than lights)

SpektraReadMessage

Message to request Spektra Data

FieldTypeLabelDescription
type SpektraTargetType

What to read; with manifest set, SEQUENCE or THEME

index uint32

Slot index; when manifest = true, the manifest page number

manifest bool

TRUE = reply with a SpektraManifestMessage for 'type' instead of one slot. Additive: firmware below the manifest floor ignores this field and replies with slot 'index', so a client MUST gate on firmware version AND check that the reply actually carries spektra_manifest.

SpektraManifestMessage

Compact summary of which slots of a Spektra slot table hold data, and a change

token for each. Reply to a SpektraReadMessage with manifest = true.

Lets a client read only the slots that exist instead of polling every slot: a

site with 8 sequences goes from 143 round trips to 1 + 8. That matters most on

the transports where it hurts most - mobile/VPN links, and TLS.

NOT an atomic snapshot: the device reads the slot table a sector at a time and

releases its flash lock between sectors, so a write that lands mid-scan may or

may not be reflected. That is correct for a change detector; do not treat the

manifest as a transactional view.

FieldTypeLabelDescription
type SpektraTargetType

SEQUENCE or THEME - which slot table this describes

slot_offset uint32

First slot index this page covers

slot_count uint32

Slots this page covers, occupied or not

is_last_page bool

TRUE on the final page of the table

index uint32 repeated

Occupied slot indices, ascending

crc fixed32 repeated

CRC-32 of each slot's stored page, aligned 1:1 with 'index'. Opaque change token: equal CRC means the stored bytes did not change. WIRE INVARIANT: index count == crc count; a receiver that sees otherwise must discard the message.

SpektraControlMessage

Message to control the Spektra Module

FieldTypeLabelDescription
type SpektraTargetType

Spektra Target Type - Sequence/Theme

zone uint32

Zone (0 to 9) or Zones (255) to control

index uint32

Index of Action. I.e. Sequence 5

action SpektraActionType

Type of Action. Start/Resume/Stop

SpektraLiveMessage

What Spektra is doing right now, one entry per zone in every repeated field: the reply to spektra_read LIVE.

FieldTypeLabelDescription
type SpektraTargetType repeated

Target Type Per Zone (Sequence/Theme etc)

index uint32 repeated

Target Index Per Zone

action SpektraActionType repeated

Target Action Per Zone

step_index uint32 repeated

Current Step

step_index_direction uint32 repeated

Forwards/Backwards (If Cycling)

colour_index uint32 repeated

Current State of Colour Index (Changes over time)

colour_range uint32 repeated

Current State of Colour Range (Changes based on Sequence Step)

random_seq_type uint32 repeated

Currently Active Random Sequence Type

zone_active bool repeated

Flag to show if any channel in this zone is active

DMX to DALI translation

DMXTranslationObject

Structure to describe the DMX to DALI translation

FieldTypeLabelDescription
line_in uint32

DMX IN - Must configure line as DMX IN

line_out uint32

DALI OUT

dmx_start_address uint32

DMX Start Address

channel_count uint32

DMX Count

dali_array uint32 repeated

DALI Addresses

affected_input uint32

Bitmask of affected inputs

blocking bool

If TRUE (1), the inputs will be ignored if the internal DMX receiving flag is TRUE

enabled bool

Translation object is enabled (1) or disabled (0)

index uint32

Index of Translation Object

DMXProtocolTranslation

Message to describe the DMX to DALI translation objects. For a 4 line controller, up to 3 objects can be created allowing for single/multi line translation to single/multi line out.

FieldTypeLabelDescription
object DMXTranslationObject repeated

Typically 1 for a 4 Pole device but can be more for 9 Pole eDIDIO

Diagnostics

LineType

What is fitted on a control line (a daughterboard slot).

NameNumberDescription
LINE_EMPTY 0

No Hardware in this slot

LINE_DALI 1

Physical DALI Board in this slot

LINE_DMX 2

Physical DMX Board in this slot

LINE_DMX_IN 3

Physical DMX Board in this slot - Must be set in the case of DMX to DALI Translation.

LINE_AUTO 4

Line will be determined from physical hardware - Do not use for DMX to DALI Translation

DiagnosticMessageType

Which report a diag_message asks for. Each value says what comes back.

NameNumberDescription
DIAGNOSTIC_SYSTEM_INFO 0

Can be used to retrieve a large number of properties that describe the capabilities of the device. (Number of supported Lists, Alarms, etc.). Reply: diag_system. Devices: eDIDIO, ADDICT.

DIAGNOSTIC_INPUT_STATUS 1

Not currently supported (will default to SYSTEM_INFO). Reply: diag_system. Devices: eDIDIO, ADDICT.

DALI_LEVEL_CACHE 2

Can be used to retrieve the current entries of the in-memory DALI values cache. Reply: level_cache_response (64 levels of line).

DMX_LEVEL_CACHE 3

Can be used to retrieve the current entries of the in-memory DMX levels cache. Results must be paginated due to size of DMX universe (512). Reply: level_cache_response (64 levels of line, from page x 64). Devices: eDIDIO, ADDICT.

ROOM_JOINS 4

Removed: the "Joined Rooms" state no longer exists. Reply: AckMessage (INDEX_OUT_OF_BOUNDS).

DALI_STATUS_CACHE 5

Can be used to retrieve the current entries of the in-memory DALI status cache. Reply: level_cache_response (64 status bytes of line).

InputStateMessage

Structure of Input state mask when InputStateResponse message is sent. 1 is HIGH, 0 is LOW. GPIO are configured as default HIGH. If not connected, a momentary input will return TRUE (1)

FieldTypeLabelDescription
use_mask bool

Reply with a mask rather than a list of active inputs.

InputStateResponse

Message containing the InputStateMessage mask

FieldTypeLabelDescription
inputs uint32 repeated

Contains Inputs that are Low (i.e. currently active)

input_mask uint32

Usage is determined by "InputStateMessage: use_mask"

LevelCacheResponse

Message that contains DALI polled levels. Levels are split into pages of 64 values

DALI/DMX agnostic.

FieldTypeLabelDescription
levels uint32 repeated

Repeated Level array

line uint32

Requested Line

page uint32

Page of requested information

AliasCommandType

Command type for reading or writing user-defined names (aliases) for device elements

NameNumberDescription
GET_ALIASES 0

Retrieve stored aliases from the device

SET_ALIASES 1

Save new aliases to the device

ProfileAliases

User-defined names for profiles (max profile_count entries)

FieldTypeLabelDescription
profiles string repeated

One name per profile, in index order

InputAliases

User-defined names for physical inputs (max input_count entries)

FieldTypeLabelDescription
inputs string repeated

One name per physical input, in index order

OutputAliases

User-defined names for physical outputs (max output_count entries)

FieldTypeLabelDescription
outputs string repeated

One name per output, in index order

ListAliases

User-defined names for lists (max list_count entries)

FieldTypeLabelDescription
lists string repeated

One name per list, in index order

SensorAliases

User-defined names for sensors (max 40 entries)

FieldTypeLabelDescription
sensors string repeated

One name per sensor, in index order

DaliInputAliases

User-defined names for DALI input devices (max input_dali_count entries)

FieldTypeLabelDescription
dali_inputs string repeated

One name per DALI input, in index order

ScheduleAliases

User-defined names for schedules/alarms (max alarm_count entries)

FieldTypeLabelDescription
schedules string repeated

One name per alarm (schedule), in index order

DataAliases

Container for getting or setting user-defined aliases. Only one alias type can be sent per message.

FieldTypeLabelDescription
command AliasCommandType

GET_ALIASES to read, SET_ALIASES to write

profiles ProfileAliases

Profile names

inputs InputAliases

Physical input names

outputs OutputAliases

Output names

lists ListAliases

List names

sensors SensorAliases

Sensor names

dali_inputs DaliInputAliases

DALI input names

schedules ScheduleAliases

Alarm (schedule) names

DiagnosticSystemInfoResponse

Message to request system information. Contains vital information about connected devices configuration capabilities, as well as firmware and hardware version.

FieldTypeLabelDescription
firmware string

Firmware Version number

hardware string

Hardware Version number

error string

Any populated Error message

input_count uint32

Number of supported Inputs

output_count uint32

Number of supported Outputs

ir_count uint32

Number of supported IR codes

list_step_count uint32

Number of supported List Steps

list_count uint32

Number of supported Lists

alarm_count uint32

Number of supported Alarms (Schedules)

burnin_count uint32

Number of supported Burn-ins

spektra_seq_count uint32

Number of supported Spektra Sequences

spektra_seq_step_count uint32

Number of supported Spektra Sequence Steps

spektra_theme_count uint32

Number of supported Spektra Themes

spektra_static_count uint32

Number of supported Spektra Static Colours

proto_version uint32

Protocol version = ProtocolVersion_PROTOCOL_VERSION_CURRENT, byte-packed 0x00_MM_mm_PP (e.g. 0x010301 = 1.3.1)

line_count uint32

Number of supported Control Lines (for DMX, DALI)

lines LineType repeated

Denotes what control type is assigned to each line (e.g. DMX, DALI)

profile_count uint32

Number of supported Profiles

preset_code_count uint32

Number of supported Preset Codes

user_level_count uint32

Number of supported User Levels

dmx_to_dali_count uint32

Number of supported DMX to DALI Translations

spektra_zone_count uint32

Number of supported Spektra Zones

logic_count uint32

Number of supported Logic Mappings

input_dali_count uint32

Number of supported DALI Inputs

vendor_id string

Vendor ID - "Control Freak"

selected_profile uint32

Currently Selected Profile

bootloader string

Bootloader Version number (if applicable)

commit_hash string

Git commit hash from the build system

build_date string

Build date/time string (e.g. "Apr 8 2026 14:30:00")

has_confidentiality_key bool

TRUE if the device can accept an encrypted (V3) firmware image. Lets the updater gate the V3 option. Older firmware omits it -> decodes as false.

DiagnosticMessage

Request a diagnostic response message of a given type.

FieldTypeLabelDescription
type DiagnosticMessageType

Which report; each DiagnosticMessageType says what comes back

page uint32

Allow paging of results, eg. 32 DMX levels per page, 16 pages.

line uint32

If a line/DMX universe needs to be indicated it can go here.

Admin

DALISensorType

Which frames the device uses to talk to its DALI sensors.

NameNumberDescription
EDALI_25_BIT 0

25-bit frame type for a vendor-specific pre-configured sensor

DEFAULT_DALI_2 1

The default 24-bit DALI 2 frames

AdminProjectPropertiesMessage

Message to get or set Admin Properties in reference to project information.

FieldTypeLabelDescription
device_name string

As shown on the Network (in Spektra/Configurator Discovery)

project_name string

For project documentation

longitude float

For astronomical calculations (e.g. sunrise/sunset)

latitude float

For astronomical calculations (e.g. sunrise/sunset)

local_offset float

For astronomical calculations (e.g. sunrise/sunset)

daylight_savings bool

For astronomical calculations (e.g. sunrise/sunset)

daylight_savings_start uint32

Can be used to state when DST is active from

daylight_savings_end uint32

Can be used to state when DST is active to

poll_active uint32

Should the device be polling the DALI line to cache arc levels. If not 0, it is the polling interval in seconds

AdminConfigStatusMessage

Message to get or set Admin Properties in reference to the device configuration

FieldTypeLabelDescription
list_status uint32 repeated

State of each List (DISABLED / ENABLED / LOOPING)

burn_in_status uint32 repeated

State of each Burn-in (RUNNING / NOT RUNNING)

alarm_status uint32

Currently Selected Alarm (i.e. 'next Alarm')

alarm_time_from_reg TimeClockMessage

Time for next Alarm as per RTC Register

sensor_status uint32 repeated

State of each DALI Sensor (IDLE / DISABLED / WARNING / OCCUPANCY)

AdminNetworkPropertiesMessage

Message to get or set Admin Properties in reference to the network connection. Will require a device reboot to update - Used with AdminMessage

FieldTypeLabelDescription
DHCP bool

Should DHCP be used? If False, the static IP will be used instead

IP string

A static IP to use if DHCP is False

MAC string

The MAC Address of this Device

gateway string

The Gateway IP for the network this Device is on

NTPServer string

The NTP Server address from RTC updates over the network

NTP bool

Should NTP be used to keep the RTC up-to-date via network requests

error string

Error or Status Message 32 char

NTPTimeout uint32

Timeout in seconds for NTP Retry

subnet string

The Subnet if set by Static IP

DNS_Primary string

Primary DNS

DNS_Secondary string

Secondary DNS

AdminDNSServersMessage

Message to set the DNS Server - Used with AdminMessage

FieldTypeLabelDescription
DNS_Primary string

Primary DNS

DNS_Secondary string

Secondary DNS

AdminControllerLinesMessage

Message to set the Type of Controller lines - Used with AdminMessage

FieldTypeLabelDescription
lines LineType repeated

Used to set the control type on each control line (e.g. DMX / DALI)

AdminDeviceStatusMessage

Message to get device temperature and battery - Used with AdminMessage

FieldTypeLabelDescription
temperature float

The current device chip temperature

battery float

The current battery voltage (3.3V battery)

AdminSecureLoginMessage

Message to enable/disable the Secure Login functionality

FieldTypeLabelDescription
username string

Which username to login as ("control" / "config" / "admin"; 3rd party vendors may have a built-in alias for the admin role)

cnonce string

The nonce generated by the client attempting to login

hash uint32 repeated

The login response digest, as 32 repeated byte (0-255) elements (decoded as raw bytes).

AuthRole

Which role a per-role login secret belongs to. Hierarchical clearance: ADMIN includes CONFIG includes CONTROL.

NameNumberDescription
ROLE_CONTROL 0

Drive outputs, run sequences/scenes, read state/diagnostics

ROLE_CONFIG 1

+ edit inputs/schedules/sensors/lists/logic/alarms/addressing

ROLE_ADMIN 2

+ network/firmware/provisioning/secure-session/resets/accounts

AdminUserAccountMessage

Provisions a role's login secret. Used with AdminMessage (USER_ACCOUNT, SET, ADMIN clearance).

Write-only: the device never returns a secret. An all-zero secret clears (un-provisions) that role.

FieldTypeLabelDescription
role AuthRole

Which role's secret to set

secret bytes

32-byte login secret (all-zero = clear/UNSET)

AdminDALISensorTypeMessage

Message to set the DALI sensor messaging type (24 or 25 bit DALI) - Used with AdminMessage

FieldTypeLabelDescription
type DALISensorType

Which type of eDALI will the eDIDIO use to decode & encode Sensor packets?

DMXTimingMode

DMX512 timing modes as defined by ESTA for Relaxed DMX Timing. Affects refresh rate and compatibility with fixtures

NameNumberDescription
DMX_TIMING_FAST 0

Fastest refresh rate, may have compatibility issues with some fixtures

DMX_TIMING_MEDIUM 1

Balanced timing for most fixtures

DMX_TIMING_SLOW 2

Slower timing for maximum fixture compatibility

DMX_TIMING_NORMAL 3

Standard DMX512 timing per ESTA specification

AdminDMXGlobalTimingConfig

Global DMX Timing

FieldTypeLabelDescription
mode DMXTimingMode

Applies to all lines

AdminDMXLineParameters

Per-line DMX output configuration

FieldTypeLabelDescription
line_index uint32

DMX line / universe index (0-based)

output_slot_count uint32

Number of DMX slots to transmit (1-512)

use_16bit_output bool

If true, use 16-bit resolution (pairs adjacent slots for fine/coarse control)

dmx_slot_mapping_raw bytes

Optional: Custom fixture slot remapping. Value of 513 indicates unused slot

TaskMemoryInfo

Per-task stack accounting. One entry per FreeRTOS task currently running.

stack_hwm_bytes is the canonical "free bytes at worst since the task started"

reported by uxTaskGetStackHighWaterMark(); on Cortex-M the underlying counter

is words (4-byte), already multiplied here for client convenience.

FieldTypeLabelDescription
name string

FreeRTOS task name (configMAX_TASK_NAME_LEN-1 chars max)

stack_size_bytes uint32

Allocated stack region in bytes

stack_hwm_bytes uint32

Free bytes at worst since task start (lower = more used)

stack_used_peak_bytes uint32

Convenience: stack_size_bytes - stack_hwm_bytes

stack_min_hwm_bytes uint32

Lowest HWM ever observed by the firmware's own periodic sampler (0 if not separately tracked for this task)

instance_index uint32

Disambiguator for dynamic-instance tasks (TCP/TLS clients); 0 for singletons

priority uint32

Current FreeRTOS priority

AdminMemoryDiagnosticsMessage

Memory diagnostics snapshot. Returned in response to AdminMessage{GET, MEMORY_DIAGNOSTICS}.

All byte counts are bytes (not FreeRTOS "words"). uptime_seconds is included so

the client can judge whether HWMs have had enough wall time to converge.

FieldTypeLabelDescription
tasks TaskMemoryInfo repeated

Live tasks only (NULL handles skipped)

task_count uint32

Length of tasks (mirror for clients that don't auto-count)

sys_stack_size_bytes uint32

System/MSP stack (the stack used before scheduler start + by ISRs). HWM derived from a stack-painting scan.

sys_stack_hwm_bytes uint32

Free bytes at worst this run

sys_stack_hwm_prev_bytes uint32

Free bytes captured before this reboot

sram_total_bytes uint32

Linker-section static usage (computed from _sdata/_edata/_sbss/_ebss/_enoinit/_sccmram/_eccmram/_estack). 128 KB total

sram_static_bytes uint32

.data + .bss + .noinit

ccmram_total_bytes uint32

64 KB total

ccmram_static_bytes uint32

Sections marked CCMRAM

uptime_seconds uint32

Seconds since boot

boot_sys_stack_hwm_bytes uint32

System-stack peak captured immediately before vTaskStartScheduler(). Compare against sys_stack_hwm_bytes to disambiguate pre-scheduler boot-init depth vs. post-boot ISR growth: equal => boot was the peak. Free bytes at scheduler start (lower = more used)

tls_pool_size_bytes uint32

TLS static memory pool. 0 in builds without TLS support. tls_pool_hwm_bytes is the peak first-fit allocation offset, NOT peak concurrent in-use bytes — fragmentation can push real-world need higher. total TLS pool size (24576 bytes when enabled)

tls_pool_hwm_bytes uint32

Peak byte offset ever allocated

EthLinkState

Resolved link state. UNKNOWN until the first link-up after boot.

NameNumberDescription
ETH_LINK_UNKNOWN 0

Not reported (older firmware, or not measured yet)

ETH_LINK_DOWN 1

No Ethernet link

ETH_LINK_UP 2

Ethernet link up

EthDuplexMode

Resolved duplex. UNKNOWN means the PHY has not yet published a valid

HCDSPEED (auto-neg in progress, or AN disabled + no link, or AUTODONE

timeout occurred).

NameNumberDescription
ETH_DUPLEX_UNKNOWN 0

Not reported (older firmware, or not measured yet)

ETH_DUPLEX_HALF 1

Half duplex

ETH_DUPLEX_FULL 2

Full duplex

EthNegotiationMethod

How the current link speed/duplex was decided. PARALLEL_DETECTED is the

duplex-mismatch smoking gun: it means the link partner did not transmit

FLP bursts, so the PHY had to detect speed only and (per IEEE 802.3)

pick half-duplex. If the partner is actually configured full-duplex,

every collision they see is "late" and TCP loses retransmits.

NameNumberDescription
ETH_NEG_UNKNOWN 0

Not yet determined (no link, fill-time read happened pre-link)

ETH_NEG_AN_DISABLED 1

BMCR.AN_EN == 0 (forced speed/duplex)

ETH_NEG_AN_IN_PROGRESS 2

AN_EN set but BMSR.AN_COMPLETE not yet

ETH_NEG_AN_COMPLETED 3

Clean auto-negotiation with a peer that also auto-negotiates

ETH_NEG_PARALLEL_DETECT 4

ANER.PAR_DETECT_FAULT set OR LP_AN_ABLE==0 with link up

EthLinkEventKind

Reason a record was appended to the ring buffer.

NameNumberDescription
ETH_EVT_BOOT_INIT 0

Snapshot taken at end of lan8720Init()

ETH_EVT_LINK_UP 1

Edge: link came up

ETH_EVT_LINK_DOWN 2

Edge: link went down

ETH_EVT_AN_COMPLETE 3

BMSR.AN_COMPLETE latched in ISR

ETH_EVT_PAR_DETECT_FAULT 4

ANER.PAR_DETECT_FAULT observed

ETH_EVT_AUTODONE_TIMEOUT 5

Reserved for future bounded-poll fix; not emitted yet

ETH_EVT_INVALID_HCDSPEED 6

PSCSR.HCDSPEED resolved to a reserved value

EthErrorHistogramBucket

One slot of the per-minute error histogram. Counters are deltas for the

minute identified by minute_index (uptime_seconds / 60). The bucket

labelled "current_minute_index" in the parent message is still

accumulating; older buckets are closed and frozen.

FieldTypeLabelDescription
minute_index uint32

Uptime-minute when this bucket was opened

secr_count uint32

PHY SECR ticks during this minute

crc_count uint32

MAC RX CRC errors during this minute

miss_count uint32

DMA controller-side missed frames during this minute

rx_good_count uint32

MAC RX good frames during this minute — context for the error rates

tx_good_count uint32

MAC TX good frames during this minute — context for the error rates

EthLinkEventRecord

One row of the link-event ring buffer. Fixed-stride for simple parsing.

PHY register fields are uint32 only to widen nanopb varint encoding —

real values fit in 16 bits.

FieldTypeLabelDescription
uptime_seconds uint32

When the event was recorded (xTaskGetTickCount / configTICK_RATE_HZ)

kind EthLinkEventKind

What happened

resolved_speed_mbps uint32

0 / 10 / 100 — 0 means UNKNOWN at the time of the event

resolved_duplex EthDuplexMode

Duplex resolved at the time

bmsr uint32

BMSR (PHY reg 0x01) at event time

anlpar uint32

ANLPAR(PHY reg 0x05) — what link partner advertised; 0x0000 => partner did not AN

aner uint32

ANER (PHY reg 0x06) — bit 4 PAR_DETECT_FAULT, bit 0 LP_AN_ABLE

pscsr uint32

PSCSR (PHY reg 0x1F) — bit 12 AUTODONE, bits 4:2 HCDSPEED

AdminEthernetDiagnosticsMessage

Returned in response to AdminMessage{GET, ETHERNET_DIAGNOSTICS}.

All PHY register fields are live reads via MDIO at the moment of the

request (except SECR — symbol error count is self-clearing on read and

is accumulated in phy_symbol_errors_total).

MAC counters are the Ethernet MAC's MMC registers (32-bit, not self-clearing by

default on this build). They are absolute since power-on; clients should

take two snapshots and diff to get a rate. They WILL wrap eventually

(~8 hours at 100 Mbps line-rate of 64-byte frames).

FieldTypeLabelDescription
link_state EthLinkState

===== Resolved live link state =====

link_speed_mbps uint32

0 / 10 / 100

duplex_mode EthDuplexMode

Duplex mode now

neg_method EthNegotiationMethod

Derived from BMCR/BMSR/ANER at fill-time

partner_an_capable bool

ANER.LP_AN_ABLE

partner_adv_full_duplex bool

ANLPAR.100BTX_FD || ANLPAR.10BT_FD

partner_adv_100mbps bool

ANLPAR.100BTX_FD || ANLPAR.100BTX_HD

autodone bool

PSCSR.AUTODONE

use_auto_negotiation_setting bool

the user's auto-negotiation setting (what the user toggled)

bmcr uint32

0x00 — AN_EN, SPEED_SEL, DUPLEX, RESTART_AN

bmsr uint32

0x01 — LINK_STATUS, AN_COMPLETE, capabilities

phyid1 uint32

0x02 — PHY ID 1 (identity high)

phyid2 uint32

0x03 — PHY ID 2 (identity low)

anar uint32

0x04 — what WE advertised

anlpar uint32

0x05 — what PARTNER advertised

aner uint32

0x06 — PAR_DETECT_FAULT, LP_AN_ABLE

mcsr uint32

0x11 — EDPWRDOWN, ENERGYON

scsir uint32

0x1B — AMDIX, polarity

pscsr uint32

0x1F — AUTODONE, HCDSPEED

mac_tx_good_frames uint32

ETH_MMCTGFCR — successfully transmitted frames

mac_tx_single_collision uint32

ETH_MMCTGFSCCR — transmitted after one collision (HD only; non-zero on HD link is normal, non-zero on FD link => mismatch)

mac_tx_multi_collision uint32

ETH_MMCTGFMSCCR — transmitted after >1 collisions (HD only; very strong mismatch indicator on a FD partner)

mac_rx_good_frames uint32

ETH_MMCRGUFCR — received good unicast frames

mac_rx_crc_errors uint32

ETH_MMCRFCECR — CRC errors (cable, EMI, or duplex mismatch on FD side)

mac_rx_alignment_errors uint32

ETH_MMCRFAECR — frame alignment / dribble errors

dma_missed_frames_app uint32

ETH_DMAMFBOCR.MFA[27:17] — drops because the descriptor list was full (RX backlog)

dma_missed_frames_controller uint32

ETH_DMAMFBOCR.MFC[15:0] — drops because the RX FIFO was full

phy_symbol_errors_total uint64

Sum of PHY SECR (reg 0x1A) reads

link_up_count uint32

How many times the link came up since boot

link_down_count uint32

How many times the link dropped

par_detect_count uint32

Times ANER.PAR_DETECT_FAULT was latched

invalid_hcdspeed_count uint32

Times PSCSR.HCDSPEED came back as a reserved value (the invalid-operation-mode warning path)

autodone_timeout_count uint32

Times the post-link-event AUTODONE wait expired (currently a 2.5 s budget)

secr_saturation_count uint32

SECR (PHY reg 0x1A) is a 16-bit self-clearing counter. If the symbol error rate exceeds 65535 between successive drains, the register saturates at 0xFFFF and we lose count fidelity for the overflow. This counter increments every time we drain SECR and find exactly 0xFFFF — i.e. every time we know we under-counted. A non-zero value means the phy_symbol_errors_total / per-minute histogram are LOWER BOUNDS only.

uptime_seconds uint32

Seconds since boot, when this was read

peak_secr_per_tick uint32

===== Burst tracking ===== Largest single-drain SECR value ever observed since boot. The diagnostics module drains SECR on a periodic timer (~4 Hz / 250 ms by default) AND on every PHY poll tick (~1 Hz). The field name is kept for wire compatibility; treat it as "peak_secr_per_drain". If this approaches 0xFFFF (= 65535) the chip saturated the counter and we lost precision — see secr_saturation_count.

current_minute_secr uint32

SECR count accumulated in the CURRENTLY-OPEN minute bucket (i.e. the bucket that will eventually be appended to `buckets` when the minute rolls). 0 to ~10s for a brand-new minute, up to ~1.8M/min at observed peak rates.

current_minute_index uint32

Uptime-minute index of the currently-open bucket — clients use this to know which minute the partial `current_minute_secr` belongs to.

events EthLinkEventRecord repeated

===== Ring buffer of recent link-state transitions, oldest -> newest =====

buckets EthErrorHistogramBucket repeated

===== Per-minute error histogram, oldest -> newest ===== Each bucket is a closed (finalised) 1-minute window. The currently accumulating minute is exposed via current_minute_* above. Up to 30 minutes of history so you can leave the device running and see patterns (thermal drift, time-of-day EMI, traffic correlation).

phy_regs_all uint32 repeated

===== Full Ethernet PHY register dump (live MDIO sweep) ===== 32 entries indexed by PHY register address (0..31). Reserved/unused registers will read back as 0 (or whatever the chip drives onto MDIO for those addresses). Included primarily for forensic comparison against the PHY datasheet when needed.

GpioPhase1Result

Raw Phase-1 GPIO classification — TX/RX as input with internal pull-down, EN as

output low (DMX transceiver receive mode), 16 samples OR-folded over ~8 ms.

Multi-sampling matters: a single read of RX on a line being actively driven by an

external DMX master can land inside a BREAK or 0-bit and falsely report EMPTY.

OR-folding 16 samples across one DMX frame's worth of time guarantees we observe

at least one MARK state if the line is active.

Why each pattern occurs:

EMPTY: nothing fitted, internal pull-downs win on both pins

DALI_LIKE: TX pulled to ~2 V by the on-board 3V3 → opto-LED → R4 (390R) bleed-through

regardless of DALI bus state. RX may be 0 or 1 depending on whether the

DALI bus is energised — TX HIGH alone is enough to classify.

DMX_LIKE: DMX line transceiver receiver enabled (EN=LOW) drives R output push-pull HIGH via the

transceiver's internal fail-safe biasing on undriven A/B. TX stays LOW

because the D input is high-Z CMOS.

CAUTION: this pattern is ALSO matched by a DALI daughterboard whose TX

bleed-through path is broken (R4 open, TX-opto LED open, daughterboard

3V3 lost on the TX-side feed) while R2's RX pull-up is still alive — that

case is what `dmx_toggle` exists to disambiguate.

NameNumberDescription
GPIO_PHASE1_UNKNOWN 0

Not run

GPIO_PHASE1_EMPTY 1

(TX, RX) = (0, 0)

GPIO_PHASE1_DALI_LIKE 2

(TX, RX) = (1, X)

GPIO_PHASE1_DMX_LIKE 3

(TX, RX) = (0, 1)

DaliEchoResult

DALI active self-echo probe (~13 ms total, GPIO-only). Drives TX HIGH (DALI idle),

settles 10 ms (covers worst-case ~9 ms DALI bus rise time on fully-loaded buses),

reads RX. Then TX LOW for ~200 µs (active sink — well below any DALI receiver's

frame-start threshold so no devices misinterpret it) and reads RX. Then TX HIGH

again and reads RX. A healthy DALI board on a powered (~16 V) bus shows the

sequence (rx_idle=0, rx_during=1, rx_after=0) because the receive opto's

conduction tracks bus voltage.

PASS is a UNIQUELY POSITIVE identification of a healthy DALI loop on a powered bus

— no other fitted hardware can produce this echo pattern. Always run regardless of

Phase 1's classification so cross-checking can catch P1 misclassifications.

FAIL does NOT localise to a specific failure — could be a damaged DALI board, an

unpowered/disconnected DALI bus, a shorted bus, or a non-DALI daughterboard.

SKIPPED means the echo did not run. Two causes, distinguishable by the rest of the

entry:

- RX was observed toggling in the ~1 ms pre-check immediately before this phase,

i.e. an external DMX master is transmitting. Driving TX into a line another

transmitter owns is unsafe, and the result would be meaningless anyway: a BREAK

sampled as rx_idle followed by a data MARK can forge the (0, 1, 0) signature.

Here gpio_phase1 and verdict still carry real results.

- The whole probe was skipped because the line was locked by DALI or RDM traffic.

Here gpio_phase1 and verdict are both UNKNOWN and every phase reads SKIPPED.

To rule out the forged-signature case the echo is repeated three times back-to-back

and only reports PASS when all three agree.

NameNumberDescription
DALI_ECHO_UNKNOWN 0

Not run

DALI_ECHO_PASS 1

The frame sent came back on RX: a working DALI interface

DALI_ECHO_FAIL 2

Nothing came back

DALI_ECHO_SKIPPED 3

External transmitter seen on RX, or the whole probe was skipped (line busy)

DmxToggleResult

DMX EN-toggle probe (~7 ms total, GPIO-only). Holds TX OUTPUT HIGH (so if the driver

were enabled it would output DMX idle A=HIGH/B=LOW — minimally disruptive), RX as

input pull-down. EN goes LOW (receiver enabled) then HIGH (receiver disabled, driver

briefly enabled for ~10 µs) then back LOW. Only a real DMX transceiver R output transitions

from push-pull HIGH → high-Z in this sequence. A DALI board's RX is held HIGH by R2

(4k7 to on-board 3V3) regardless of EN, so it gets stuck HIGH on both reads. Empty

slot reads (0, 0).

PASS is a UNIQUELY POSITIVE identification of a working DMX receiver — no other

fitted hardware can produce the high→high-Z transition. Always run regardless of

Phase 1's classification so cross-checking can catch P1 misclassifications.

SKIPPED has three causes:

- dali_echo already returned PASS. The board is positively identified as DALI and

the verdict no longer depends on this phase, so it is not run.

- RX was observed toggling (active external master) during the ~1 ms pre-check run

immediately before this phase. Skipping protects against driving the line into

contention with an external master mid-frame.

- The whole probe was skipped because the line was locked by DALI or RDM traffic,

in which case verdict is UNKNOWN and every phase reads SKIPPED.

NameNumberDescription
DMX_TOGGLE_UNKNOWN 0

Not run

DMX_TOGGLE_SKIPPED 1

DALI already confirmed, external transmitter on RX, or whole probe skipped (line busy)

DMX_TOGGLE_PASS 2

(rx_low=1, rx_high=0) — confirmed DMX receiver

DMX_TOGGLE_FAIL_STUCK_HIGH 3

(rx_low=1, rx_high=1) — something pulls RX HIGH regardless of EN (most-likely DALI R2)

DMX_TOGGLE_FAIL_STUCK_LOW 4

(rx_low=0, rx_high=0) — no driver on RX

DMX_TOGGLE_FAIL_INVERTED 5

(rx_low=0, rx_high=1) — unexpected; investigate hardware

DmxListenResult

DMX passive listen (~50 ms). Decodes the USART RXNE/FE/ORE stream while EN=LOW, looking

for the DMX512 framing signature — a BREAK (which surfaces as a single framing error)

followed by a 0x00 NULL start code and slot data. Only runs

when the line's USART is already enabled (i.e. configured DMX or DMX_IN) — for other

configurations the USART for that slot is not clocked, and reconfiguring it from a

diagnostic call would be invasive. Also skipped once dali_echo has returned PASS:

the board is identified and this window would only delay the response.

NameNumberDescription
DMX_LISTEN_UNKNOWN 0

Not run

DMX_LISTEN_SKIPPED 1

USART not configured for this line, DALI already confirmed, or whole probe skipped (line busy)

DMX_LISTEN_QUIET 2

Zero events in window — line is electrically clean

DMX_LISTEN_ACTIVE 3

Events seen but not validated as DMX — could be an external master we did not catch a BREAK from, or a transceiver fault

DMX_LISTEN_DMX_VALID 4

Coherent DMX512 stream validated: BREAK -> 0x00 start code -> slots

LineDiagnosticVerdict

Synthesized verdict from (configured_as, gpio_phase1, dali_echo, dmx_toggle, dmx_listen).

Verdict logic prefers the strongest positive signal:

1. dali_echo == PASS → DALI confirmed (regardless of P1)

2. dmx_toggle == PASS → DMX confirmed (regardless of P1)

3. dmx_listen == DMX_VALID → a coherent DMX512 stream is positive proof of a working

receive path, obtained passively. Ranks below the EN-toggle, which proves the

control path as well, but above any P1 inference.

4. none of those → fall back to P1 + the FAIL/SKIPPED context

This protects against P1 misclassifications — e.g. a damaged DMX board whose TX pin

leaks high reads as DALI_LIKE under P1, but the EN-toggle correctly identifies it.

Failure modes deliberately NOT distinguished by this verdict (firmware can't see them

from the three pins available): DALI bus open vs. shorted; DALI cable mis-wired into

a DMX board (looks like quiet DMX); DMX cable mis-wired into a DALI board (looks

like unpowered DALI bus); DMX board with lost on-board 3V3 (looks like EMPTY unless

the operator configured the slot as DMX, in which case EMPTY_OR_UNPOWERED_BOARD).

NameNumberDescription
LINE_VERDICT_UNKNOWN 0

No verdict (probe not run)

LINE_VERDICT_EMPTY 1

Slot empty; matches configured EMPTY/AUTO. Nothing to investigate.

LINE_VERDICT_EMPTY_OR_UNPOWERED_BOARD 2

Operator configured DALI/DMX but all probes returned negative. Either no board fitted, on-board 3V3 lost, or transceiver IC dead.

LINE_VERDICT_DALI_OK_BUS_POWERED 3

DALI board + DALI bus both verified healthy by echo.

LINE_VERDICT_DALI_PRESENT_BUS_UNVERIFIED 4

Phase 1 saw DALI TX bleed-through but the echo failed. Bus is open / shorted / not energised — connect a DALI PSU and retry.

LINE_VERDICT_DMX_OK 5

DMX board confirmed via EN-toggle, line quiet (or USART not yet running).

LINE_VERDICT_DMX_PRESENT_ACTIVE_TRAFFIC 6

DMX board confirmed via EN-toggle, external traffic seen on bus.

LINE_VERDICT_BOARD_PRESENT_TYPE_AMBIGUOUS 7

Phase 1 looked DMX-like but the EN-toggle said NOT a DMX receiver and the DALI echo also failed. Most-likely a TX-broken DALI board (R4 / TX opto LED open) with R2 still pulling RX up. Replace daughterboard.

LINE_VERDICT_MISCONFIGURED_LIKELY_DMX 8

Configured type ≠ DMX, but EN-toggle confirms a DMX board is fitted. Reconfigure to DMX.

LINE_VERDICT_MISCONFIGURED_LIKELY_DALI 9

Configured type ≠ DALI, but DALI echo confirms a healthy DALI board on a powered bus. Reconfigure to DALI.

LINE_VERDICT_MISCONFIGURED_OTHER 10

Configured ≠ probed and no active probe gave a confident positive identification. Investigate cabling + board fit.

LINE_VERDICT_FAULT 11

Probes returned a pattern that does not match any healthy configuration (e.g. P1 says DALI_LIKE but every other probe disagrees). Likely a damaged daughterboard.

LineDiagnosticConfidence

How sure a line diagnostic verdict is.

NameNumberDescription
LINE_CONFIDENCE_UNKNOWN 0

No verdict, so no confidence

LINE_CONFIDENCE_LOW 1

Verdict relies on inference the firmware cannot directly verify (e.g. EMPTY vs unpowered board)

LINE_CONFIDENCE_MEDIUM 2

Verdict is consistent with the probes but one or more came back SKIPPED / ambiguous

LINE_CONFIDENCE_HIGH 3

All probes that ran agree, in a pattern that uniquely identifies the verdict

LineDiagnosticEntry

One per physical line slot. All four raw probe results are reported alongside the

synthesized verdict so a UI can show "why" the verdict was reached.

FieldTypeLabelDescription
line_index uint32

0-based; 0..LINE_COUNT-1 for the current hardware variant

configured_as LineType

The configured type for this line

gpio_phase1 GpioPhase1Result

Phase-1 (TX, RX) classification after multi-sample OR-fold

dali_echo DaliEchoResult

Active DALI self-echo (always run)

dmx_toggle DmxToggleResult

EN-toggle DMX-receiver presence test (always run unless RDM busy or external traffic observed)

dmx_listen DmxListenResult

Passive ~50 ms USART listen, validated against DMX512 framing (only when line's USART is enabled)

verdict LineDiagnosticVerdict

Highest-information verdict; see enum comment

confidence LineDiagnosticConfidence

How much to trust `verdict`

AdminLineDiagnosticsMessage

Per-line diagnostic snapshot. Returned in response to AdminMessage{GET, LINE_DIAGNOSTICS}.

All four probes run on every line (with safety-skip on P3/P4 if RDM is active or

external traffic is detected). Per-line wall time: ~33 ms typical, ~88 ms when P4

runs. Total message wall time: bounded under 400 ms on any hardware variant. Not

safe to spam from a hot loop.

FieldTypeLabelDescription
lines LineDiagnosticEntry repeated

One entry per physical line slot, in line-index order

uptime_seconds uint32

Seconds since boot — context for the probe (e.g. very-recent boot may not have stable bus state yet)

ClockSource

Which clock drives the RTC. UNKNOWN should not appear in a healthy device.

NameNumberDescription
CLOCK_SOURCE_UNKNOWN 0

Not reported (older firmware, or not measured yet)

CLOCK_SOURCE_LSE 1

32.768 kHz external crystal (default)

CLOCK_SOURCE_LSI 2

Internal RC oscillator (less accurate fallback)

ClockMeasurementStatus

Outcome of the software LSE-vs-HSE ppm measurement.

NameNumberDescription
LSE_MEAS_NOT_RUN 0

Never measured (default after boot, before first probe)

LSE_MEAS_OK 1

Window completed cleanly

LSE_MEAS_LSE_DEAD 2

SSR never advanced — crystal silent

LSE_MEAS_HSE_UNSTABLE 3

HSE drifted during the window — measurement invalid

LSE_MEAS_INSUFFICIENT_TIME 4

dwt_delta too small to resolve

TimeSetSource

Origin of the most-recent RTC write. Used by clients to distinguish drift

(no recent write) from operator action (recent NETWORK_ADMIN / MENU write).

NameNumberDescription
TIME_SET_NEVER 0

Clock has never been set since the last battery loss

TIME_SET_FACTORY 1

Reserved — not currently emitted

TIME_SET_MENU 2

Set via the on-device menu / debug helper

TIME_SET_NETWORK_LEGACY 3

UpdateTimeMessage (top-level update_time)

TIME_SET_NETWORK_ADMIN 4

AdminPropertyType DEVICE_TIME SET

TIME_SET_NTP 5

NTP success path

TIME_SET_BACNET 6

BACnet TimeSync (local or UTC)

TIME_SET_DST_ADJUST 7

Automatic DST hour-boundary fixup

DstHemisphere

Inferred from start_day / end_day of the configured DST window.

NameNumberDescription
DST_HEMISPHERE_UNKNOWN 0

DST disabled in config

DST_HEMISPHERE_NORTHERN 1

start_day < end_day (DST contained within one calendar year)

DST_HEMISPHERE_SOUTHERN 2

start_day > end_day (DST wraps across the new year)

DstTransitionType

What the next DST transition will do.

NameNumberDescription
DST_TRANSITION_NONE 0

DST disabled or no transition scheduled

DST_TRANSITION_ENTER 1

Spring forward (gain an hour)

DST_TRANSITION_LEAVE 2

Fall back (lose an hour)

NtpSyncRecord

Single entry in the recent-NTP-sync ring buffer. RAM-only on the device

(lost on reboot), populated in chronological order: oldest → newest.

FieldTypeLabelDescription
unix_time uint32

Y2K-relative seconds at the moment of acceptance

correction_seconds sint32

server - rtc, before stepping (signed)

rtt_ms uint32

Request → response round-trip

stratum uint32

From NTP packet[1] (1-15 valid)

AdminTimeDiagnosticsMessage

Returned in response to AdminMessage{GET, TIME_DIAGNOSTICS}.

Performs a fresh ~250 ms LSE-vs-HSE ppm measurement on every call unless

the caller recently issued AdminPropertyType_TIME_DIAG_MEASURE_LSE (RUN),

in which case the cached result is returned. Otherwise side-effect-free.

===== Clock source identity & health =====

FieldTypeLabelDescription
rtc_clock_source ClockSource

LSE / LSI / UNKNOWN

lse_ready_now bool

RCC->BDCR.LSERDY at read time

lse_css_enabled bool

RCC->BDCR.LSECSSON

lse_css_fault_latched bool

RCC->BDCR.LSECSSD — sticky once tripped

nominal_lse_hz uint32

32768

hse_hz uint32

SystemCoreClock (reference rate)

measurement_status ClockMeasurementStatus

===== Independent frequency measurement =====

measured_lse_ppm_error sint32

(measured - 32768) ppm

measurement_window_us uint32

Actual elapsed window

measurement_dwt_delta uint32

Raw HCLK cycles in the window

measurement_rtc_subsec_delta uint32

Raw SSR ticks in the window

applied_ppm_correction float

Active RTC ppm calibration value at read time

temperature_at_last_calibration float

Internal MCU temp °C at last hour-boundary call

smooth_calib_period_seconds uint32

32 seconds

rtc_temp_comp_enabled bool

Persisted action-knob state

rtc_ppm_manual_override_enabled bool

Persisted action-knob state

rtc_ppm_manual_override_value sint32

Persisted action-knob state

ntp_enabled_in_config bool

NTP enabled in config

ntp_server_hostname string

From config (max_size enforced in .options)

ntp_sync_success_count uint32

Lifetime, persisted

ntp_sync_failure_count uint32

Lifetime, persisted

last_ntp_success_unix uint32

0xFFFFFFFF means never (Y2K epoch)

last_ntp_attempt_unix uint32

Either success or failure (Y2K epoch)

last_ntp_correction_seconds sint32

Signed: server - rtc at last success

last_ntp_rtt_ms uint32

Round-trip of last attempt

last_ntp_stratum uint32

Stratum of last successful response

effective_ntp_poll_period_seconds uint32

ntp_poll_period_seconds override if set, else config NTPTimeout

ntp_max_acceptable_delta_seconds uint32

The rejection threshold currently in force

last_ntp_error string

Last NTP error string (max 32 chars)

ntp_history NtpSyncRecord repeated

Oldest → newest, RAM only

rtc_unix_epoch_now uint32

Y2K seconds at read time

rtc_subseconds_now uint32

RTC->SSR snapshot

rtc_advancing bool

SSR observed to change during a 200 µs probe

last_boot_lost_backup bool

backup-domain canary was clear at this boot's start

boots_since_last_backup_loss uint32

Persisted, bumped each boot when canary valid

rtc_ever_been_set bool

True once any non-DST set has occurred since loss

vbat_voltage float

Backup battery voltage

vbat_low bool

backup battery voltage below the low-battery threshold

dst_enabled_in_config bool

===== DST visibility =====

dst_currently_active bool

DST store flag active

dst_offset_seconds sint32

-3600 / 0 / +3600

dst_last_transition_unix uint32

0 until first observed transition (Y2K epoch)

dst_next_transition_unix uint32

Computed forward from current date

dst_next_transition_type DstTransitionType

Whether the next daylight-saving change starts or ends DST

dst_hemisphere DstHemisphere

Hemisphere the DST rules were worked out for

total_time_set_count uint32

Lifetime, persisted

last_time_set_unix uint32

Y2K seconds of the last set

last_time_set_source TimeSetSource

What set the clock last

last_manual_set_delta_seconds sint32

(new - old) at the last non-NTP, non-DST set

uptime_seconds uint32

Seconds since boot, when this was read

Spi2StallType

Which flag of the storage SPI bus stalled. The

distinction matters: on a TXE stall nothing was clocked out (a resend would

have been safe), whereas on BSY or RXNE the byte was already sent (a resend

would have corrupted the frame). The firmware discards in both cases.

NameNumberDescription
SPI2_STALL_NONE 0

No stall has occurred since boot

SPI2_STALL_TXE 1

TX buffer never emptied - byte not sent

SPI2_STALL_BSY 2

Peripheral stayed busy - byte was sent

SPI2_STALL_RXNE 3

RX buffer never filled - byte was sent

AdminStorageDiagnosticsMessage

Storage subsystem health. Returned for AdminMessage{GET, STORAGE_DIAGNOSTICS}.

Scope is the storage SPI bus and every device on it - the SD card, the NOR

flash and the IO expander share the bus, so one device wedging it takes the

others down. The bus fields come first because they are the context the device

fields are read in.

All counters are absolute since boot, never cleared; diff successive GETs for

a rate. Only the four sd_*_abort_* counters saturate at 0xFFFFFFFF (a value

there is a lower bound); the rest are plain 2^32 wraps.

Side-effect-free: every field is a RAM latch, nothing probes the bus, so this

is safe to poll.

===== Roll-up =====

FieldTypeLabelDescription
storage_healthy bool

False if the bus is suppressed, the NOR has a latched or presence fault, or a fitted SD card is failing health checks. A convenience only - every input is also present below. The mount-cycle counters and sd_cd_hint do not feed it: they are history and pin state, not present health.

spi2_suppressed bool

True while the bus is suppressed after a stall the driver could not clear. Read before any nor_* field: while suppressed, transfers return 0x00 instead of failing, so every nor_* value below is stale (the last latched before suppression) and should be shown as unknown, not healthy. The spi2_* counters stay valid - they are what suppressed the bus.

spi2_stall_txe_count uint32

Stalls where TXE never set

spi2_stall_bsy_count uint32

Stalls where BSY never cleared

spi2_stall_rxne_count uint32

Stalls where RXNE never set

spi2_last_stall Spi2StallType

Kind of the most recent stall

spi2_reset_count uint32

Times the driver reset the SPI peripheral

nor_fault_active bool

Sticky since boot: the part latched a program/erase error or the boot presence probe rejected it - the NOR itself is suspect. Not set by a suppressed bus (that is a bus property, reported by spi2_suppressed); stays valid as history while suppressed, just stops updating.

nor_fault_count uint32

Program/erase operations that did not complete cleanly. Two causes: the part latched E_ERR/P_ERR, or the operation was attempted while the bus was suppressed and the bytes never left the MCU. Only the first sets nor_fault_active/nor_fault_last_status, so a non-zero count with both of those clear means "attempted while the bus was down", not a failing part.

nor_fault_last_status uint32

The NOR's status register 1 byte that carried the error bits (0 if none): bit5 (0x20) = E_ERR erase failed, bit6 (0x40) = P_ERR program failed.

nor_presence_fault uint32

Boot probe cause bitmask, latched once and never re-probed. 0 healthy, bit0 (0x01) RDID absent or wrong part, bit1 (0x02) CR1 TBPARM set (parameter block not at the bottom). Mutually exclusive - CR1 is trusted only once the part identifies as ours - so 0x03 cannot occur.

sd_supported bool

False on variants with no SD socket. Without it, every field below reads 0 and is indistinguishable from a fitted card sitting idle.

sd_mounted bool

The SD card is mounted and usable

sd_last_probe_r1 uint32

Raw R1 from the last CMD0 probe - keeps the absent vs present-and-faulty distinction the mount result loses. 0xFF nothing answered: no card fitted, no probe run yet, or the bus suppressed (check spi2_suppressed before wording this one). 0x01 a card in idle state. Healthy. bit7 set but not 0xFF: no valid R1 received; the low bits are bus noise. otherwise a present card that answered with error bits set. SD spec 7.3.2.1: bit6 erase reset, bit5 illegal command, bit4 CRC error, bit3 erase sequence error, bit2 address error, bit1 parameter error.

sd_block_abort_rx uint32

Blocks abandoned by the per-block deadline, and operations abandoned by the per-operation deadline (refused at entry, or cut short mid-transfer). All four are deadline aborts, not media errors; FatFs reports both as FR_DISK_ERR and these counters are the only thing that tells them apart.

sd_block_abort_tx uint32

Blocks abandoned while writing (see sd_block_abort_rx)

sd_op_abort_entry uint32

Operations refused at entry by the per-operation deadline

sd_op_abort_mid uint32

Operations cut short mid-transfer by the per-operation deadline

sd_unsafe_delete_count uint32

Deletions that proceeded without the guarantee the safe path provides.

sd_consecutive_health_failures uint32

Consecutive failed CMD13 health checks on the mounted card. Reaching the firmware's threshold unmounts the volume, so a persistently non-zero value below it means a card answering intermittently - the state that precedes an unexplained unmount.

sd_recovery_consecutive_failures uint32

Power-cycle escalation while the card is unmounted: consecutive failed SPI probes, and the count the next rail drop needs. The threshold doubles after every drop, so it also reports how many have happened (first-rung = none).

sd_recovery_failures_needed uint32

Failed probes the next power cycle of the card needs (see sd_recovery_consecutive_failures)

sd_total_bytes uint64

Volume capacity as last measured by f_getfree(). total_bytes = 0 on a mounted card means capacity has never been measured (every f_getfree() since the mount failed), not that the card is empty - the same condition SD_CAPACITY_UNKNOWN reports, and while it holds size-based log retention cannot run.

sd_free_bytes uint64

Free space, as last measured (see sd_total_bytes)

sd_mount_attempts uint32

===== Mount cycle history - monotonic since boot, never reset ===== Counted at the sole f_mount site, so the boot mount is included. Read attempts and successes as a pair: alone they cannot be interpreted (a card reinserted often and one that never mounts both climb). Attempts rising with successes stuck at zero is a card that answers CMD0 but whose filesystem will not mount - no other field moves, because the probe is succeeding and the power-cycle escalation never arms.

sd_mount_successes uint32

Mounts that succeeded (read with sd_mount_attempts)

sd_unmount_count uint32

Confirmed removals (enough consecutive CMD13 failures for the firmware to unmount). The only durable record that a removal happened: sd_consecutive_health_failures resets on the unmount it triggers, so a client polling slower than the health check would miss it. A non-zero value with sd_mounted true means the card is up now but has been up and down.

sd_mount_deferred_lock_busy uint32

Mounts abandoned before f_mount because the volume lock was still held. Not a media fault, and not counted as an attempt: another task held the filesystem longer than the firmware would wait, usually the NOR on the shared SPI bus. Expected near zero; a large value points at bus contention, so read it against the spi2_* counters.

sd_cd_hint bool

===== Card detect pin ===== The debounced CD switch, sampled every 10 ms. Advisory only - it is a mechanical switch, not a presence answer; mount authority rests entirely on whether the card answers CMD0. Never label it "card present" in a UI. These switches fail in both directions on this hardware, so the value is only useful cross-checked against the authoritative fields: true + sd_last_probe_r1 == 0xFF -> switch stuck closed, or an empty socket reading as occupied (check spi2_suppressed, also 0xFF). false + sd_mounted true -> switch stuck open. The card works only because the firmware probes on a timer; insertion is detected late (~1 s) in this state. False before the debounce settles (30 ms from boot), long resolved by the time any client can ask - no "never sampled" ambiguity to allow for.

sd_cid_valid bool

===== Card identity (CID register, SD spec 5.2) ===== Read once per mount by a single CMD10, then cached (this message never touches the bus); cleared on unmount, so the identity always belongs to the mounted card. Check sd_cid_valid first - every field below is meaningless without it, and an unvalidated identity is worse than none: the read discards the CRC16, so a marginal SPI joint yields a plausible-looking name rather than an obvious failure. The flag covers CRC7 plus the all-zero/all-ones idle-bus patterns (CRC7 has a fixed point at zero, so a blank register passes its checksum).

sd_cid_manufacturer_id uint32

Manufacturer ID. Raw on purpose: MIDs are allocated privately by SD-3C LLC with no public registry, so every MID-to-name table is guesswork. Display as hex; use oid/pnm for the readable identity.

sd_cid_oem_id string

OID, 2 ASCII chars

sd_cid_product_name string

PNM, 5 ASCII chars

sd_cid_revision_major uint32

PRV, two BCD nibbles. Present as "major.minor", not a single number.

sd_cid_revision_minor uint32

Product revision, minor part (see sd_cid_revision_major)

sd_cid_serial uint32

PSN, 32-bit binary. Display as hex.

sd_cid_mdt_year uint32

MDT. Year is absolute (the device already applied the spec's 2000 offset). Month is 1-based; 0 or >12 means the card encoded an out-of-spec value, passed through rather than clamped.

sd_cid_mdt_month uint32

Manufacturing month, 1-12 (see sd_cid_mdt_year)

uptime_seconds uint32

Seconds since boot, when this was read

DaliBusPower

What is powering a DALI line's bus. Used with DaliLineStatus

NameNumberDescription
DALI_BUS_POWER_UNKNOWN 0

Not reported by this firmware

DALI_BUS_POWER_NONE 1

No supply on the bus

DALI_BUS_POWER_EXTERNAL 2

An external DALI bus supply

DALI_BUS_POWER_INTERNAL 3

The device's own bus supply for this line

DALI_BUS_POWER_SHORT 4

Bus held low while powered: own supply removed. Latched until the bus is seen high again or the supply is re-enabled

DaliLineStatus

Per-line DALI health snapshot. Mirrors one line of the device's

DALI status structure. Short-address bitmaps use bit n = DALI short address n.

FieldTypeLabelDescription
line_index uint32

0-based physical DALI line index

device_count uint32

Devices currently online (popcount of the poll mask)

fault_count uint32

Devices on this line reporting a lamp or gear fault

bus_power_error bool

TRUE if the DALI bus itself is down (debounced)

lowest_fault_address uint32

Lowest DALI short address with a fault (0xFF = none)

missing_devices_mask uint64

Latching bitmap of devices that failed retries (gone silent). JS_STRING so JS clients keep full 64-bit precision (a JS number loses bits above 2^53).

comms_error_mask uint64

Bitmap of devices present but returning corrupted responses. JS_STRING so JS clients keep full 64-bit precision (a JS number loses bits above 2^53).

bus_power DaliBusPower

What is powering the bus. Live, whatever polling_active says

short_count uint32

Shorts detected on this line since boot

dual_supply_count uint32

Own and external supply found together (own one then removed), since boot

AdminDaliStatusMessage

DALI system status summary. Returned in response to AdminMessage{GET, DALI_STATUS}.

Read-only mirror of the device's DALI system status — the

same structure the on-device Logic system evaluates for "any DALI error" actions.

FieldTypeLabelDescription
lines DaliLineStatus repeated

One entry per configured DALI line, in line-index order

any_system_fault bool

Global flag: TRUE if any line has any fault

polling_active bool

FALSE if DALI polling is disabled (dali_polling_interval == 0). When FALSE the per-line data is NOT live — a clean report means "not being monitored", not "no faults". Clients (e.g. a BMS) must check this before trusting any_system_fault. Each line's bus_power, short_count and dual_supply_count are live even when FALSE.

Wi-Fi (ADDICT V3)

AdminPropertyType

The property an AdminMessage targets. Each value lists its commands, the AdminMessage field its value travels in (Payload), and the login role it needs.

NameNumberDescription
DEVICE_NAME 0

The device name that appears on the network. Limited to 16 characters. Commands: GET, SET. Payload: data.string_data. Role: CONFIG. Devices: eDIDIO, ADDICT.

PROJECT_NAME 1

Used for documentation. Limited to 32 characters. Commands: GET, SET. Payload: data.string_data. Role: CONFIG.

LONGITUDE 2

Used for calculating astronomical sunrise / sunset. Commands: GET, SET. Payload: data.float_data. Role: CONFIG.

LATITUDE 3

Used for calculating astronomical sunrise / sunset. Commands: GET, SET. Payload: data.float_data. Role: CONFIG.

LOCAL_UTC_OFFSET 4

Used for calculating astronomical sunrise / sunset. Commands: GET, SET. Payload: data.float_data. Role: CONFIG.

DAYLIGHT_SAVINGS 5

Used for calculating astronomical sunrise / sunset. Commands: GET, SET. Payload: data.uint_data. Role: CONFIG.

POLL_ACTIVE 6

Whether or not to poll the current level of DALI devices to keep an in-memory cache up-to-date. Commands: GET, SET. Payload: data.uint_data. Role: CONFIG.

DHCP_ENABLED 7

Whether or not the device should use a static IP or expect a DHCP server to provide it with an IP. Commands: GET, SET. Payload: data.uint_data. Role: ADMIN.

IP_ADDR 8

The static IP address to use if DHCP_ENABLED is FALSE. Commands: GET, SET. Payload: data.string_data. Role: ADMIN.

MAC_ADDR 9

The MAC Address of the device. Expected format: [40:D8:55:1B:XX:XX]. Commands: GET, SET. Payload: data.string_data. Role: ADMIN.

GATEWAY_IP 10

The IP address of the gateway for the network this device will be installed on. Commands: GET, SET. Payload: data.string_data. Role: ADMIN.

NETWORK_PROPERTIES 11

Contains numerous properties such as DHCP, NTP, Gateway, IP, MAC. Commands: GET, SET. Payload: network_properties. Role: ADMIN. Devices: eDIDIO, ADDICT.

SYSTEM_PROPERTIES 12

Contains numerous properties such as Device Name (documentation only; not network hostname), Project Name, Latitude, Longitude, UTC Offset, DLS, Polling. Commands: GET, SET. Payload: project_properties. Role: CONFIG.

CONTROLLER_LINES 13

Allows you to specify the daughterboards installed in the device [NONE, DALI, DMX, DMX_IN]. Commands: GET, SET. Payload: controller_lines. Role: CONFIG.

EEPROM_FULL_CHIP 14

Allows you to request a reset to default values for all data stored in EEPROM. Commands: RESET. Payload: none. Role: ADMIN.

CONFIG_DATA 15

Allows you to request a reset to default values for the Config Data stored in EEPROM. Commands: RESET. Payload: none. Role: ADMIN.

SPEKTRA_DATA 16

Allows you to request a reset to default values for the Spektra Data stored in EEPROM. Commands: RESET. Payload: none. Role: ADMIN.

DEVICE_STATUS 17

Can be used to request the Device Status: Temperature and Battery Voltage. Commands: GET. Payload: device_status. Role: CONTROL. Devices: eDIDIO, ADDICT.

CONFIG_STATUS 18

Can be used to request the Config Status: Active Alarm, List States, Sensor States, Burn-in States. Commands: GET. Payload: config_status. Role: CONTROL.

DEVICE_TIME 19

Get or Set the RTC time on the device. Commands: GET, SET. Payload: device_time. Role: CONTROL for GET, CONFIG for SET.

NTP_DETAILS 20

Allows you to Get or Set the NTP parameters (i.e. NTP Server) used for maintaining the RTC via NTP updates. Commands: GET, SET. Payload: network_properties. Role: CONFIG.

DALI_SENSORS 21

Provides actions for DALI Sensor control: "ADD" to un-mute all. "REMOVE" to mute all. "RESET" to clear all (unprogram). Commands: ADD, REMOVE, RESET. Payload: none. Role: CONFIG.

SECURE_SESSION 22

Allows you to Get or Set the "Secure Session" status of the device. Commands: GET, SET. Payload: data.uint_data. Role: CONTROL for GET, ADMIN for SET.

NONCE 23

Allows you to request a Nonce to perform a Secure Login. Commands: GET. Payload: data.string_data. Role: NONE.

DALI_SENSOR_TYPE 24

The type of DALI frame (24 or 25-bit) for eDALI packets to/from motion sensors. Commands: GET. Payload: dali_sensor_type. Role: CONFIG.

DEVICE_REBOOT 25

Will reboot the device when used with the 'RUN' AdminCommandType. Commands: RUN. Payload: none. Role: ADMIN. Devices: eDIDIO, ADDICT.

SYSTEM_LOGGING 26

Will reset the system logs when used with a 'RESET' AdminCommandType. Commands: GET, RESET. Payload: data.uint_data. Role: CONFIG.

SUBNET 27

The Subnet of the Device. Commands: GET, SET. Payload: data.string_data. Role: ADMIN.

DNS 28

The Primary and Secondary DNS, both ways in dns_servers. eDIDIO firmware before 1.6.3 refused a SET with INVALID_PARAMS and answered a GET in the wrong arm - use NETWORK_PROPERTIES (DNS_Primary / DNS_Secondary) for those. Commands: GET, SET. Payload: dns_servers. Role: ADMIN.

LINK 29

Whether or not the UDP Link state is active. Commands: GET, SET. Payload: data.uint_data. Role: ADMIN.

LINK_TYPE 30

Type of Link to enable, based on ReadType. Commands: GET, SET. Payload: data.uint_data. Role: ADMIN.

LINK_MASK 31

Link Index Mask for above. Commands: GET, SET. Payload: data.uint_data. Role: ADMIN.

LINK_NETMASK 32

Netmask for Link to create Network groups for UDP messaging. Commands: GET, SET. Payload: data.uint_data. Role: ADMIN.

DALI_RX_TOLERANCE 33

The tolerance for DALI RX (where 10 is 10% above and below nominal half bit time of 416us). Commands: GET, SET. Payload: data.uint_data. Role: CONFIG.

DALI_TX_HALF_BIT_TIME 34

Default value is 416us. Commands: GET, SET. Payload: data.uint_data. Role: CONFIG.

DMX_TIMING 35

DMX Timing (I.e. 44Hz). Commands: GET, SET. Payload: dmx_timing_mode. Role: CONFIG. Devices: eDIDIO, ADDICT.

DMX_PROPERTIES 36

DMX Line Properties. Channel Mapping, 16 bit, slot count. Commands: GET, SET. Payload: dmx_line_props. Role: CONFIG. Devices: eDIDIO, ADDICT.

MEMORY_DIAGNOSTICS 37

GET-only. Returns per-task stack high-water-marks, system-stack HWM, and SRAM/CCMRAM static-section usage. Use with the 'GET' AdminCommandType. Used for tuning FreeRTOS task stack sizes and monitoring runtime RAM headroom. Commands: GET. Payload: memory_diagnostics. Role: CONTROL. Devices: eDIDIO, ADDICT.

ETHERNET_DIAGNOSTICS 38

GET-only. Returns Ethernet PHY register snapshot, Ethernet MAC counters, resolved link state, and a ring buffer of recent link-state transitions. Use with the 'GET' AdminCommandType. Used to diagnose link/auto-negotiation/duplex-mismatch issues without an SD card. Commands: GET. Payload: ethernet_diagnostics. Role: CONTROL.

LINE_DIAGNOSTICS 39

GET-only. Per-line readout of configured-vs-probed daughterboard type plus a coarse OK/FAULTY/EMPTY/MISCONFIGURED verdict. Briefly perturbs each line (a DALI half-bit pulse and/or a DMX RX-mode window) — fire on demand, not on a hot loop. Use with the 'GET' AdminCommandType. Commands: GET. Payload: line_diagnostics. Role: CONTROL.

TIME_DIAGNOSTICS 40

GET-only. RTC/NTP/DST observability: LSE crystal ppm measurement, lifetime NTP success/failure counts, last sync details, time-set audit trail, backup-domain boot counter, DST visibility. Use with the 'GET' AdminCommandType. Commands: GET. Payload: time_diagnostics. Role: CONTROL.

RTC_TEMP_COMP_ENABLED 41

GET/SET. Enable/disable the temperature-driven smooth calibration of the RTC. Persisted in BKPSRAM (reset on battery loss). Default 1. Commands: GET, SET. Payload: data.uint_data. Role: CONFIG.

RTC_PPM_MANUAL_OVERRIDE 42

GET/SET. When enabled (override flag in PayloadMessage), the RTC smooth calibration is set to a fixed signed ppm value at every hour boundary, bypassing temp comp. Persisted in BKPSRAM. Commands: GET, SET. Payload: data.float_data. Role: CONFIG.

NTP_FORCE_SYNC 43

RUN. Triggers an immediate NTP sync attempt. Commands: RUN. Payload: none. Role: CONTROL.

NTP_POLL_PERIOD_SECONDS 44

GET/SET. Override the NTP poll period. 0 means use the existing NTP_DETAILS.NTPTimeout from config. Non-zero is persisted in BKPSRAM. Commands: GET, SET. Payload: data.uint_data. Role: CONFIG.

NTP_MAX_ACCEPTABLE_DELTA_SECONDS 45

GET/SET. NTP corrections whose |delta| exceeds this value are rejected (treated as a sanity-check failure). Default 3600 (1 hour). Persisted in BKPSRAM. Commands: GET, SET. Payload: data.uint_data. Role: CONFIG.

TIME_DIAG_MEASURE_LSE 46

RUN. Triggers an on-demand LSE-vs-HSE ppm measurement (~250 ms). Result is cached and returned on the next GET TIME_DIAGNOSTICS. Commands: RUN. Payload: none. Role: CONTROL.

BACKUP_DOMAIN_RESET_CANARY 47

RUN. Resets the boots_since_last_backup_loss counter to 0. Use after a deliberate battery replacement so the counter reflects only post-replacement boots. Commands: RUN. Payload: none. Role: CONFIG.

DALI_STATUS 48

GET-only. Returns the DALI system status summary (per-line online/fault device counts, bus-power errors, lowest faulting address, and missing/comms-error device bitmaps) — the same data the on-device Logic system evaluates for "any DALI error" actions. Use with the 'GET' AdminCommandType. Commands: GET. Payload: dali_status. Role: CONTROL. Devices: eDIDIO, ADDICT.

USER_ACCOUNT 49

SET-only (ADMIN clearance). Provisions a role's login secret (see AdminUserAccountMessage). Write-only — secrets are never returned by a GET. Commands: SET. Payload: user_account. Role: ADMIN.

STORAGE_DIAGNOSTICS 50

GET-only. Health of the shared SPI storage bus and everything on it: bus stall/reset counters, NOR flash program/erase fault state and presence/identity verdict, and — on variants fitted with an SD card — mount state, probe response, deadline-abort counters and the removal/power-cycle escalation state. Side-effect-free: every value is read from a RAM latch, nothing is probed. Use with the 'GET' AdminCommandType. Not in eDIDIO firmware 1.6.3, which answers UNEXPECTED_TYPE. Commands: GET. Payload: storage_diagnostics. Role: CONTROL.

WIFI_SETTINGS 51

GET/SET. Wi-Fi of a device with an ESP32 co-processor (ADDICT V3): access point only or access point + station, the station network and the access point channel. The station password is write-only - a GET never returns it. A SET replies before the device reconnects its Wi-Fi. See AdminWifiSettingsMessage. Commands: GET, SET. Payload: wifi_settings. Role: NONE. Devices: ADDICT.

WIFI_STATUS 52

GET-only. Live Wi-Fi state: station link and IP, the device's own access point (SSID, IP, connected clients) and both MACs. See AdminWifiStatusMessage. Commands: GET. Payload: wifi_status. Role: NONE. Devices: ADDICT.

WIFI_DIAGNOSTICS 53

GET-only. Wi-Fi link quality (station RSSI, channel, BSSID), co-processor version and restart counters, and command-pipeline health counters. Side-effect-free: every value is cached. See AdminWifiDiagnosticsMessage. Commands: GET. Payload: wifi_diagnostics. Role: NONE. Devices: ADDICT.

AdminCommandType

Used with AdminPropertyType

NameNumberDescription
SET 0

Set property

GET 1

Get property

ADD 2

Add property

REMOVE 3

Remove property

RESET 4

Reset property

RUN 5

Run property

WifiMode

Used with AdminWifiSettingsMessage / AdminWifiStatusMessage

NameNumberDescription
WIFI_MODE_AP 0

The device's own access point only

WIFI_MODE_AP_STATION 1

Its own access point, and it joins the station network as well

WifiStationState

Used with AdminWifiStatusMessage

NameNumberDescription
WIFI_STATION_DISCONNECTED 0

Not associated with the station network (or station mode is off)

WIFI_STATION_CONNECTED 1

Associated, no IP address yet

WIFI_STATION_GOT_IP 2

Associated, with an IP address

AdminWifiSettingsMessage

AdminMessage{GET / SET, WIFI_SETTINGS}. The access point is always the

device's own (on an ADDICT: "ADDICT_" with its per-unit password, printed

on the unit) and is not configurable here. Station IP settings (DHCP / static)

are AdminNetworkPropertiesMessage; the hostname is DEVICE_NAME.

FieldTypeLabelDescription
mode WifiMode

GET/SET

station_ssid string

GET/SET. Up to 32 printable ASCII characters, not " \ or a comma

station_password string

SET only, never returned. "" = an open network, else 8-32 printable ASCII characters (not " \ or a comma). Ignored when keep_station_password is set

keep_station_password bool

SET: true = keep the stored password (station_password ignored). GET: true = a station password is stored

ap_channel uint32

GET/SET. 2.4 GHz channel of the access point, 1-13. On a SET, 0 = keep

AdminWifiStatusMessage

AdminMessage{GET, WIFI_STATUS}

FieldTypeLabelDescription
running bool

The Wi-Fi co-processor is up (false: Wi-Fi switched off, or the unit started on battery)

mode WifiMode

Access point only, or access point + station

station_state WifiStationState

How far the station has got joining its network

station_ssid string

The network it joins (station mode)

station_ip string

Its address there; "" until it has one

ap_ssid string

Its own access point, e.g. "ADDICT_23"

ap_ip string

e.g. "192.168.8.1"

ap_clients uint32

Stations connected to its access point

station_mac string

Expected format: [40:D8:55:1B:XX:XX]

ap_mac string

MAC address of its own access point, "XX:XX:XX:XX:XX:XX"

AdminWifiDiagnosticsMessage

AdminMessage{GET, WIFI_DIAGNOSTICS}. Counters are since boot (uptime_seconds); diff two snapshots for a rate.

---- Station link (0 / "" while not associated) ----

FieldTypeLabelDescription
station_rssi sint32

dBm, e.g. -58

station_channel uint32

2.4 GHz channel of the station network

station_bssid string

The access point it is associated with, "XX:XX:XX:XX:XX:XX"

ap_channel uint32

Channel its own access point is actually on (in AP + station mode it follows the station's)

rssi_age_seconds uint32

How old station_rssi / station_channel / station_bssid are

coprocessor_version string

e.g. the ESP-AT "AT version:" line

uart_baud uint32

UART rate to the co-processor (921600, or 115200 if the handover fell back)

uptime_seconds uint32

Seconds since boot

coprocessor_restarts uint32

Co-processor reboots seen (each one re-initialised)

coprocessor_resets uint32

Hard resets after it stopped answering

station_disconnects uint32

Station links lost

station_join_failures uint32

Station joins that failed or timed out

tcp_clients uint32

TCP clients connected now

tcp_clients_max uint32

TCP client slots (4, or 3 while Art-Net / sACN holds one)

rx_overruns uint32

Receive bursts dropped: the staging buffers were full

at_retries uint32

Reads and sends the co-processor refused ("busy") and were retried

reply_timeouts uint32

Replies abandoned: the co-processor never asked for the data

replies_dropped uint32

Keep-alive / discovery replies skipped while another reply was in flight

reads_recovered uint32

Received data found unread that was never announced

rx_bytes_discarded uint32

Received bytes discarded: overflow, lost framing or an incomplete frame

AdminMessage

The Main AdminMessage used with the specific oneof message type.

FieldTypeLabelDescription
command AdminCommandType

What type of Command to run (GET / SET / etc.)

target AdminPropertyType

Which property to run the Command on

data PayloadMessage

A single value - the properties that use it say which PayloadMessage field

network_properties AdminNetworkPropertiesMessage

NETWORK_PROPERTIES and NTP_DETAILS

project_properties AdminProjectPropertiesMessage

SYSTEM_PROPERTIES

controller_lines AdminControllerLinesMessage

CONTROLLER_LINES

device_status AdminDeviceStatusMessage

DEVICE_STATUS

config_status AdminConfigStatusMessage

CONFIG_STATUS

device_time UpdateTimeMessage

DEVICE_TIME

dali_sensor_type AdminDALISensorTypeMessage

DALI_SENSOR_TYPE

dns_servers AdminDNSServersMessage

DNS

dmx_timing_mode AdminDMXGlobalTimingConfig

Applies to all lines

dmx_line_props AdminDMXLineParameters

One entry per active DMX line

memory_diagnostics AdminMemoryDiagnosticsMessage

Per-task stack HWMs + system/section memory usage

ethernet_diagnostics AdminEthernetDiagnosticsMessage

Ethernet PHY regs, Ethernet MAC counters, link-event ring buffer

line_diagnostics AdminLineDiagnosticsMessage

Per-line configured-vs-probed daughterboard type + coarse OK/FAULTY/EMPTY/MISCONFIGURED verdict

time_diagnostics AdminTimeDiagnosticsMessage

RTC/NTP/DST observability snapshot

dali_status AdminDaliStatusMessage

DALI system status summary (per-line device/fault counts + missing/comms-error bitmaps)

user_account AdminUserAccountMessage

Provision a role's login secret (USER_ACCOUNT, SET, ADMIN)

storage_diagnostics AdminStorageDiagnosticsMessage

Storage bus stalls/resets, NOR flash fault + presence state, SD mount/probe/deadline-abort counters

wifi_settings AdminWifiSettingsMessage

Wi-Fi mode, station network, AP channel (WIFI_SETTINGS, GET/SET)

wifi_status AdminWifiStatusMessage

Live Wi-Fi state (WIFI_STATUS, GET)

wifi_diagnostics AdminWifiDiagnosticsMessage

Wi-Fi link quality and health counters (WIFI_DIAGNOSTICS, GET)

Firmware update

FirmwareCommandType

The steps of a firmware update (FirmwareControlMessage), both directions.

NameNumberDescription
FW_READY 0

System Ready for Firmware Message

FW_APPLY 1

Sent to controller to initiate a Firmware update

FW_VERIFY 2

Sent to controller to initiate stored Firmware verification - This will complete the firmware upload mode and unlock normal functionality.

FW_VERIFY_FAILED 3

Received from controller - Issue with stored Firmware

FW_VERIFY_SUCCESS 4

Received from controller - Stored Firmware is Valid

FW_READ 5

Sent to controller to request information for currently stored Firmware

FW_CLONE 6

Command to Clone Main FW to Backup. Using the firmware_is_backup flag will clone Backup to Main

DataMessage

Simple free-form binary data blob that can be used for chunk transfer.

FieldTypeLabelDescription
identifier uint32

A free-form number that indicates exactly what type of data is being dealt with. Eg. 0x99 may indicate a firmware flash.

seq uint32

The message position in the sequence.

count uint32

The expected total number of DataMessages to be sent. When seq == count, you know you've got the last chunk and can go ahead and process the data (eg. flash firmware).

data uint32 repeated

The data, one byte (0-255) per element

FirmwareMetaMessage

Firmware Update Meta Message. Contains information on new incoming firmware. Sending this message begins the update process and will ERASE the currently stored firmware

FieldTypeLabelDescription
firmware_version uint32

MSB.XXX.LSB

firmware_date uint32

Day/Month/Year Compiled - Deprecated, use tag = 10, 11, 12

firmware_date_upload uint32

Day/Month/Year Uploaded - Deprecated, uses controller time

firmware_checksum uint32

Checksum to verify data

firmware_chunk_count uint32

Number of stored chunks

firmware_base_address uint32

Base Address of the Firmware

firmware_end_address uint32

End Address - For sector erases

firmware_is_backup bool

Flag to send Firmware to 'Backup' Location

nonce uint32 repeated

Decryption Nonce

firmware_date_day uint32

Day in Firmware File

firmware_date_month uint32

Month in Firmware File

firmware_date_year uint32

Year in Firmware File

signature bytes

Optional image signature over the staged chunk stream (raw bytes). Absent => unsigned image.

firmware_format uint32

Optional encrypted-firmware (V3) fields. Absent, or firmware_format==0, means a classic image. 0 = classic, 3 = encrypted (V3)

kem_alg uint32

Content-key wrap algorithm identifier

content_alg uint32

Chunk-payload cipher identifier

content_iv bytes

16-byte base initialisation vector

wrapped_content_key bytes

Wrapped content key (raw bytes)

FirmwareControlMessage

Reply from eDIDIO, or command from program. eDIDIO will check firmware before 'Apply'

FieldTypeLabelDescription
cmd FirmwareCommandType

The step: from the client READY / APPLY / VERIFY / READ / CLONE, from the device the verify result

firmware_is_backup bool

Flag used for FW_READ, FW_VERIFY, and FW_CLONE. Does not work for FW_APPLY

FirmwareChunkMessage

Chunk of firmware to be sent via a 256 byte payload

FieldTypeLabelDescription
firmware_address uint32

Offset of this chunk in the image, bytes

total_bytes uint32

Size of the whole image, bytes

payload DataMessage

The chunk (up to 256 bytes)

System logging

SystemLogReadMessage

Message sent to read the logs. The start address is offset for how many logs are requested. Up to 32 logs are sent in one message.

FieldTypeLabelDescription
log_start_address uint32

Which log to start from

logs_requested uint32

How many logs requested? Max of 32

logs SystemLogMessage repeated

Array of requested logs

SystemLogMessage

Individual Log packet containing oneof log type of information. Logs are timestamped using the timesinceboot parameter. The boot packet will provide the time of boot, so exact times can be extracted

FieldTypeLabelDescription
time_since_boot uint32

Time since boot (From latest power message)

boot SystemLogBoot

The device started

netlink SystemLogNetLink

The Ethernet link went up or down

ntp SystemLogNTP

The clock was set from NTP

trigger SystemLogTrigger

A trigger ran

spektra SystemLogSpektra

Spektra started, stopped or paused something

schedule SystemLogSchedule

An alarm fired

userstart SystemLogUserStart

The logs were started or reset by a user

SystemLogBoot

Message for Log Boot Type

FieldTypeLabelDescription
timeclock TimeClockMessage

The clock at boot

flags uint32

Boot flags (bitmask)

Message for Log Netlink Type

FieldTypeLabelDescription
is_linked bool

true: link up; false: link down

SystemLogNTP

Message for Log NTP Type

FieldTypeLabelDescription
timeclock TimeClockMessage

The time set

SystemLogTrigger

Message for Log Trigger Type

FieldTypeLabelDescription
trigger TriggerMessage

The trigger that ran

source ReadType

What fired it, as a ReadType (INPUTS, SENSOR, LIST, ...)

SystemLogSpektra

Message for Log Spektra Type

FieldTypeLabelDescription
action SpektraActionType

Start, stop or pause

type SpektraTargetType

Sequence or theme

index uint32

Which one, 0-based

SystemLogSchedule

Message for Log Schedule Type

FieldTypeLabelDescription
index uint32

Which alarm, 0-based

isStart uint32

1: its start trigger; 0: its end trigger

second uint32

Time it fired: seconds

minute uint32

Time it fired: minutes

hour uint32

Time it fired: hours

SystemLogUserStart

Message for Log User Start Type

FieldTypeLabelDescription
timeclock TimeClockMessage

When

flags uint32

Which logs were reset (bitmask)

SystemMetaDataReadMessage

Message to contain system metadata for debugging purposes

FieldTypeLabelDescription
input_press_counter uint32 repeated

Max 24 Inputs

list_start_counter uint32 repeated

Max 32 Lists

schedules_counter uint32 repeated

Max 10 Alarms

screen_on_time uint32

Time in seconds

screen_dim_time uint32

Time in seconds

screen_saver_time uint32

Time in seconds

reboot_counter uint32

Number of reboots since Data erased

Events

EventType

What an EventMessage reports. On an eDIDIO, live events are EventStreamMessage (event_stream).

NameNumberDescription
REGISTER 0

Sent by the client to register for events.

TRIGGER_EVENT 1

Emitted when trigger runs an action listed in TriggerType.

INPUT_EVENT 2

Emitted when a physical Input is triggered.

SENSOR_EVENT 3

Emitted when a Sensor (24-bit DALI or 25-bit) is triggered.

CONTROL_EVENT 4

Emitted when a DALI/DMX/physical output type event is done. References an action in TriggerType.

ROOM_JOIN_EVENT 5

Emitted when rooms are joined/unjoined.

DALI_24_INPUT_EVENT 6

Emitted when a 24-bit DALI Input Device is triggered.

DALI_24_FRAME_EVENT 7

Emitted when a 24-bit DALI Frame is received.

DALI24InputType

Input event types from DALI-2 (24-bit) input devices

NameNumberDescription
MOMENTARY_SHORT 0

Short button press (< 250ms)

MOMENTARY_LONG 1

Long button press (> 650ms)

LATCHED_LOW 2

Switch transitioned to closed/low state

LATCHED_HIGH 3

Switch transitioned to open/high state

POSITIONAL 4

Rotary encoder or slider position value

DALIMotionSensorStates

State machine for DALI motion sensor occupancy detection

NameNumberDescription
MOTION_IDLE 0

No occupancy detected, lights at idle/off level

MOTION_DISABLED 1

Sensor is muted or in deadtime period

MOTION_WARNING 2

Occupancy timeout reached, lights dimmed to warning level

MOTION_OCCUPANCY 3

Active occupancy detected, lights at occupied level

DALILuxSensorStates

State machine for DALI light level (lux) sensor daylight harvesting

NameNumberDescription
LUX_DISABLED 0

Daylight harvesting is inactive

LUX_ENABLED 1

Actively regulating to maintain target lux setpoint

LUX_DEVIATE 2

Light level has deviated significantly from setpoint

EventFilter

Message to set Event Filter Mask

FieldTypeLabelDescription
input bool

eDIDIO physical inputs

dali_arc_level bool

16-bit DALI Arc Level Commands

dali_command bool

16-bit DALI Commands

dali_sensor bool

DALI Sensors (24-bit and 25-bit)

dali_input bool

24-bit DALI Inputs

dmx_stream_changed bool

DMX output stream changes

dali_24_frame bool

Raw 24-bit DALI frames

trigger_message bool

High Level Trigger from Input/List/Sensor/Schedule

TriggerEvent

Message Response for Trigger Event

FieldTypeLabelDescription
type TriggerType

What type of Trigger occurred

level uint32

Associated level (if applicable)

dali_command DALICommandType

Associated DALI Command (if applicable)

target_address uint32

The target address for the TriggerType (if applicable)

line_mask uint32

The Line(s) on which the Trigger occurred (if applicable)

zone uint32

The zone of the Trigger (if applicable)

value uint32

The value of the Trigger (if applicable)

query_index uint32

The query_index of the Trigger (if applicable)

source uint32

The source of the trigger (input/list/sensor) (if applicable)

DALI24InputEvent

Message Response for DALI 24 Input Event

FieldTypeLabelDescription
index uint32

DALI input, 0-based

line uint32

DALI line it is on

address uint32

Its short address

type DALI24InputType

Momentary Short / Momentary Long / Latch Low / Latch High / Positional

arg uint32

Relevant information for the DALI24InputType

DALI24FrameEvent

Message Response for DALI 24 Frame Event

FieldTypeLabelDescription
line uint32

Which DALI Line within the eDIDIO (left -> right): 1, 2, 3, 4

frame uint32

The 24-bit Frame

DALISensorEvent

Message Response for DALI Sensor Event

FieldTypeLabelDescription
index uint32

Sensor, 0-based

line uint32

DALI line it is on

address uint32

Its short address

motion_state DALIMotionSensorStates

Idle / Disabled / Warning / Occupancy

lux_state DALILuxSensorStates

Disabled / Enabled / Deviate

lux_level uint32

Light level reported, lux

EventMessage

A message sent to a client when an event occurs. Depending on the event type (Trigger, Input or Sensor) different data is supplied with the event.

If a client sends an EventMessage with EventType of REGISTER then broadcast events out to the client.

FieldTypeLabelDescription
event EventType

What happened; sent by the client as REGISTER (ADDICT: to start or stop monitoring)

trigger TriggerEvent

TRIGGER_EVENT / CONTROL_EVENT: the trigger that ran

inputs InputStateResponse

INPUT_EVENT: the input state

payload PayloadMessage

A plain value, for events that carry one

sensor DALISensorEvent

OBSOLETE: JoinedRoomsMessage joined_rooms (5) --> No longer used

dali_24_input DALI24InputEvent

DALI_24_INPUT_EVENT: the input that fired

filter EventFilter

From the client: what to monitor (ADDICT: which 24-bit frames)

dali_24_frame DALI24FrameEvent

DALI_24_FRAME_EVENT: a 24-bit frame seen on the bus

SD card files (6-pole)

SdFileControlType

SD card file operations (SdFileControlMessage).

NameNumberDescription
SD_STAT 0

Get file info (size, date, time)

SD_GET_SPACE 1

Get free/total bytes on card

SD_DELETE 2

Delete a file (stub: returns ACCESS_DENIED until approved)

SD_WRITE_BEGIN 3

Begin upload session (creates temp file)

SD_WRITE_END 4

Finalize upload (rename temp -> target)

SD_WRITE_ABORT 5

Cancel upload (delete temp file)

SD_WRITE_RESUME 6

Resume interrupted upload (returns bytes already written to temp)

SdStatusCode

The result of an SD card operation.

NameNumberDescription
SD_OK 0

Success

SD_NOT_MOUNTED 1

No card, or it is not mounted

SD_FILE_NOT_FOUND 2

No such file

SD_ACCESS_DENIED 3

Not allowed (e.g. delete, until enabled)

SD_DISK_FULL 4

The card is full

SD_IO_ERROR 5

The card returned an error

SD_INVALID_PATH 6

The path is not valid

SD_BUSY 7

The card is in use - retry

SD_TIMEOUT 8

The card did not answer in time

SD_WRITE_ERROR 9

A write failed

SD_CAPACITY_UNKNOWN 10

The volume is mounted but its capacity has never been measured: every f_getfree() since the mount failed. Returned by SD_GET_SPACE instead of an SD_OK carrying free_bytes = total_bytes = 0, which is indistinguishable from a card with nothing left on it. A client seeing this should treat free space as unknown, not as zero.

SD_DEADLINE_ABORT 11

The operation was abandoned by the device's own per-operation deadline rather than failing on the media. Distinguishes a card that is too slow (or a bus that stalled) from one that is returning errors: the request may well succeed on a retry, where SD_IO_ERROR usually will not.

SdDirEntry

A single directory entry returned in SdDirListMessage

FieldTypeLabelDescription
name string

8.3 filename (max 12 chars + null)

size uint32

File size in bytes

date uint32

FAT date: ((year-1980)<<9)|(month<<5)|day

time uint32

FAT time: (hour<<11)|(min<<5)|(sec/2)

is_directory bool

true for a folder

SdDirListMessage

Browse SD card directory contents (paginated)

Request fields

FieldTypeLabelDescription
path string

Directory path, e.g. "logs/dali"

offset uint32

Skip this many entries (for pagination)

max_entries uint32

Max entries to return (device caps at 16)

status SdStatusCode

Response fields

entries SdDirEntry repeated

Directory entries

has_more bool

True if more entries available

SdFileReadMessage

Read a chunk of a file from the SD card

Request fields

FieldTypeLabelDescription
path string

File path, e.g. "logs/sys/SYS_0001.LOG"

offset uint32

Byte offset to start reading from

length uint32

Bytes requested (device caps at 512)

status SdStatusCode

Response fields

file_size uint32

Total file size (from f_stat at read time)

bytes_read uint32

Actual bytes returned in data

data bytes

File content chunk (max 512 bytes)

SdFileWriteMessage

Write a chunk of data to the SD card (during an upload session)

Request fields

FieldTypeLabelDescription
offset uint32

Byte offset for this chunk

data bytes

Data to write (max 512 bytes)

status SdStatusCode

Response fields

bytes_written uint32

Actual bytes written

SdFileControlMessage

File control operations (stat, delete, space, upload begin/end/resume)

FieldTypeLabelDescription
command SdFileControlType

Request fields

path string

File or directory path

expected_size uint32

For WRITE_BEGIN: expected total size (advisory)

status SdStatusCode

Response fields

file_size uint32

For STAT/WRITE_RESUME: file size in bytes

file_date uint32

For STAT: FAT date

file_time uint32

For STAT: FAT time

free_bytes uint64

For GET_SPACE

total_bytes uint64

For GET_SPACE

SdLogConfigMessage

Log category enable/disable configuration

FieldTypeLabelDescription
is_write bool

false=read config, true=write config

enabled_mask uint32

Bitmask: bit N = log category N enabled

api_version uint32

Client's API version

status SdStatusCode

Response fields

current_mask uint32

Current enabled mask after operation

category_count uint32

Number of log categories (11)

device_api_version uint32

Device's API version

SdLogStreamMessage

Live log streaming - subscribe to real-time log entries pushed by the device

Request fields (client -> device: subscribe/unsubscribe)

FieldTypeLabelDescription
subscribe bool

true=subscribe, false=unsubscribe

category_mask uint32

Bitmask of categories to stream

category uint32

log category value

timestamp_ms uint32

FreeRTOS tick count (milliseconds since boot)

rtc_time uint32

RTC seconds since 2000-01-01

payload bytes

Text log line or binary entry (DALI 12B / EVENT 35B)

sequence uint32

Monotonic sequence number (detects missed entries)

level uint32

Log level: 0=ERROR, 1=WARN, 2=INFO. Push only; binary categories write 0.

EventStreamMessage

===== Event Stream v2 (tag 77) — typed live event/log stream =====

Replaces SdLogStreamMessage (tag 69, deprecated) on the wire. Same transport,

sequence/timestamp/level observability and ISR-safe SD-independent producers,

but a TYPED, endian-safe, forward-compatible payload instead of raw C structs

memcpy'd into a bytes field. Runs on ALL hardware variants (not SD-specific).

Enum-valued fields are carried as uint32 (values documented inline) rather than

proto enums, for forward-compatibility (new firmware values decode as numbers on

old clients) and consistency across every discriminator in this family.

FieldTypeLabelDescription
subscribe bool

---- request (client -> device) ----

category_mask uint32

bit N = category N

level_threshold uint32

push text iff level <= threshold (0=ERR,1=WARN,2=INFO)

ack bool

true only on the subscribe/unsubscribe reply

sequence uint32

monotonic per-connection; gaps => dropped entries

timestamp_ms uint32

authoritative: producer tick, ms since boot

rtc_time uint32

seconds since 2000-01-01 (0 if RTC unset)

category uint32

log category value

level uint32

text severity; 0 for binary/structured categories

text string

text categories (0,2,4,5,6,7,8,9)

input InputEvent

An input was pressed

sensor SensorEvent

A sensor changed state

list ListEvent

A list ran a step

schedule ScheduleEvent

An alarm fired

config ConfigEvent

Configuration changed

boot BootEvent

The device started

net NetEvent

A link or connection changed

dali DaliFrame

raw frame + decoded envelope

raw bytes

forward-safe fallback: META/unknown types

spektra SpektraEvent

sequence/theme playback (EVT_TYPE_SPEKTRA)

command CommandEvent

standalone trigger/command (network, logic, IR, device, iRAD)

TriggerInfo

Trigger action embedded in Input/Schedule/List (matches what producers hold).

FieldTypeLabelDescription
trigger_type uint32

TriggerType enum

target_index uint32

Its target (address, group, list, sequence ...), as for TriggerMessage

value uint32

Its value (level, scene ...), as for TriggerMessage

line_mask uint32

The lines it acts on

InputEvent

An input was pressed (category: inputs). press_type means what source says: for physical inputs 0 short, 1 long, 2 latch low, 3 latch high; for DALI inputs 0 short, 1 long, 2 pressed, 3 released, 4 rotary.

FieldTypeLabelDescription
input_index uint32

Which input, 0-based

source uint32

ReadType: 0=GPIO, 15=DALI

press_type uint32

GPIO or DALI press type (per source)

action TriggerInfo

The trigger it ran

dali_line uint32

reclaimed (DALI inputs only; 0/absent for GPIO)

dali_address uint32

DALI inputs: the input device's short address (0 for physical inputs)

raw_arg uint32

raw rotary/positional value pre-transform

SensorEvent

A sensor changed state (category: sensors). transition: 1 occupancy, 2 warning, 3 off, 4 re-enabled after its deadtime, 5 light level, 6 override.

FieldTypeLabelDescription
sensor_index uint32

Which sensor, 0-based

transition uint32

sensor transition type

light_state uint32

The lights it controls: 0 off, 1 warning, 2 occupancy, 3 override

motion_state uint32

The motion detector: 0 idle, 1 disabled (deadtime), 2 warning, 3 occupancy

lux_value uint32

Light level, lux (0 if not reported)

dali_line uint32

reclaimed (available in the sensor struct)

dali_address uint32

The sensor's short address

ListEvent

A list ran a step (category: lists).

FieldTypeLabelDescription
list_index uint32

Which list, 0-based

step_index uint32

The step it ran

list_state uint32

0 disabled, 1 enabled, 2 looping, 3 random loop, 4 random withdrawn, 5 random withdrawn loop

action TriggerInfo

The step's action (line_mask is 0: list steps carry none)

ScheduleEvent

An alarm (schedule) fired (category: schedules).

FieldTypeLabelDescription
alarm_index uint32

Which alarm, 0-based

is_end bool

false: its start trigger ran; true: its end trigger

action TriggerInfo

The trigger that ran

ConfigEvent

Configuration was changed (category: config).

FieldTypeLabelDescription
read_type uint32

What changed, as a ReadType; 17 Spektra sequence, 18 theme, 19 zone settings, 20 calendar

item_index uint32

Which item, 0-based; 0xFF = all of them

source uint32

Who changed it: 0 network (a client), 1 BACnet, 2 the device's menu, 3 a profile change, 4 the firmware itself

profile_index uint32

The active profile at the time

ip bytes

The client's IPv4 address (4 bytes) when source is 0; zero otherwise

port uint32

The client's TCP port when source is 0; 0 otherwise

mac bytes

The client's MAC address (6 bytes) when source is 0; zero otherwise

BootEvent

The device started (category: boot).

FieldTypeLabelDescription
reset_cause uint32

Why it reset, a bitmask: bit0 power-on, bit1 software, bit2 independent watchdog, bit3 window watchdog, bit4 low power, bit5 reset pin

profile_index uint32

The profile active at boot

NetEvent

A network link or client connection changed (category: network).

FieldTypeLabelDescription
event uint32

0 link up, 1 link down, 2 TCP connect, 3 TCP disconnect, 4 TLS connect, 5 TLS disconnect, 6 / 7 keep-alive (AytMessage) on TCP / TLS, 8 / 9 legacy raw keep-alive (0xFF 0xF6) on TCP / TLS

ip bytes

The client's IPv4 address (4 bytes); zero for link events

port uint32

The client's port; 0 for link events

mac bytes

The client's MAC address (6 bytes); zero for link events

reason uint32

For a disconnect: 0 graceful, 1 idle timeout, 2 reset by peer, 3 closed by peer, 4 end of stream, 5 send failed, 6 TLS handshake failed, 7 TLS init failed, 8 socket setup failed, 9 link down, 10 no route, 11 not connected, 12 no free connection slot, 13 task creation failed, 255 other

SpektraEvent

Spektra sequence/theme playback event (EVT_TYPE_SPEKTRA).

FieldTypeLabelDescription
zone uint32

The Spektra zone, 0-based

action uint32

Spektra action: 1=START,2=STOP,3=PAUSE

target uint32

Spektra target: 1=SEQUENCE,2=THEME

index uint32

sequence/theme index

DaliFrame

One DALI frame seen or sent on a line (category: DALI bus).

FieldTypeLabelDescription
line uint32

0-3, 0xFF=META

direction uint32

0=TX,1=RX,0xFF=META

frame_type uint32

0=8b,1=16b,2=24b (or META subtype)

status uint32

TX: the send result (success, collision, timeout or error); RX: for an incomplete frame, how many bits were decoded; 0 for META entries

frame uint32

RAW frame bits (up to 24) — the deliberate raw payload

CommandEvent

A trigger/command executed by a non-input origin (network, logic, IR, device, iRAD).

The action is a plain TriggerInfo; `source` says where it came from. Reuses the

ConfigEvent precedent of discriminating origin with a field, not a message type.

The successor to legacy TRIGGER_EVENT / CONTROL_EVENT.

FieldTypeLabelDescription
source uint32

ReadType_*: 2=IR, 10=NETWORK, 11=DEVICE, 14=LOGIC, 255=iRAD/internal

action TriggerInfo

trigger_type, target_index, value, line_mask

zone uint32

trigger zone (0 if unused by this command)

query_index uint32

trigger query_index (0 if unused by this command)

ip bytes

Network-origin identity (source==NETWORK only; 0-len / 0 otherwise). Mirrors ConfigEvent.

port uint32

The client's TCP port when source is NETWORK; 0 otherwise

mac bytes

The client's MAC address (6 bytes) when source is NETWORK; empty otherwise

SdLogPolicyOp

What an SdLogPolicyMessage request does.

NameNumberDescription
SD_LOG_POLICY_GET 0

Read current policy table

SD_LOG_POLICY_SET 1

Validate + commit new policy table

SD_LOG_POLICY_RESET 2

Restore flash factory defaults

SdLogPolicyField

Identifies which field in a SET request failed validation. Returned in

SdLogPolicyMessage.invalid_field when status != SD_OK.

NameNumberDescription
SD_LOG_POLICY_FIELD_NONE 0

No field (the table is valid)

SD_LOG_POLICY_FIELD_CATEGORY 1

category index out of range or missing

SD_LOG_POLICY_FIELD_BUDGET_PERMILLE 2

budget_permille is out of range (0-1000)

SD_LOG_POLICY_FIELD_MAX_FILE_SIZE_KB 3

max_file_size_kb is out of range (32-32768)

SD_LOG_POLICY_FIELD_PRIORITY 4

priority is out of range (0-255)

SD_LOG_POLICY_FIELD_DUPLICATE 5

same category appears twice in a SET

SD_LOG_POLICY_FIELD_COUNT 6

wrong number of entries in a SET

SdLogPolicyEntry

The rotation policy for one log category.

FieldTypeLabelDescription
category uint32

log category value (0..category_count-1)

directory string

read-only (response)

prefix string

read-only (response)

extension string

read-only (response)

budget_permille uint32

0..1000

max_file_size_kb uint32

32..32768

priority uint32

0..255

current_disk_bytes uint32

read-only (response): bytes currently on disk for this category

SdLogPolicyMessage

Read, change or reset the SD card log rotation policy: how much of the card each log category may use, how big its files grow, and which is pruned first.

FieldTypeLabelDescription
op SdLogPolicyOp

Request fields

entries SdLogPolicyEntry repeated

For SET: full table (one per category)

status SdStatusCode

SD_OK or rejection reason

invalid_field SdLogPolicyField

Which field tripped validation (0 if ok)

invalid_category uint32

Which category's entry failed (0 if ok)

category_count uint32

Number of categories on the device

device_api_version uint32

1 = initial release

Connection status

ConnectionInfo

Per-connection details returned in ConnectionStatusMessage.

FieldTypeLabelDescription
ip_bytes bytes

4-byte IPv4 address of the connected client

port uint32

TCP source port of the connected client

mac_bytes bytes

6-byte MAC address; all-zero if ARP resolution failed

is_tls bool

True if this connection is TLS, false if plain TCP

ConnectionStatusMessage

Query active client connections.

Send with no fields populated to request current status.

The device responds with slot counts and per-connection details.

FieldTypeLabelDescription
max_connections uint32

Maximum simultaneous connections this device supports

active_count uint32

Number of currently active connections

connections ConnectionInfo repeated

Details for each active connection (active_count entries)

Crash log

CrashLogMessage

Read the crash/reset record captured from backup SRAM at boot.

The device captures a 128-byte crash record into battery-backed SRAM on

HardFault/MemManage/BusFault/UsageFault/stack overflow/watchdog/assert.

On the next boot, the record is held in RAM for network retrieval.

Request fields

FieldTypeLabelDescription
clear bool

If true, acknowledge/clear the pending crash record

has_crash bool

True if a crash was recorded before this boot

crash_type uint32

Crash type: 0=none,1=hardfault,2=memmanage,3=busfault, 4=usagefault,5=stack_overflow,6=watchdog,7=assert

reset_cause uint32

Reset cause, packed as a bitmask: bit0=POR, bit1=software, bit2=IWDG, bit3=WWDG, bit4=low_power, bit5=pin_reset

crash_data bytes

Full 128-byte crash record (binary, for detailed analysis — client decodes per struct layout)

task_name string

FreeRTOS task name at fault (convenience, max 7 chars)

pc uint32

Program counter at fault (convenience)

lr uint32

Link register at fault (convenience)

time_since_boot uint32

Uptime in seconds before crash

cfsr uint32

Cortex-M Configurable Fault Status Register (convenience)

boot_watchdog_flags uint32

Watchdog status captured from .noinit RAM at boot (only valid on IWDG resets). Bitmask of tasks that fed the watchdog before reset. Missing bits indicate which tasks stalled. 0 if the reset was not caused by IWDG.

firmware_version string

Running firmware version (e.g. "1.2.3")

commit_hash string

Git commit hash from the build system

build_date string

Build date/time string (e.g. "Apr 8 2026 14:30:00")

boot_rtc_timestamp uint32

RTC wall-clock time of the boot after the crash (same as the SD crash.log header timestamp). Combined with time_since_boot, the client can estimate when the crash actually occurred. RTC seconds since 2000-01-01 at this boot

task_hwm_data bytes

Per-task stack high-water-mark snapshot captured at boot from .noinit stacks. Binary per-task stack-HWM snapshot (up to 200 bytes). Always populated when available, regardless of whether a crash was recorded. Reflects the *previous* boot's stack usage.

Device provisioning

ProvisionState

Whether the device has a provisioned identity.

NameNumberDescription
PROVISION_STATE_UNPROVISIONED 0

Default: no identity; accepts InstallIdentity

PROVISION_STATE_PROVISIONED 1

Identity in flash; refuses re-provision (Decommission first)

ProvisionResult

The result of a provisioning request.

NameNumberDescription
PROVISION_RESULT_OK 0

Success

PROVISION_RESULT_ERR_PARSE 1

supplied identity failed to parse

PROVISION_RESULT_ERR_CHAIN 2

certificate chain did not validate

PROVISION_RESULT_ERR_UID_MISMATCH 3

certificate does not match this device's unique ID

PROVISION_RESULT_ERR_POP 4

key consistency check failed

PROVISION_RESULT_ERR_FLASH 5

identity store failed

PROVISION_RESULT_ERR_ALREADY_DONE 6

already PROVISIONED; Decommission first

ProvisionGetStateMessage

Tag 73: read identity state. Request is empty; response carries state/uid/fingerprint (all public).

FieldTypeLabelDescription
state ProvisionState

Response

uid bytes

Response: 96-bit unique device ID (12 bytes)

fingerprint bytes

Response: certificate fingerprint (32 bytes; empty if UNPROVISIONED)

ProvisionInstallIdentityMessage

Tag 74: install identity, uploaded as a CHUNKED stream (mirrors FirmwareChunkMessage). The host

sends a self-describing identity blob in <=256 B chunks; the device reassembles it and, on the

final chunk, validates the certificate chain, binds it to the device ID, and stores the identity.

FieldTypeLabelDescription
total_length uint32

Request: total identity-blob length (sent on every chunk)

offset uint32

Request: byte offset of this chunk within the blob

data bytes

Request: chunk payload (<=256 B)

last bool

Request: true on the final chunk -> validate + store

ok bool

Response

result ProvisionResult

Response

received uint32

Response: bytes accepted so far (resume/diagnostics)

ProvisionProofOfPossessionMessage

Tag 75: proof of possession. Request = {nonce}; response = {signature} (device signs the nonce).

FieldTypeLabelDescription
nonce bytes

Request: tool-supplied challenge

signature bytes

Response: signature over the nonce using the device's private key

ProvisionDecommissionMessage

Tag 76: decommission back to UNPROVISIONED (phase 2: authenticated). Response = {ok, result}.

FieldTypeLabelDescription
ok bool

Response

result ProvisionResult

Response

Other enumerations

SpektraStepActionType

What a Spektra step does.

NameNumberDescription
RUN_SEQUENCE 0

Run a sequence

SHOW_THEME 1

Show a theme

START_LIST 2

Start a list

PAUSE_PREVIOUS 3

Pause what the previous step started

STOP_PREVIOUS 4

Stop what the previous step started

LogicType

Types of conditions that can be evaluated in Logic rules

NameNumberDescription
DALI_LEVEL 0

Compare against a DALI device's arc level (0-254)

INPUT_STATE 1

Compare against a physical input's current state (HIGH/LOW)

LIST_RUNNING 2

Check if a specific List is currently running

OCCUPANCY_DETECTED 3

Check if a sensor has detected occupancy

DMX_PRESENT 4

Check if DMX input signal is being received

CAL_WEEKDAY 5

Compare against current day of week (1=Monday to 7=Sunday)

CAL_MONTH 6

Compare against current month (1=January to 12=December)

ALARM_SCHEDULED 7

Check if a specific alarm/schedule is active

DALI_CACHE_STATUS 8

Checks if any DALI device in the cache has an error status

HAS_ERROR 9

Check device error flags. target_index is bitmask: [bit0=DALI Poll Error, bit1=DALI Line Error, bit2=Ethernet Link Dropped, bit3=Over Temperature, bit4=OLED Error, bits5-7=Reserved]

SystemLogType

Categories of events recorded in the system log

NameNumberDescription
BOOT 0

Device power-on or reboot event

NET_LINK 1

Ethernet link state change (connected/disconnected)

NTP 2

NTP time synchronization event

TRIGGER 3

Trigger action executed (input, schedule, or external)

SPEKTRA 4

Spektra sequence/theme state change

SCHEDULE 5

Scheduled alarm triggered

USER 6

User changed logging level configuration

CRASH 7

Crash record summary (crash_type, PC, CFSR, LR low-16)

WATCHDOG_RESET 8

Watchdog-triggered reset

CRASH_EXT 9

Extended crash data (SP, watchdog_flags, task_name)

Scalar Value Types

.proto TypeNotesC++JavaPythonGoC#PHPRuby
double double double float float64 double float Float
float float float float float32 float float Float
int32 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. int32 int int int32 int integer Bignum or Fixnum (as required)
int64 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. int64 long int/long int64 long integer/string Bignum
uint32 Uses variable-length encoding. uint32 int int/long uint32 uint integer Bignum or Fixnum (as required)
uint64 Uses variable-length encoding. uint64 long int/long uint64 ulong integer/string Bignum or Fixnum (as required)
sint32 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. int32 int int int32 int integer Bignum or Fixnum (as required)
sint64 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. int64 long int/long int64 long integer/string Bignum
fixed32 Always four bytes. More efficient than uint32 if values are often greater than 2^28. uint32 int int uint32 uint integer Bignum or Fixnum (as required)
fixed64 Always eight bytes. More efficient than uint64 if values are often greater than 2^56. uint64 long int/long uint64 ulong integer/string Bignum
sfixed32 Always four bytes. int32 int int int32 int integer Bignum or Fixnum (as required)
sfixed64 Always eight bytes. int64 long int/long int64 long integer/string Bignum
bool bool boolean boolean bool bool boolean TrueClass/FalseClass
string A string must always contain UTF-8 encoded or 7-bit ASCII text. string String str/unicode string string string String (UTF-8)
bytes May contain any arbitrary sequence of bytes. string ByteString str []byte ByteString string String (ASCII-8BIT)