10. Écouteur de flux d'événements
Se connecte au canal d'événements (port 10020) et affiche les événements système, avec un filtrage facultatif par niveau, par motif de nom et par exclusion. Lecture seule — aucun profil de session et aucune commande envoyée.
Ce que vous apprendrez :
- S'abonner aux événements WebSocket (port
10020) en tant qu'observateur passif - Analyser un événement JSON —
level,name,category,data,message - Filtrer par niveau de gravité minimal
- Correspondance de noms avec caractères génériques, et exclusion
- Utiliser ce tutoriel pour évaluer les performances de la boucle de contrôle en parallèle avec n'importe quel autre tutoriel
Déroulement
- Analyser les options CLI (
--level,--name,--exclude,--no-hide-rate,--port). - Se connecter à
ws://localhost:10020(le canal d'événements) — aucun profil de session n'est envoyé, puisqu'il s'agit d'un observateur en lecture seule. - Pour chaque message entrant, analyser l'événement JSON et appliquer les filtres :
- Écarter le message si
levelest inférieur au niveau de gravité minimal. - Si des motifs
--namesont fournis, écarter le message sauf si l'un d'eux correspond (ànameseul ou àcategory/name). - Si un motif
--excludecorrespond, écarter le message.
- Écarter le message si
- Afficher les événements retenus avec leur niveau, leur nom qualifié, le message facultatif et la charge utile
datafacultative.
Paramètres
| Option | Valeur par défaut | Rôle |
|---|---|---|
--port | 10020 | Port du canal d'événements |
-l, --level | info | Gravité minimale — l'une des valeurs info, notice, warning, error, critical, panic |
-n, --name | (aucune) | N'afficher que les événements correspondant au motif (glob, répétable) |
-x, --exclude | (aucune) | Masquer les événements correspondant au motif (glob, répétable) |
--no-hide-rate | false | Inclure les événements system-rate-report (masqués par défaut, car très bavards) |
Lancez n'importe quel tutoriel (04-hello-floor, 05-position-control, 06-combined...) dans un terminal, et l'écouteur d'événements avec --no-hide-rate dans un autre. L'événement system-rate-report contient la fréquence de tick effective de l'appareil : comparez les variantes Python / C++ nlohmann / C++ Glaze d'un même tutoriel pour observer la surcharge de sérialisation sur une boucle de contrôle d'environ 4 kHz.
# 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
Champs d'état lus
Chaque message entrant correspond à un seul événement :
level— gravité sous forme de chaîne (info...panic)name— nom de l'événement (p. ex.device-connected,system-rate-report)category— catégorie (p. ex.device,session,system)message— chaîne lisible facultativedata— charge utile JSON imbriquée facultative (la structure dépend de l'événement)
Catalogue complet des événements : Événements et surveillance.
Envoi / réception
Abonnement passif — seule recv() est utilisée ; rien n'est renvoyé. Les trois variantes implémentent le même pipeline de filtrage ; la partie la plus spécifique à l'API Inverse est la structure de l'événement.
- Python
- C++ (nlohmann)
- C++ (Glaze)
async for msg in websocket est la forme la plus courte de la boucle de réception seule.
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))
Modèle de rappel libhv — onmessage s'exécute sur le thread d'E/S ; le thread principal se bloque en attendant ENTRÉE. Les événements sont traités comme des JSON non typés — chaque champ est lu via .value(...) avec une valeur par défaut.
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
Les champs d'événement connus sont mappés sur une structure event_data typée. Le champ data reste de type glz::raw_json_view, afin que des charges utiles imbriquées arbitraires (qui dépendent de l'événement) puissent être transmises telles quelles, sans définir de schéma complet.
// 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
Le tutoriel 10 est aussi installé localement avec le SDK — consultez tutorials/10-haply-inverse-events/ dans le répertoire d'installation du service.
Source : Python · C++ · C++ Glaze
Voir aussi : Événements et surveillance · Protocole WebSocket