Part 08 — Events and the Event CatalogLink to the section Part 08 — Events and the Event Catalog

On this page

Maturity: Draft · Profiles: S (mandatory set), C, N · Schema: univip.event.v0.2 (../schemas/event.schema.json)

8.1 ModelLink to the section 8.1 Model

An event is a discrete notification. Events are published on the session channel as type: "event" envelopes and are retrievable for a limited history via GET /events. Events are either stateless (something happened) or stateful (a condition became active and later cleared); stateful events carry state: ACTIVE | CLEARED and the same topic.

8.2 Envelope payloadLink to the section 8.2 Envelope payload

{
  "schema": "univip.event.v0.2",
  "event_id": "01J9ZC4B8X2V5N7P1Q3R6T9W0Y",
  "device_id": "urn:univip:acme:SN12345",
  "session_id": "flight-2026-10-15-1042",
  "topic": "vehicle.battery.low",
  "severity": "WARNING",
  "state": "ACTIVE",
  "timestamp": "2026-10-15T10:40:02.500Z",
  "source": { "component": "AIRCRAFT" },
  "data": { "battery_pct": 24, "threshold_pct": 25, "remaining_endurance_s": 310 },
  "related": { "command_id": null, "lease_id": null }
}
Member Required Description
event_id yes Unique, RECOMMENDED ULID
topic yes Dotted lowercase; standard topics begin vehicle.; vendor topics use reverse-DNS (com.acme.…)
severity yes DEBUG, INFO, WARNING, ERROR, CRITICAL
state stateful only ACTIVE, CLEARED
timestamp yes Time of occurrence
source.component yes AIRCRAFT, PAYLOAD, DOCK, CONTROLLER, GATEWAY, ANALYTICS, UNIVIP
source.payload_id if PAYLOAD/ANALYTICS
data yes (may be {}) Topic-specific object; standard topics define their members below
related MAY command_id, lease_id, media_id, stream_id

8.3 Standard catalogLink to the section 8.3 Standard catalog

M = mandatory for Profile S devices that can detect the condition. A device that cannot detect a condition (for example a gateway with no battery access) MUST omit the topic from events.topics in capabilities. In particular, a gateway that reaches the vehicle only over the link whose loss it would report cannot tell link loss from the vehicle falling silent: it raises vehicle.telemetry.stale and does not advertise vehicle.link.lost unless another component (a dock or controller) reports the link state.

Topic Profile Stateful Default severity data members
vehicle.device.online S M no INFO —
vehicle.device.offline S M no WARNING reason (VEHICLE_UNREACHABLE, GATEWAY_SHUTDOWN, POWER_OFF, MAINTENANCE, OTHER)
vehicle.device.capabilities_changed S M no INFO —
vehicle.telemetry.stale S M yes WARNING last_sample_at
vehicle.operation.predeploy S no INFO — (aerial: preflight checks begun)
vehicle.operation.started S M no INFO launch_position (a telemetry position object; aerial: take-off; underwater: dive/launch)
vehicle.operation.ended S M no INFO recovery_position (a telemetry position object), operation_time_s (aerial: landed; underwater: recovered)
vehicle.operation.state_changed S M no INFO from, to (vehicle_state enum)
vehicle.operation.mode_changed S no INFO from, to (vendor strings)
vehicle.operation.emergency S M yes CRITICAL kind (MOTOR_FAILURE, LOSS_OF_CONTROL, FORCED_LANDING, CRASH, OTHER), message
vehicle.battery.low S M yes WARNING battery_pct, threshold_pct, remaining_endurance_s
vehicle.battery.critical S M yes CRITICAL as above
vehicle.link.degraded S M yes WARNING signal_quality_pct, latency_ms
vehicle.link.lost S M yes CRITICAL last_contact_at, failsafe_action
vehicle.positioning.degraded S yes WARNING source, fix, satellites, hdop, horizontal_accuracy_m
vehicle.health.fault S M yes per fault code, message, component
vehicle.geofence.warning N yes WARNING distance_to_boundary_m
vehicle.geofence.breach N yes CRITICAL position, action
vehicle.altitude.limit N (AIR) yes WARNING altitude_agl_m, limit_agl_m
vehicle.depth.limit N (UNDERWATER) yes WARNING depth_m, limit_m
vehicle.navigation.returning_home S no WARNING reason (PILOT, CLIENT, LOW_BATTERY, LINK_LOST, GEOFENCE, LEAK, WEATHER, TRAFFIC, OBSTACLE, FAULT, OTHER)
vehicle.navigation.hold N no INFO reason
vehicle.navigation.waypoint_reached N no INFO mission_id, waypoint_index
vehicle.navigation.mission_state N no INFO mission_id, state (STARTED, PAUSED, RESUMED, COMPLETED, ABORTED)
vehicle.control.lease_granted C/N no INFO lease_id, scope, client_id, expires_at
vehicle.control.lease_released C/N no INFO lease_id, reason (RELEASED, EXPIRED, REVOKED, PREEMPTED)
vehicle.control.pilot_override N M yes WARNING lease_id
vehicle.command.accepted C/N no DEBUG command_id, type
vehicle.command.rejected C/N M no WARNING command_id, type, reason, message
vehicle.command.completed C/N no INFO command_id, type
vehicle.command.failed C/N M no ERROR command_id, type, reason, message
vehicle.camera.recording.started S no INFO payload_id, media_id
vehicle.camera.recording.stopped S no INFO payload_id, media_id, duration_s
vehicle.camera.snapshot C no INFO payload_id, media_id
vehicle.camera.stream.started S no INFO stream_id
vehicle.camera.stream.stopped S no INFO stream_id, reason (NO_VIEWERS, SHUTDOWN, SOURCE_ENDED, ERROR)
vehicle.camera.mode_changed C no INFO payload_id, from, to
vehicle.analytics.object.detected optional no INFO Part 12 target object
vehicle.analytics.object.lost optional no INFO target_id
vehicle.dock.state_changed optional no INFO from, to (CLOSED, OPENING, OPEN, CLOSING, CHARGING, FAULT)
vehicle.dock.fault optional yes ERROR code, message

8.4 Ordering and deliveryLink to the section 8.4 Ordering and delivery

  • Events are delivered in the order of occurrence per device. event_id ULIDs are time-sortable.
  • At-least-once delivery over the session channel. The device tracks, per configured endpoint, the last event it wrote to a session with that endpoint. After reconnection it MUST replay every event generated after that one, provided the disconnect lasted at most 15 minutes and produced at most 500 events; it MAY retain more. On the first session ever established with an endpoint nothing is replayed. Clients MUST deduplicate on event_id.
  • A stateful condition is identified by its condition key: the topic plus data.code (vehicle.health.fault, vehicle.dock.fault), else data.lease_id (vehicle.control.pilot_override), else source.payload_id, else the topic alone. A CLEARED event closes the ACTIVE event with the same condition key; at most one condition per key is active.
  • After every session establishment, the device MUST send each stateful event whose condition is still ACTIVE, with its original event_id. A client that kept its state drops it as a duplicate; one that lost its state learns the condition.

8.5 Standard fault codesLink to the section 8.5 Standard fault codes

Devices SHOULD use these codes in health.faults[].code and vehicle.health.fault: IMU_CALIBRATION, COMPASS_INTERFERENCE, BAROMETER_FAULT, GNSS_SPOOFING_SUSPECTED, MOTOR_FAULT, ESC_FAULT, BATTERY_TEMPERATURE, BATTERY_CELL_IMBALANCE, GIMBAL_FAULT, CAMERA_FAULT, STORAGE_FULL, OBSTACLE_SENSOR_FAULT, RADIO_INTERFERENCE, FIRMWARE_MISMATCH, OTHER.

8.6 ONVIF topic mappingLink to the section 8.6 ONVIF topic mapping

Annex A maps standard topics to ONVIF topic namespace equivalents for gateways that also expose ONVIF events (for example vehicle.camera.recording.started ↔ tns1:RecordingConfig/RecordingJobConfiguration where sensible, vehicle.health.fault ↔ tns1:Device/HardwareFailure/...). Where no ONVIF equivalent exists, gateways MUST use the tns1:Device/Trigger/… or a vendor namespace and MUST NOT misreport as an unrelated ONVIF topic.

8.7 MQTT 5 alternativeLink to the section 8.7 MQTT 5 alternative

When the real-time plane uses MQTT 5:

Content Topic
Telemetry univip/v1/{device_id}/telemetry
Events univip/v1/{device_id}/events/{topic with . replaced by /}
Command status univip/v1/{device_id}/commands/{command_id}/status
Signaling univip/v1/{device_id}/signal/{stream_id} (both directions, with direction member)
Lease updates univip/v1/{device_id}/leases/{lease_id}
Client → device commands univip/v1/{device_id}/commands/submit

Payloads are the same JSON envelopes as on the WebSocket channel. Telemetry uses QoS 0 with retained last sample; events and command status use QoS 1; vehicle.device.offline MUST be registered as the MQTT Will message. Topic aliases and user properties MAY be used; device_id MUST remain in the envelope regardless.

Generated from spec/08-events.md.