MQTT / WAN Protocol Reference
DFACS communicates with the DFACSWAN cloud portal via MQTT over TLS. Each device subscribes and publishes to topics namespaced by its DEVICE_ID.
Broker: portal.dragonflyacs.ai:8883 (TLS)
Topic prefix: dfacs/{DEVICE_ID}/ or dfacswan/instance/{DEVICE_ID}/
Connection Behaviour
- Auto-reconnects on disconnect with exponential backoff: starts at 5s, caps at 300s
- Heartbeat published every 30 seconds
- 5 missed heartbeat ACKs triggers a WAN settings revert to defaults
- Firebase config loaded in memory only — never persisted to disk
Topics — Device Subscribes (Portal → Device)
Commands
| Topic |
Description |
dfacs/{DEVICE_ID}/command |
Portal-issued commands (see Commands section) |
dfacs/{DEVICE_ID}/config/update |
Remote config push |
dfacs/register/response/{DEVICE_ID} |
Registration acknowledgment |
dfacs/{DEVICE_ID}/heartbeat/ack |
Heartbeat acknowledgment |
User Sync
| Topic |
Description |
dfacswan/instance/{DEVICE_ID}/users/update |
Add or modify a single user |
dfacswan/instance/{DEVICE_ID}/users/revoke |
Deactivate a user |
dfacswan/instance/{DEVICE_ID}/users/sync |
Full user list replacement |
Schedule Sync
| Topic |
Description |
dfacswan/instance/{DEVICE_ID}/schedules/push |
Door and holiday schedule push |
dfacswan/instance/{DEVICE_ID}/schedules/sync/ack |
ACK/NACK for schedule push |
Alcatraz
| Topic |
Description |
dfacs/{DEVICE_ID}/alcatraz/profile/deleted |
Profile removal notification |
dfacs/{DEVICE_ID}/alcatraz/credential/deleted |
Card/badge deletion |
dfacs/{DEVICE_ID}/alcatraz/credential/added |
Card/badge addition |
dfacs/{DEVICE_ID}/alcatraz/profiles/synced |
Trigger local profile re-sync |
dfacs/{DEVICE_ID}/alcatraz/enrollment/lookup |
Enrollment barcode lookup request |
dfacs/{DEVICE_ID}/image/request |
Request Alcatraz event image |
Audit
| Topic |
Description |
dfacswan/instance/{DEVICE_ID}/audit_event |
Portal audit log entry |
Topics — Device Publishes (Device → Portal)
Status & Registration
| Topic |
Description |
dfacs/register |
Initial registration with device metadata |
dfacs/{DEVICE_ID}/status |
System status update |
dfacs/{DEVICE_ID}/heartbeat |
Periodic health update (every 30s) |
dfacs/{DEVICE_ID}/command/response |
Response to a portal command |
User Sync ACK
| Topic |
Description |
dfacswan/instance/{DEVICE_ID}/users/ack |
ACK/NACK for user updates |
Schedule Sync
| Topic |
Description |
dfacs/{DEVICE_ID}/schedules/ack |
ACK/NACK for schedule push |
dfacs/{DEVICE_ID}/schedules/sync |
Push local schedule changes to portal |
Alcatraz
| Topic |
Description |
dfacs/{DEVICE_ID}/alcatraz/enrollment/lookup/response |
Member email/name for enrollment |
dfacs/{DEVICE_ID}/image/response |
Base64-encoded event image |
Registration
Published to dfacs/register on startup.
{
"device_id": "dfacs-aabbccdd",
"timestamp": "2026-05-26T14:30:00Z",
"friendly_name": "Main Gym Door",
"version": "4.1.5",
"local_ip": "192.168.1.100",
"mac_suffix": "aabbccdd",
"api_type": "zenoti",
"relay_type": "dragonfly"
}
Heartbeat
Published to dfacs/{DEVICE_ID}/heartbeat every 30 seconds.
{
"timestamp": "2026-05-26T14:30:00Z",
"device_id": "dfacs-aabbccdd",
"friendly_name": "Main Gym Door",
"version": "4.1.5",
"api_type": "zenoti",
"uptime_seconds": 86400,
"relay_state": "locked | unlocked | unknown",
"failsafe_active": false,
"memory_percent": 45.2,
"cpu_percent": 12.5,
"disk_percent": 72.1,
"pending_checkins": 0,
"schedule_hash": "abc123def456",
"schedule_status": "open | closed | modified"
}
Access Log Event (Check-in)
Published to dfacs/{DEVICE_ID}/status after each scan.
{
"barcode": "1234567890",
"timestamp": "2026-05-26T14:30:00Z",
"result": "Allowed",
"reason": null,
"first_name": "Jane",
"last_name": "Smith",
"membership_type": "Premium"
}
result is "Allowed" or "Denied". reason is null on allowed, or a denial reason string on denied.
Commands
The portal sends commands to dfacs/{DEVICE_ID}/command. Each command has a command field and optional parameters.
Door Control
| Command |
Parameters |
Description |
open |
duration (int, seconds) |
Unlock door for N seconds |
lock |
— |
Lock relay |
unlock |
— |
Permanently unlock relay |
failsafe |
enable (bool) |
Toggle fail-safe feature |
Data Retrieval
| Command |
Parameters |
Description |
get_status |
— |
Return relay state + system metrics |
get_config |
— |
Return all config settings |
get_access_logs |
limit (int) |
Return recent access logs |
get_audit_events |
limit (int) |
Return system audit events |
get_denied_barcodes |
— |
Return full blocklist |
get_barcodes |
limit, offset, search |
Paginated vendor barcode list |
get_checkin_queue |
— |
Return pending offline check-ins |
get_checkin_history |
limit (int) |
Return sent check-in history |
get_system_logs |
limit, level, after |
Return application logs |
get_event_viewer |
lookback_minutes (int) |
Windows Event Viewer logs |
get_table_checksums |
— |
Row counts for sync verification |
get_schedules |
— |
Return all access schedules |
get_membership_types |
— |
Return available membership type filters |
get_access_restrictions |
— |
Return current membership allow/deny lists |
Sync & Data Management
| Command |
Parameters |
Description |
sync_barcodes |
— |
Force immediate barcode sync |
save_schedule |
schedule (object) |
Create or update an access schedule |
delete_schedule |
id (int) |
Delete an access schedule |
set_access_restrictions |
allowed (list), denied (list) |
Update membership type filters |
Published to dfacs/{DEVICE_ID}/command/response:
{
"command": "get_status",
"success": true,
"data": { ... },
"error": null,
"timestamp": "2026-05-26T14:30:00Z"
}
User Sync Payloads
Add/Update User
{
"firebase_uid": "uid_abc123",
"email": "[email protected]",
"first_name": "Jane",
"last_name": "Smith",
"role_name": "Operator",
"permissions": ["door.unlock", "access_logs.view"],
"is_active": true
}
Revoke User
{
"firebase_uid": "uid_abc123"
}
Full Sync
{
"users": [ { ...user object... }, ... ]
}
ACK response to dfacswan/instance/{DEVICE_ID}/users/ack:
{
"success": true,
"count": 12,
"error": null
}
Schedule Sync Payload
{
"door_schedules": [
{
"id": 1,
"name": "Business Hours",
"is_active": true,
"weekly_hours": {
"monday": [["06:00", "22:00"]],
"tuesday": [["06:00", "22:00"]],
"saturday": [["08:00", "18:00"]],
"sunday": []
}
}
],
"holiday_schedules": [
{
"id": 1,
"name": "Christmas",
"date": "2026-12-25",
"recurs_annually": true,
"override_type": "closed",
"deny_access_control": true
}
]
}