10. Écouteur de flux d'événements
Se connecte à l' Chaîne Événements (Port 10020) et affiche les événements système, filtrés (en option) selon leur niveau de gravité, un modèle de nom et des exclusions. En lecture seule — pas de profil de session, aucune commande n'est envoyée.
Ce que vous apprendrez :
- S'abonner à la Événements - WebSocket (Port
10020) en tant qu'observateur passif - Analyser le Événement-JSON —
level,name,category,data,message - Filtrer par gravité minimale
- Comparaison de noms avec des caractères génériques et des exclusions
- Utilisez ce tutoriel en complément de n'importe quel autre tutoriel pour évaluer les performances de la boucle de régulation.
Déroulement
- Analyse des options CLI (
--level,--name,--exclude,--no-hide-rate,--port). - Lien vers
ws://localhost:10020restaurer (le Chaîne Événements) — Aucun profil de session n'est envoyé, car il s'agit d'un observateur en lecture seule. - Pour chaque message entrant, analyser le JSON de l'événement et appliquer les filtres :
- Rejeter si
levelqui se situe en dessous du seuil minimal de gravité. - Si
--name-Rejeter les cas mentionnés ci-dessous, dans la mesure où aucun ne s'applique (soit en violation denameseul ou contrecategory/name). - Si un
--exclude- Si cela s'applique, rejeter.
- Rejeter si
- Événements restants avec niveau de gravité, nom qualifié, message facultatif et
data- Afficher la charge utile.
Paramètres
| Drapeau | Standard | Objet |
|---|---|---|
--port | 10020 | Port des chaînes événementielles |
-l, --level | info | Gravité minimale — l'une des info, notice, warning, error, critical, panic |
-n, --name | (aucun) | Afficher uniquement les événements correspondant au modèle (glob, répétable) |
-x, --exclude | (aucun) | Masquer les événements correspondant au modèle (globale, répétable) |
--no-hide-rate | false | system-rate-report- Inclure les événements (masqués par défaut — génère un très grand nombre de messages) |
Exécutez l'un des tutoriels de votre choix (04-hello-floor, 05-position-control, 06-combined...) dans un terminal, puis définissez l'écouteur d'événements avec --no-hide-rate dans un autre. L'événement system-rate-report indique la fréquence d'horloge effective de l'appareil. Comparez les variantes Python / C++ nlohmann / C++ Glaze du même tutoriel afin d'observer la charge de sérialisation pour une boucle de régulation 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 reçu constitue un événement distinct :
level— Niveau de gravité sous forme de chaîne de caractères (info...panic)name— Nom de l'événement (par exemple,device-connected,system-rate-report)category— Catégorie (par exempledevice,session,system)message— facultatif, chaîne de caractères lisible par l'utilisateurdata— charge utile JSON imbriquée facultative (le format dépend de l'événement)
Catalogue complet des événements : Événements et surveillance.
Envoyer / Recevoir
Abonnement « Passives » — uniquement recv() est utilisé ; rien n'est renvoyé. Les trois variantes implémentent le même pipeline de filtrage ; la partie intéressante, spécifique à l'API inverse, réside dans la forme de l'objet événement.
- Python
- C++ (nlohmann)
- C++ (Glaze)
async for msg in websocket C'est la forme la plus courte de la boucle de réception pure.
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 dans le thread d'E/S ; le thread principal reste bloqué jusqu'à ce que la touche ENTRÉE soit enfoncée. Les événements sont traités comme des données JSON non typées — chaque champ est défini via .value(...) lu 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énements connus sont convertis en une structure typée event_data-Structure représentée. Le champ data reste comme glz::raw_json_view conservées, de sorte que des charges utiles imbriquées à volonté (qui dépendent de l'événement) puissent être transmises telles quelles, sans qu'il soit nécessaire de définir un 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 également installé localement avec le SDK — vous le trouverez sous tutorials/10-haply-inverse-events/ dans le répertoire d'installation du service.
Source : Python · C++ · C++ Glaze
Sujets connexes : Événements et surveillance · Protocole WebSocket