10. Event-Stream-Listener
Verbindet sich mit dem Events-Kanal (Port 10020) und gibt Systemereignisse aus, optional gefiltert nach Schweregrad, Namensmuster und Ausschlüssen. Nur lesend — kein Sitzungsprofil, es werden keine Befehle gesendet.
Was Sie lernen:
- Abonnieren des Events-WebSocket (Port
10020) als passiver Beobachter - Parsen des Event-JSON —
level,name,category,data,message - Filtern nach minimalem Schweregrad
- Namensabgleich mit Platzhaltern und Ausschluss
- Dieses Tutorial zusammen mit einem beliebigen anderen Tutorial nutzen, um den Regelkreis zu benchmarken
Ablauf
- CLI-Flags parsen (
--level,--name,--exclude,--no-hide-rate,--port). - Verbindung zu
ws://localhost:10020herstellen (der Events-Kanal) — es wird kein Sitzungsprofil gesendet, da es sich um einen rein lesenden Beobachter handelt. - Für jede eingehende Nachricht den Event-JSON parsen und die Filter anwenden:
- Verwerfen, wenn
levelunter dem minimalen Schweregrad liegt. - Wenn
--name-Muster angegeben sind, verwerfen, sofern keines zutrifft (entweder gegennameallein oder gegencategory/name). - Wenn ein
--exclude-Muster zutrifft, verwerfen.
- Verwerfen, wenn
- Verbleibende Ereignisse mit Schweregrad, qualifiziertem Namen, optionaler Meldung und optionaler
data-Nutzlast ausgeben.
Parameter
| Flag | Standard | Zweck |
|---|---|---|
--port | 10020 | Port des Event-Kanals |
-l, --level | info | Minimaler Schweregrad — einer von info, notice, warning, error, critical, panic |
-n, --name | (keiner) | Nur Ereignisse anzeigen, die dem Muster entsprechen (Glob, wiederholbar) |
-x, --exclude | (keiner) | Ereignisse ausblenden, die dem Muster entsprechen (Glob, wiederholbar) |
--no-hide-rate | false | system-rate-report-Ereignisse einbeziehen (standardmäßig ausgeblendet — erzeugt sehr viele Ausgaben) |
Führen Sie ein beliebiges Tutorial (04-hello-floor, 05-position-control, 06-combined...) in einem Terminal aus und den Event-Listener mit --no-hide-rate in einem anderen. Das Ereignis system-rate-report enthält die effektive Taktrate des Geräts. Vergleichen Sie die Varianten Python / C++ nlohmann / C++ Glaze desselben Tutorials, um den Serialisierungsaufwand bei einem Regelkreis von etwa 4 kHz zu beobachten.
# Terminal 1 — pick a variant
./04-haply-inverse-hello-floor # C++ nlohmann
./04-haply-inverse-hello-floor-glz # C++ Glaze
python 04-haply-inverse-hello-floor.py # Python
# Terminal 2 — watch the rate
./10-haply-inverse-events --no-hide-rate
Gelesene Zustandsfelder
Jede eingehende Nachricht ist ein einzelnes Ereignis:
level— Schweregrad als Zeichenkette (info...panic)name— Ereignisname (z. B.device-connected,system-rate-report)category— Kategorie (z. B.device,session,system)message— optionale, für Menschen lesbare Zeichenkettedata— optionale verschachtelte JSON-Nutzlast (Form hängt vom Ereignis ab)
Vollständiger Ereigniskatalog: Events & Monitoring.
Senden / Empfangen
Passives Abonnement — nur recv() wird verwendet; es wird nichts zurückgesendet. Alle drei Varianten implementieren dieselbe Filterpipeline; der interessante, Inverse-API-spezifische Teil ist die Form des Ereignisobjekts.
- Python
- C++ (nlohmann)
- C++ (Glaze)
async for msg in websocket ist die kürzeste Form der reinen Empfangsschleife.
async with websockets.connect(uri) as websocket:
async for msg in websocket:
try:
event = json.loads(msg)
except json.JSONDecodeError:
continue
if accept_event(event, min_level_index, name_patterns, exclude_patterns):
print(format_event(event))
libhv-Callback-Modell — onmessage läuft im I/O-Thread; der Hauptthread blockiert, bis ENTER gedrückt wird. Ereignisse werden als untypisierte JSON-Daten behandelt — jedes Feld wird über .value(...) mit einem Standardwert gelesen.
ws.onmessage = [&](const std::string &msg) {
json event;
try { event = json::parse(msg); } catch (...) { return; }
if (accept_event(event, opts.min_level, opts.name_patterns, opts.exclude_patterns))
print_event(event);
};
ws.open("ws://localhost:10020");
while (std::cin.get() != '\n') {} // block main thread
Die bekannten Ereignisfelder werden auf eine typisierte event_data-Struktur abgebildet. Das Feld data bleibt als glz::raw_json_view erhalten, sodass beliebig verschachtelte Nutzlasten (die vom Ereignis abhängen) unverändert weitergegeben werden können, ohne ein vollständiges Schema definieren zu müssen.
// Struct model — known fields typed, nested `data` kept as raw JSON
struct event_data {
std::string level;
std::string name;
std::string category;
std::string message;
glz::raw_json_view data{};
};
// Send / receive
ws.onmessage = [&](const std::string &msg) {
event_data event{};
if (glz::read<glz_settings>(event, msg)) return; // drop malformed
if (accept_event(event, opts.min_level, opts.name_patterns, opts.exclude_patterns))
print_event(event);
};
ws.open("ws://localhost:10020");
while (std::cin.get() != '\n') {} // block main thread
Tutorial 10 wird ebenfalls lokal mit dem SDK installiert — Sie finden es unter tutorials/10-haply-inverse-events/ im Installationsverzeichnis des Dienstes.
Quelle: Python · C++ · C++ Glaze
Verwandte Themen: Events & Monitoring · WebSocket-Protokoll