Skip to main content

Event Integration

The NE503 Event Bus is the device's internal publish/subscribe message hub. This page covers event protocols and access methods. For HTTP authentication and event-management requests, see RESTful API Reference; for app permissions, see App Reference.

1. Choose an access method

Access methodDefault endpointUse it forLocation
Python SDKunix:///run/aipc/event-bus.sockPublishing or subscribing inside a containerhailo_ipc_sdk.events.EventClient
gRPCSame endpoint, as exposed by deploymentC++, Go, or custom servicesevent.proto
REST/api/v1/events/topics, /api/v1/events/publishExternal topic queries or publishingAPI authentication required
WebSocket/api/v1/events/streamBrowser or external real-time consumersAPI authentication required
MQTT bridgeBridge-specificExisting MQTT platformsMaintain the bridge process yourself

If the device's internal gRPC TCP address is deployed on loopback, only the device itself can reach it. External hosts should use REST/WebSocket or an approved tunnel instead of assuming direct access.

2. Topic matching

Topics are hierarchical strings separated by /. The current matcher supports exact matches, single-level *, multi-level **, and the suffix form **/suffix.

Subscription expressionMatchesDoes not match
inference/model_a/mainThe exact topicinference/model_b/main
inference/*/maininference/model_a/maininference/model_a/sub/extra
inference/**inference/model_a/main and deeper topicsTopics outside inference/
**/detectionsAny topic ending in detections.../detections/raw

Wildcards match topics; they do not parse payloads for the subscriber. Narrow subscriptions for high-throughput applications, and choose queue_size, drop_old, and consumer speed deliberately.

3. Event message structure

The protocol is defined in platform/event-bus/proto/event.proto:

{
"topic": "app/alert",
"timestamp_ns": 1717545600000000000,
"source": "people_counting",
"event_id": "evt-1",
"payload": "{\"type\":\"person_detected\"}",
"payload_type": "json",
"metadata": {
"stream_id": "main"
}
}
FieldTypeDescription
topicstringTopic name
timestamp_nsuint64Timestamp in nanoseconds
sourcestringService name or application ID
event_idstringEvent ID; the publish response also returns an ID
payloadbytesJSON or another encoded payload
payload_typestringCommonly json; may also identify protobuf
metadatamap of string to stringOptional metadata

The Python SDK converts JSON payloads into the event.payload dictionary. A raw gRPC client must parse the payload according to payload_type. Publish requests also support persistent and ttl_ms.

Subscribe requests support topic, subscriber_id, filters, queue_size, and drop_old. The service exposes Publish, PublishBatch, Subscribe, Unsubscribe, topic queries, and statistics RPCs.

4. Event producers and topic shapes

Prefixes help locate a producer, but they are not a complete fixed enumeration:

ProducerSource-code topic shapeMeaning
App Managerapp/{eventType}App install, start, stop, and lifecycle events
Device Controldevice/{eventType}Device-control events
Normal AI Runtime resultsinference/{model_id}/{stream_id}Result path in grpc_service.cpp
AI Runtime auto-inference pathinference/{stream_id}Another result path in auto_infer.cpp
App-defined eventsApp-definedKeep names consistent with conventions such as app/{app_id}/...

The two AI Runtime paths in source do not have the same number of segments. When consuming inference events, inspect topics produced by the target build and use event.metadata or the payload to identify the model and stream. Do not hardcode a three-segment topic for every firmware version.

5. Python SDK: publish and subscribe

from hailo_ipc_sdk.events import EventClient


def main():
with EventClient() as events:
events.publish(
"app/people_counting/stats",
{"current_count": 2, "threshold": 10},
metadata={"stream_id": "main"},
)

for event in events.subscribe(
"app/**",
queue_size=100,
drop_old=True,
):
print(event.topic, event.payload, event.source)


if __name__ == "__main__":
main()

EventClient also provides publish_batch(), on_event(), unsubscribe(), list_topics(), get_topic_info(), get_stats(), and get_topic_stats(). Subscription is a blocking iterator; long-running apps should handle shutdown and call close().

5.1 Manifest permissions

Declare the topic range in app.yaml before an app uses Event Bus:

permissions:
events:
publish:
- app/people_counting/*
subscribe:
- inference/**

Publish and subscribe permissions are checked separately. Do not use a broad ** just for convenience unless the application genuinely needs every topic.

6. WebSocket: external real-time subscription

The event WebSocket path is:

wss://<device-ip>/api/v1/events/stream

Log in through REST first, then follow the authentication conventions in RESTful API Reference. Source starts the server-side event stream with a wildcard Event Bus subscription and forwards events to WebSocket clients; a topic filter appended to the URL is therefore not a substitute for client-side filtering. Filter by topic, source, or payload, and handle reconnects and duplicate events.

For device-internal app-to-app communication, prefer the SDK/gRPC Unix Socket. WebSocket is better suited to browsers, gateways, and external monitoring systems.

7. MQTT bridge

MQTT is not a native Event Bus protocol. A bridge subscribes to Event Bus and converts each event into an MQTT message:

import json
import os

import paho.mqtt.client as mqtt
from hailo_ipc_sdk.events import EventClient


mqtt_client = mqtt.Client(client_id=os.environ["MQTT_CLIENT_ID"])
mqtt_client.username_pw_set(
os.environ["MQTT_USERNAME"], os.environ["MQTT_PASSWORD"]
)
mqtt_client.connect(os.environ["MQTT_HOST"], int(os.environ.get("MQTT_PORT", "1883")))
mqtt_client.loop_start()

events = EventClient()
try:
for event in events.subscribe("**"):
payload = json.dumps({
"timestamp_ns": event.timestamp_ns,
"source": event.source,
"event_id": event.event_id,
"payload": event.payload,
"metadata": event.metadata,
})
mqtt_client.publish(f"ne503/{event.topic}", payload, qos=1)
finally:
events.close()
mqtt_client.loop_stop()
mqtt_client.disconnect()

Production bridges also need TLS, secret management, reconnects, QoS, and duplicate-event handling. Never place credentials in documentation examples or image source.

8. Three integration decisions

  1. Topic scope: subscribe to the smallest useful set to avoid filling queues with unrelated events.
  2. Message semantics: retain business objects, timestamps, and idempotency keys in the payload; do not rely only on receive time.
  3. Failure behavior: define reconnect, stale-message, duplicate-consumption, and downstream-outage behavior for SDK, WebSocket, and MQTT consumers.