Aller au contenu

Référence des nœuds ​

Chaque type de nœud qu'une expérience peut contenir, dans les groupes du menu d'ajout : actions, attentes, émulation, défaillances, données, vérifications et flux. Comment les ajouter et les relier est expliqué dans L'éditeur ; signallab nodes imprime le même catalogue en JSON, pour les scripts et les assistants (La ligne de commande).

Lire cette page ​

Chaque nœud a un tableau de ses champs :

  • Champ est le nom dans le volet des propriétés ; Dans le fichier est la clé dans le JSON de l'expérience.
  • Défaut est ce qu'un nœud reçoit quand vous l'ajoutez dans l'éditeur. Là où un fichier peut omettre une clé, la valeur qu'il prend alors est donnée comme si absente ; les autres clés sont obligatoires dans un fichier.
  • Modèles : oui — le champ accepte des {{templates}} : paramètres, variables définies plus tôt, secrets et générateurs, résolus pendant que l'étape s'exécute (Données et modèles). Paramètres uniquement — il est ouvert avant la première étape, quand seuls les paramètres sont connus. Non — la valeur est prise telle qu'écrite.

Les durées sont en millisecondes. Les limites sont vérifiées avant qu'une exécution ne démarre ; un champ hors limites empêche l'expérience de s'exécuter et est signalé sur le nœud.

Un nœud dans un fichier ​

Dans un fichier d'expérience, un nœud est un objet avec un id (unique dans l'expérience), son type, sa place sur le canevas (x, y, zéro ou plus), ses champs, et les réglages qu'il utilise (retry, repeat, load, omis quand ils sont désactivés). Un fil est une arête allant de la sortie d'un nœud (port, next si absent) vers un autre nœud :

json
{
  "nodes": [
    { "id": "start", "type": "start", "x": 40, "y": 80 },
    { "id": "ping", "type": "udp", "x": 270, "y": 80, "target": "127.0.0.1:9000", "text": "PING",
      "retry": { "attempts": 3, "delay_ms": 500, "backoff": "fixed" } },
    { "id": "end", "type": "end", "x": 500, "y": 80 }
  ],
  "edges": [
    { "from": "start", "to": "ping", "port": "next" },
    { "from": "ping", "to": "end", "port": "next" }
  ]
}

Les exemples ci-dessous montrent un nœud chacun, tel qu'un fichier le contient.

Réglages partagés par de nombreux nœuds ​

Ils s'activent dans la partie basse des propriétés d'un nœud. Quel nœud accepte lequel est indiqué sous chaque nœud.

RéglageQui l'accepteCe qu'il fait
RéessaiLes nœuds qui envoient ou écoutent : Requête HTTP, Message TCP, Message OSC, Datagramme UDP, Publication MQTT, Connexion WebSocket, Envoi WebSocket, et chaque attenteRéessaie quand l'étape échoue
RépétitionLes nœuds qui envoient : Requête HTTP, Message TCP, Message OSC, Datagramme UDP, Publication MQTT, Envoi WebSocketEnvoie encore et encore, un certain nombre de fois ou pendant une durée
ChargeRequête HTTPEnvoie la requête selon un profil de charge, mesurée et jugée par des seuils
Attendre une réponseMessage OSC, Datagramme UDPEnvoie et attend la réponse dans la même étape

Réessai ​

réessayer en cas d’échec : quand l'étape échoue — pas de connexion, un délai d'attente, une attente sans rien qui corresponde — elle fait une pause et s'exécute de nouveau. Chaque tentative échouée est une ligne dans la chronologie ; l'étape échoue quand la dernière tentative échoue. Un modèle qui ne peut pas être résolu n'est pas réessayé. Arrêter met aussi fin à une pause.

ChampDans le fichierQuoiDéfaut et limites
Tentativesretry.attemptsTentatives au total, la première comprise3 ; 2–10 dans l'éditeur (un fichier peut aussi dire 1)
Pause, msretry.delay_msLa pause avant la deuxième tentative500 ; 0–60 000
Pausesretry.backoffidentiques (fixed) : la même pause à chaque fois ; qui doublent (exponential) : deux fois plus longue après chaque échecfixed (aussi si absent)

Aucune pause ne dépasse 60 secondes, quoi qu'il arrive au doublement. Une attente dont la sortie Expiré a un fil n'échoue pas sur un délai d'attente — elle sort par cette sortie — elle n'est donc pas réessayée alors.

Répétition ​

répéter l’envoi : le nœud envoie encore et encore — un battement, une interrogation, un flux régulier — sans boucle dans le graphe. Chaque envoi relit ses modèles ({{counter}} est son numéro, {{now}} son instant), et le Réessai, quand il est actif, s'applique à chaque envoi. L'étape réussit quand tous les envois ont réussi ; un envoi qui échoue définitivement fait échouer l'étape. La chronologie rapporte la progression au plus une fois par seconde.

ChampDans le fichierQuoiDéfaut et limites
Répéterrepeat.untilun nombre de fois (count) ou pendant une durée (duration)count (aussi si absent)
Foisrepeat.countEnvois au total, le premier compris10 (aussi si absent) ; 2–10 000
Pendant, msrepeat.duration_msCombien de temps continuer d'envoyer, à partir du premier envoi10 000 (aussi si absent) ; 1–300 000
Toutes les, msrepeat.interval_msLa pause entre deux envois1 000 ; 10–60 000 ; obligatoire dans un fichier
Gigue, msrepeat.jitter_msChaque pause jusqu'à autant plus longue, tirée de la graine de l'exécution0 (aussi si absent) ; 0–60 000

Les répétitions doivent tenir dans les 300 secondes d'une exécution, et pendant une durée doivent demander moins de 10 000 envois (sa durée divisée par l'intervalle).

Charge ​

envoyer sous charge, sur un Requête HTTP uniquement : la requête est envoyée selon un profil — un débit constant, une rampe, des paliers, un pic ou des arrivées aléatoires — avec jusqu'à 512 en vol en même temps (32 par défaut), et mesurée : latences, erreurs, débit atteint. Des seuils décident si l'étape réussit. La charge remplace la Répétition et le Réessai (une requête échouée est comptée, pas réessayée), et ne laisse aucune réponse pour les vérifications qui la suivent. Ses champs et résultats sont dans Tests de charge.

Attendre une réponse ​

attendre une réponse, sur un Message OSC ou un Datagramme UDP : le message est envoyé depuis le port sur lequel la réponse est attendue, si bien qu'un appareil qui répond à l'expéditeur est entendu, et l'étape ne réussit que quand une réponse correspondante arrive à temps. Aucune réponse fait échouer l'étape — le Réessai renvoie. La réponse est stockée dans une variable, comme celle d'une attente.

ChampDans le fichierQuoiDéfaut et limitesModèles
Réponse sur (IP:port)reply.bindIP:port depuis lequel envoyer et écouter ; le port 0 prend n'importe quel port libre0.0.0.0:0Non
Motif d’adresse de réponse (OSC)reply.addressLe motif d'adresse de la réponse, comme dans Attente OSC/*Oui
Règles d’arguments (OSC)reply.argsRègles d'arguments, comme dans Attente OSCaucune ; 16 au plusValeurs : oui
Charge utile de réponse (UDP)reply.modeany, contains, regex ou hex — voir Correspondance de charge utileany (aussi si absent)Non
Motif (UDP)reply.patternCe que la réponse doit contenir ou auquel elle doit correspondrevide ; obligatoire sauf pour anyOui
Délai d’attente, msreply.timeout_msCombien de temps attendre2 000 (aussi si absent) ; 1–120 000Non
Variable de réponsereply.variableLa variable dans laquelle la réponse est stockéereply (aussi si absent)Non

Le port de la réponse est ouvert avant la première étape, comme celui d'une attente.

Actions ​

Des nœuds qui envoient. Une attente après une action compte les messages à partir du moment où l'action a démarré.

Requête HTTP ​

Envoie une requête HTTP et conserve la réponse pour les vérifications, les bifurcations et les nœuds Extraire une valeur qui la suivent.

ChampDans le fichierQuoiDéfaut et limitesModèles
Méthoderequest.methodGET, HEAD, POST, PUT, PATCH, DELETE ou OPTIONS (un fichier peut nommer n'importe quelle méthode)GETNon
URLrequest.urlUne URL http:// ou https://http://127.0.0.1:8080/Oui
Délai d’attente (ms)request.timeout_msPour tout l'échange4 000 (10 000 si absent) ; 1–120 000Non
En-têtes de la requêterequest.headers[[name, value], …] ; une ligne avec un nom vide est ignoréeaucuneOui, noms et valeurs
Corpsrequest.bodyDu texte, ou null pour aucunnullOui
Authentificationrequest.authAucune, Basic, Jeton Bearer ou Digest, avec Nom d’utilisateur et Mot de passe, ou JetonaucuneOui
  • N'importe quelle réponse fait réussir l'étape, 404 et 500 compris : vérifiez le statut avec Statut HTTP ou bifurquez dessus avec Branche sur statut. Une requête qui n'obtient aucune réponse — refusée, un délai d'attente, un nom qui ne se résout pas, un certificat qui n'est pas approuvé — fait échouer l'étape.
  • Les redirections sont suivies, dix au plus. Les certificats https:// sont vérifiés.
  • Le corps de la réponse est conservé jusqu'à 256 Kio pour les vérifications ; un corps plus grand est coupé là (les vérifications le disent quand ce qu'elles cherchent peut se trouver après la coupure).
  • Digest répond au challenge 401 du serveur et renvoie la requête. Les identifiants n'entrent que dans la requête : les étapes, les rapports et l'Inspecteur ne montrent jamais l'en-tête Authorization. Écrivez un mot de passe comme {{secret.NAME}}.
  • Tant que l'expérience conserve les cookies (activé par défaut, sous Paramètres), ce que les serveurs définissent est renvoyé avec les requêtes ultérieures de l'exécution qui leur sont adressées.

Sorties : Sortie. Réglages : Réessai, Répétition, Charge.

json
{ "id": "cue", "type": "http", "x": 270, "y": 80,
  "request": { "method": "POST", "url": "{{api}}/cue", "headers": [["Content-Type", "application/json"]],
               "body": "{\"cue\": 1}", "timeout_ms": 5000,
               "auth": { "scheme": "bearer", "token": "{{secret.API_TOKEN}}" } } }

Voir aussi HTTP.

Message TCP ​

Se connecte à un hôte en TCP, écrit la charge utile, attend jusqu'à 250 ms les premiers octets d'une réponse (il lit au plus 1 024 octets, une seule fois) et ferme la connexion. La taille de la réponse est rapportée, pas vérifiée.

Dans l'Inspecteur l'étape est deux trames tcp avec la source experiment : la charge utile écrite et, quand elle est venue, la réponse lue. Les secrets utilisés sont masqués dans les deux, comme dans toute trame.

ChampDans le fichierQuoiDéfaut et limitesModèles
HôtehostUn nom d'hôte ou une adresse IP127.0.0.1Oui
Portport9000 ; 1–65 535Non
Délai d’attente (ms)timeout_msPour la connexion, l'écriture et la réponse ensemble4 000 (aussi si absent) ; 1–120 000Non
Charge utilepayloadLe texte écrit une fois connecté, en UTF-8helloOui

L'étape échoue quand la connexion est refusée, que le nom ne se résout pas ou que le temps s'écoule. Sorties : Sortie. Réglages : Réessai, Répétition. Envoyer maintenant se connecte et écrit la charge utile une fois, et le résultat du nœud indique combien d'octets ont été envoyés et sont revenus.

json
{ "id": "go", "type": "tcp", "x": 270, "y": 80, "host": "127.0.0.1", "port": 5000, "payload": "GO\r\n", "timeout_ms": 2000 }

Message OSC ​

Envoie un message OSC 1.0 en UDP.

ChampDans le fichierQuoiDéfaut et limitesModèles
Cible hôte:porttargetIP:port ou host:port ; un nom d'hôte est résolu quand l'étape envoie, son adresse IPv4 prise quand il en a une127.0.0.1:9000Oui
Adresse OSCaddressCommence par //testOui
Argumentsargs[{ "type", "value" }, …] — int, float, str, long, double, bool, blob (octets), nil (aucune valeur)aucuneValeurs texte (str) : oui
attendre une réponsereplyFacultatif : envoyer et attendre la réponse — voir Attendre une réponsedésactivé

Sorties : Sortie ; avec une réponse attendue, elle n'est suivie que quand la réponse est venue. Réglages : Réessai, Répétition, une réponse. ⚡ Faire passer par une dégradation dans ses propriétés place un Dégradation devant lui.

json
{ "id": "fader", "type": "osc", "x": 270, "y": 80, "target": "{{device}}", "address": "/fader/1",
  "args": [{ "type": "float", "value": 0.75 }] }

Voir aussi OSC.

Datagramme UDP ​

Envoie une charge utile texte comme un datagramme UDP à une ou plusieurs cibles.

ChampDans le fichierQuoiDéfaut et limitesModèles
Cible hôte:porttargetIP:port ou host:port ; plusieurs séparées par des virgules, des points-virgules ou des retours à la ligne reçoivent chacune le datagramme. Un nom d'hôte est résolu quand l'étape envoie, son adresse IPv4 prise quand il en a une127.0.0.1:9000Oui
Charge utiletextLa charge utile, en UTF-8hello ; 65 507 octets au plusOui
attendre une réponsereplyFacultatif : envoyer et attendre la réponse — voir Attendre une réponsedésactivé

L'étape échoue si une cible ne peut pas être atteinte. Sorties : Sortie. Réglages : Réessai, Répétition, une réponse.

json
{ "id": "ping", "type": "udp", "x": 270, "y": 80, "target": "{{device}}", "text": "PING {{run.id}}",
  "reply": { "bind": "0.0.0.0:0", "mode": "contains", "pattern": "PONG", "timeout_ms": 1000, "variable": "pong" } }

Publication MQTT ​

Se connecte à un broker MQTT, publie un message et se déconnecte. La connexion est MQTT 3.1.1 sur TCP simple, avec une session propre et sans nom d'utilisateur ni mot de passe. La connexion, la publication et l'accusé de réception du broker doivent tous se produire en 15 secondes.

ChampDans le fichierQuoiDéfaut et limitesModèles
Hôte du brokerhostLe nom d'hôte ou l'adresse du broker127.0.0.1Oui
Portport1883 ; 1–65 535Non
TopictopicAucun joker (+, #)lab/testOui
Charge utilepayloadLe message, en textehelloOui
QoSqos0, 1 ou 20Non
Retenir le messageretaintrue : le broker le conserve comme valeur du topicfalseNon

Les six clés sont obligatoires dans un fichier. L'étape échoue quand le broker ne peut pas être atteint ou refuse la connexion ou le message. Sorties : Sortie. Réglages : Réessai, Répétition.

json
{ "id": "light", "type": "mqtt", "x": 270, "y": 80, "host": "{{broker}}", "port": 1883,
  "topic": "lab/light/1/set", "payload": "on", "qos": 1, "retain": false }

Voir aussi MQTT.

Connexion WebSocket ​

Ouvre un WebSocket pour le reste de l'exécution, ou jusqu'à un Fermeture WebSocket. Ce qui arrive à partir de là est conservé pour les étapes Attente WebSocket qui s'y rapportent. L'URL et les en-têtes sont résolus quand l'étape s'exécute, si bien qu'un jeton extrait plus tôt peut s'y trouver. Exécutée de nouveau — dans une Boucle — elle ferme d'abord sa connexion précédente et en ouvre une nouvelle. Quand l'exécution se termine, de quelque façon que ce soit, ses connexions sont fermées par une trame de fermeture.

ChampDans le fichierQuoiDéfaut et limitesModèles
URLurlUne URL ws:// ou wss://ws://127.0.0.1:9001/Oui
En-têtes de la requêteheaders[[name, value], …] envoyées avec la requête de mise à niveauaucuneOui, noms et valeurs
Sous-protocolesprotocolsSous-protocoles à proposer, par ordre de préférence ; le serveur en choisit unaucunNon
Délai d’attente (ms)timeout_msPour la connexion et la mise à niveau5 000 (10 000 si absent) ; 1–120 000Non

wss:// approuve les mêmes certificats que https://. L'étape échoue quand la connexion ou la mise à niveau échoue ; le statut du serveur est dans la raison. Sorties : Sortie. Réglages : Réessai (pas Répétition).

json
{ "id": "socket", "type": "ws_connect", "x": 270, "y": 80, "url": "ws://127.0.0.1:9001/chat",
  "headers": [["Authorization", "Bearer {{token}}"]], "protocols": ["chat.v1"], "timeout_ms": 5000 }

Voir aussi WebSocket.

Envoi WebSocket ​

Envoie un message sur la connexion qu'un Connexion WebSocket a ouverte.

ChampDans le fichierQuoiDéfaut et limitesModèles
ConnexionconnectionL'id d'un nœud Connexion WebSocket de cette expériencele premierNon
FormatbinaryTexte (false), ou Binaire (hex) (true) : la charge utile est des octets écrits en hex, de ad be effalse (aussi si absent)Non
Charge utiletextLe messagehello ; 16 Mio au plusOui

La connexion doit précéder l'envoi sur son chemin ; un envoi dont la connexion n'est pas ouverte échoue. Les réponses comptent à partir du moment où le message est écrit. Sorties : Sortie. Réglages : Réessai, Répétition.

json
{ "id": "hello", "type": "ws_send", "x": 500, "y": 80, "connection": "socket",
  "text": "{\"type\":\"ping\",\"id\":\"{{uuid}}\"}", "binary": false }

Fermeture WebSocket ​

Ferme une connexion par une poignée de main de fermeture. La chronologie dit qui l'a fermée : cette étape, le serveur plus tôt (avec son code), ou une connexion qui s'était rompue.

ChampDans le fichierQuoiDéfaut et limitesModèles
ConnexionconnectionL'id d'un nœud Connexion WebSocketle premierNon
Code de fermeturecode1000 (normal), ou 3000–4999 pour un code propre à une application1000 (aussi si absent)Non
MotifreasonEnvoyée avec le codevide ; 123 octets au plus, après les modèlesOui

Sorties : Sortie. Aucun réglage.

json
{ "id": "bye", "type": "ws_close", "x": 960, "y": 80, "connection": "socket", "code": 1000, "reason": "done" }

Marqueur de journal ​

Écrit une ligne dans la chronologie et le rapport — un point de contrôle, ou les valeurs qu'une exécution a atteintes.

ChampDans le fichierQuoiDéfaut et limitesModèles
MessagemessageLe texteCheck point ; 10 000 caractères au plusOui

Sorties : Sortie. Aucun réglage.

json
{ "id": "ready", "type": "log", "x": 500, "y": 80, "message": "device {{device}} ready" }

Attentes ​

Le groupe Observation : des nœuds qui attendent que quelque chose arrive. Ils partagent ces règles :

  • Ils écoutent dès le début de l'exécution. Le port d'une attente ou son abonnement au broker est ouvert avant la première étape, si bien qu'un appareil qui répond plus vite que le début de l'étape suivante n'est pas manqué. Deux attentes sur la même adresse partagent un socket.
  • Ils comptent à partir de la dernière action de leur branche. Un message arrivé avant la dernière requête de la branche n'est pas une réponse à celle-ci ; avant toute action, tout ce qui est arrivé depuis le début de l'exécution compte.
  • Le premier message correspondant est pris. Un message pris par une attente n'est pas vu par une autre.
  • Reçu ou Expiré. Sur une correspondance, le message est stocké dans la variable de l'attente et le flux suit Reçu. Quand le temps s'écoule, il suit Expiré si cette sortie a un fil ; sinon l'étape échoue, en indiquant combien d'autres messages sont arrivés.
  • Chaque socket conserve les 1 024 derniers messages (et 64 Mio) ; les plus anciens sont abandonnés, et un délai d'attente indique combien l'ont été.
  • Écouter maintenant écoute avec cette seule étape, à partir de maintenant.

Sorties : Reçu (obligatoire), Expiré (facultatif). Réglages : Réessai.

Correspondance de charge utile ​

Attente UDP, Attente MQTT, Attente WebSocket et une réponse UDP choisissent l'aspect que la charge utile doit avoir :

OptionDans le fichierCorrespond quand la charge utile
N’importe quel datagrammeanyest n'importe quoi
Contient le textecontainslue comme du texte UTF-8, contient le motif (sensible à la casse)
Correspond à la regexregexlue comme du texte UTF-8, correspond à l'expression régulière
Contient les octets (hex)hexcontient les octets, écrits en paires hex : de ad be ef, deadbeef, 0xde,0xad, DE:AD

Le message correspondant est stocké comme un objet. Les étapes ultérieures lisent ses champs comme {{reply.text}} (avec le nom de la variable à la place de reply) :

ChampQuoi
textLa charge utile en texte
hex, bytesLa charge utile en hex (ses 1 024 premiers octets), et sa taille en octets
matchCe qui a correspondu : le texte, le premier groupe de l'expression régulière (ou toute la correspondance), ou les octets
fromL'IP:port de l'expéditeur
msMillisecondes depuis la dernière action de la branche (ou le début de l'exécution) jusqu'au message
topicAttente MQTT : le topic sur lequel il a été publié
json, kindAttente WebSocket : le message analysé comme JSON (null quand il ne l'est pas), et text ou binary

Attendre OSC ​

Attend un message OSC dont l'adresse correspond à un motif et dont les arguments remplissent toutes les règles. Dans un bundle, le premier message qui correspond est celui qui est pris.

ChampDans le fichierQuoiDéfaut et limitesModèles
Écouter sur (IP:port)bindIP:port sur lequel écouter ; 0.0.0.0 pour toutes les cartes réseau127.0.0.1:9001Non
Motif d’adresseaddress* n'importe quels caractères, ? un seul, [0-9] un ensemble ([!0-9] en dehors), {ping,pong} l'un ou l'autre ; les jokers restent dans un même segment //pong ; 512 caractères au plusOui
Règles d’argumentsargs[{ "index", "op", "value" }, …] : l'argument index comparé à value par op (Comparaisons) ; toutes doivent teniraucune ; 16 au plus, index 0–63Valeurs : oui
Délai d’attente, mstimeout_ms2 000 (aussi si absent) ; 1–120 000Non
Variable de réponsevariableOù le message est stockéreply (aussi si absent)Non

Un argument se compare comme du texte : les nombres tels qu'écrits, les chaînes sans guillemets, true/false, un blob en hex. Une règle sur un argument que le message n'a pas ne tient pas. Le message stocké a address, args ({{reply.args[0]}}), from et ms.

json
{ "id": "status", "type": "wait_osc", "x": 500, "y": 80, "bind": "0.0.0.0:9001", "address": "/status",
  "args": [{ "index": 0, "op": "eq", "value": "ready" }], "timeout_ms": 5000, "variable": "reply" }

Attendre UDP ​

Attend un datagramme UDP dont la charge utile correspond.

ChampDans le fichierQuoiDéfaut et limitesModèles
Écouter sur (IP:port)bindIP:port sur lequel écouter127.0.0.1:9001Non
Charge utilemodeVoir Correspondance de charge utilecontains (any si absent)Non
MotifpatternCe que la charge utile doit contenir ou auquel elle doit correspondrepong ; obligatoire sauf pour anyOui
Délai d’attente, mstimeout_ms2 000 (aussi si absent) ; 1–120 000Non
Variable de réponsevariablereply (aussi si absent)Non
json
{ "id": "ready", "type": "wait_udp", "x": 500, "y": 80, "bind": "0.0.0.0:9002", "mode": "contains",
  "pattern": "READY", "timeout_ms": 5000, "variable": "reply" }

Attendre MQTT ​

Attend un message publié sur un topic d'un broker, dont la charge utile correspond. L'exécution se connecte et s'abonne avant sa première étape. Les messages retenus que le broker rejoue à l'abonnement sont ignorés : seul ce qui est publié après le début de l'exécution compte.

ChampDans le fichierQuoiDéfaut et limitesModèles
Hôte du brokerhostLe broker127.0.0.1Paramètres uniquement
Portport1883 ; 1–65 535Non
Filtre de topictopicUn filtre : + est un niveau quelconque, # tout ce qui est en dessous (en dernier seulement)lab/#Paramètres uniquement
Charge utilemodeVoir Correspondance de charge utileany (aussi si absent)Non
Motifpatternvide ; obligatoire sauf pour anyOui
Délai d’attente, mstimeout_ms2 000 (aussi si absent) ; 1–120 000Non
Variable de réponsevariablereply (aussi si absent)Non
json
{ "id": "state", "type": "wait_mqtt", "x": 500, "y": 80, "host": "{{broker}}", "port": 1883,
  "topic": "lab/+/state", "mode": "contains", "pattern": "on", "timeout_ms": 5000, "variable": "reply" }

Attendre une requête HTTP ​

Attend une requête HTTP — un webhook, un rappel — adressée à l'Émulateur de l'exécution sur cette adresse, ou, quand l'exécution n'a pas d'émulateur HTTP à cet endroit, à un écouteur propre à l'exécution qui répond à chaque requête par 204. La requête doit correspondre à la méthode, au chemin et à chaque condition.

ChampDans le fichierQuoiDéfaut et limitesModèles
Écouter sur (IP:port)bindIP:port127.0.0.1:18080 — là où écoute un nouvel ÉmulateurNon
MéthodemethodUne méthode, ou Toutes (ANY) ; GET prend aussi HEADANY (aussi si absent)Non
Cheminpath/hooks/:name nomme un segment ({{request.params.name}}) ; un /* final prend le reste/* (aussi si absent) ; 512 caractères au plusOui
Conditionswhen[{ "on", "name", "op", "value" }, …] sur un header, un paramètre query, le body ou un chemin json ; chacune doit teniraucune ; 16 au plusOui, noms et valeurs
Délai d’attente, mstimeout_ms5 000 (2 000 si absent) ; 1–120 000Non
Variable de réponsevariablerequest (aussi si absent)Non

La requête stockée a method, path, query, headers, body, json, params, from et ms : {{request.json.event}}, {{request.headers.x-key}}.

json
{ "id": "hook", "type": "wait_http", "x": 500, "y": 80, "bind": "127.0.0.1:18081", "method": "POST",
  "path": "/hooks/:name", "when": [{ "on": "json", "name": "$.event", "op": "eq", "value": "deploy" }],
  "timeout_ms": 5000, "variable": "request" }

Attendre WebSocket ​

Attend un message sur la connexion qu'un Connexion WebSocket a ouverte, dont la charge utile correspond. Les messages depuis la dernière action de la branche comptent — la connexion elle-même, un envoi, ou toute autre requête.

ChampDans le fichierQuoiDéfaut et limitesModèles
ConnexionconnectionL'id d'un nœud Connexion WebSocketle premierNon
Charge utilemodeVoir Correspondance de charge utileany (aussi si absent)Non
Motifpatternvide ; obligatoire sauf pour anyOui
Délai d’attente, mstimeout_ms2 000 (aussi si absent) ; 1–120 000Non
Variable de réponsevariablereply (aussi si absent)Non

Un message JSON est lisible champ par champ : {{reply.json.type}}. La connexion doit précéder l'attente sur son chemin.

json
{ "id": "pong", "type": "wait_ws", "x": 730, "y": 80, "connection": "socket", "mode": "contains",
  "pattern": "pong", "timeout_ms": 3000, "variable": "reply" }

Émulation ​

Émulateur ​

Joue une dépendance — une API HTTP, un appareil OSC, UDP ou TCP, un broker MQTT — pendant toute l'exécution. Il s'ouvre avant la première étape et répond jusqu'à la fin de l'exécution ; dans le flux, l'étape est franchie aussitôt. Ce qu'il a reçu est compté, règle par règle, dans le rapport de l'exécution.

ChampDans le fichierQuoiDéfaut
Modifier…emulatorL'émulateur : name, bind (IP:port), protocol (http, osc, udp, tcp, mqtt), ses routes ou règles, et un outage facultatifUne API HTTP nommée API sur 127.0.0.1:18080 qui répond à /health

Les propriétés montrent ce qu'il joue en une ligne. Modifier… ouvre ses règles, le même éditeur que l'écran Émulateurs ; Vers la bibliothèque en garde une copie dans la bibliothèque d'émulateurs, et Depuis la bibliothèque remplace celui-ci par une copie qui en vient. Les règles — routes, réponses, défaillances, pannes — y sont décrites.

  • Un émulateur HTTP est aussi ce que lit un Attente de requête HTTP sur son adresse ; un émulateur OSC ou UDP partage son port avec les attentes de l'exécution à cet endroit.
  • Deux émulateurs d'un même transport ne peuvent pas partager un port dans une exécution.
  • Émulateur en panne/en service le met en panne et le remet en service.

Sorties : Sortie. Aucun réglage.

json
{ "id": "api", "type": "emulator", "x": 270, "y": 80,
  "emulator": { "name": "Orders API", "bind": "127.0.0.1:18080", "protocol": "http",
    "routes": [{ "method": "GET", "path": "/orders/:id", "order": "sequence",
                 "responses": [{ "status": 503 }, { "status": 200, "body": "{\"id\":\"{{request.params.id}}\"}" }] }] } }

Défaillances ​

Des nœuds qui cassent des choses à la demande. Une branche de nœuds Délai et ceux-ci à côté du trafic se lit comme un calendrier ; Défaillances sur un calendrier montre comment.

Dégradation ​

Un relais de dégradation pour toute l'exécution : le système testé envoie à (ou se connecte à) Écouter sur au lieu de sa vraie cible ; le relais transmet à Transmettre à, et les réponses reviennent de la même façon, dégradées par le profil. Il s'ouvre avant la première étape et se ferme quand l'exécution se termine, de quelque façon que ce soit, si bien que rien ne reste dégradé ; dans le flux, l'étape est franchie aussitôt. Chaque décision est tirée de la graine de l'exécution : la même graine et le même trafic connaissent le même sort.

ChampDans le fichierQuoiDéfaut et limitesModèles
Écouter surlistenIP:port auquel le système testé envoie127.0.0.1:9010Paramètres uniquement
Transmettre àtargetIP:port de la vraie destination, ou host:port — un nom d'hôte est résolu au démarrage de l'exécution, et un nom introuvable arrête l'exécution sur ce nœud127.0.0.1:9000Paramètres uniquement
ProtocoleprotocolUDP (udp) : chaque datagramme connaît son propre sort ; TCP (tcp) : chaque connexion est jointe à une connexion à elle vers la cible, et les deux flux sont dégradésUDP (udp si absent)Non
Préréglage et les valeurs en dessousprofileCe que le relais fait au trafic — voir Le profilLAN (aucune dégradation si absent)Non

L'adresse d'écoute d'un relais ne peut pas être un autre socket de l'exécution, et les relais ne peuvent pas transmettre les uns vers les autres en cercle. Une cible donnée par un nom est suivie une fois résolue, si bien qu'un cercle passant par un nom arrête l'exécution à son démarrage. Le rapport compte chaque phase d'un relais séparément.

Sorties : Sortie. Aucun réglage.

json
{ "id": "relay", "type": "impairment", "x": 270, "y": 80, "listen": "127.0.0.1:9010", "target": "{{device}}",
  "profile": { "name": "lan", "latency_ms": 1, "jitter_ms": 1 } }

Le profil ​

Un préréglage — LAN, Wi-Fi chargé, 4G, Satellite, Intermittent, Hors ligne — remplit toutes les valeurs ; modifiez ensuite celles que vous voulez. Un relais ne lit que les valeurs de son protocole ; dans un fichier, toute clé peut être omise (zéro, désactivé).

ChampDans le fichierQuoiLimitesProtocole
—nameUn libellé pour la chronologie et le rapport : la clé d'un préréglage (lan, wifi, 4g, satellite, intermittent, offline) ou le vôtre60 caractères au plusles deux
Hors ligne — rien ne passeofflineRien ne passetrue / falseles deux
Latencelatency_msDélai ajouté à chaque paquet, ou morceau d'un flux0–60 000 (le curseur va jusqu'à 1 000)les deux
Giguejitter_msUn délai supplémentaire aléatoire jusqu'à autant ; un flux TCP reste dans l'ordre0–60 000 (le curseur va jusqu'à 500)les deux
Bande passante, kbit/srate_kbpsUne limite de bande passante, 0 pour aucune. UDP : au-delà d'une seconde de file, les datagrammes sont abandonnés comme bridés ; TCP : l'émetteur est ralenti, rien n'est abandonné0, ou 8–10 000 000les deux
Perte de paquetslossLa chance qu'un datagramme soit abandonné0–1 (le curseur montre des %)UDP
Pertes en rafale, Longueur de rafale, datagrammesburst_start, burst_lengthLa chance qu'une rafale de pertes commence, et combien de datagrammes elle dure en moyenne0–1 ; 1–1 000 quand les rafales sont activesUDP
DuplicationduplicateLa chance qu'un datagramme soit envoyé deux fois0–1UDP
CorruptioncorruptLa chance qu'un bit d'un datagramme soit inversé0–1UDP
RéordonnancementreorderLa chance qu'un datagramme soit retenu, si bien que les suivants le dépassent0–1UDP
Connexion réinitialiséeresetLa chance qu'un morceau d'un flux réinitialise plutôt sa connexion — les deux côtés reçoivent une réinitialisation0–1TCP
Semi-ouvertestallLa chance qu'un morceau laisse sa connexion semi-ouverte : plus rien ne passe dans un sens ni dans l'autre, et aucun côté n'est prévenu0–1TCP

Pour en savoir plus sur les relais, les préréglages et ce qu'ils modélisent, voir la page Dégradation.

Changer la dégradation ​

Fait passer l'un des nœuds Dégradation de l'exécution à un autre profil à partir de cette étape, sans abandonner son port. La phase écoulée est close et comptée dans le rapport.

ChampDans le fichierQuoiDéfautModèles
DégradationrelayL'id d'un nœud Dégradation de cette expériencele premierNon
Préréglage et les valeurs en dessousprofileAvec quoi il dégrade à partir de maintenant — voir Le profil ; le relais lit les valeurs de son propre protocoleHors ligne (aucune dégradation si absent)Non

L'étape échoue si le relais ne tourne pas — il a échoué à relayer, par exemple. Sorties : Sortie. Aucun réglage.

json
{ "id": "cut", "type": "impairment_change", "x": 730, "y": 200, "relay": "relay",
  "profile": { "name": "offline", "offline": true } }

Émulateur en panne et en service ​

Met en panne l'un des émulateurs de l'exécution, ou le remet en service. Pendant la panne, un émulateur HTTP répond comme l'indique Pendant la panne ; un appareil TCP et un broker MQTT coupent leurs connexions et refusent les nouvelles ; les appareils OSC et UDP ne répondent rien. De nouveau en service, l'émulateur suit son propre calendrier de pannes, s'il en a un.

ChampDans le fichierQuoiDéfaut
ÉmulateuremulatorL'id d'un nœud Émulateur de cette expériencele premier
ÉtatdownEn panne (true) ou En service (false)en panne (false si absent)
Pendant la pannefaultHTTP uniquement : 503 Unavailable (unavailable), Fermer la connexion (reset : la connexion est fermée sans réponse) ou Pas de réponse (timeout : la requête est retenue jusqu'à ce que le client abandonne, 120 s au plus)unavailable (aussi si absent)

Sorties : Sortie. Aucun réglage. Aucun champ n'est un modèle.

json
{ "id": "down", "type": "emulator_state", "x": 500, "y": 200, "emulator": "api", "down": true, "fault": "unavailable" }

Données ​

Extraire une valeur ​

Enregistre une partie de la dernière réponse HTTP sur son chemin comme variable, pour les champs ultérieurs ({{token}}), les vérifications et les bifurcations. Une requête HTTP doit le précéder sur chaque chemin. Cliquer sur une valeur dans une réponse de Envoyer maintenant en ajoute un pour vous.

ChampDans le fichierQuoiDéfaut et limitesModèles
VariablevariableLe nom : lettres, chiffres et _, ne commençant pas par un chiffre, ni un mot réservé, ni le nom d'un paramètretokenNon
Prendre dansfromChamp JSON (json), En-tête (header), Code de statut (status), Corps entier (body) ou Expression régulière (regex)jsonNon
Chemin JSON, Nom de l’en-tête ou Motif (groupe 1 s’il existe)exprUn chemin JSON ($.data.token, $.items[0], $["first name"]), un nom d'en-tête (casse indifférente), ou une expression régulière — son premier groupe, ou toute la correspondance$.token ; inutilisé pour le statut et le corpsNon

L'étape échoue quand il n'y a rien à prendre : le corps n'est pas du JSON, le chemin ou l'en-tête manque, l'expression ne correspond pas, ou — pour un champ JSON ou le corps entier — le corps était plus long que les 256 Kio conservés. Un statut est stocké comme un nombre ; le reste comme du texte, ou comme la valeur JSON trouvée. Sorties : Sortie. Aucun réglage.

json
{ "id": "token", "type": "extract", "x": 500, "y": 80, "variable": "token", "from": "json", "expr": "$.data.token" }

Pour en savoir plus sur les variables, voir Données et modèles.

Vérifications ​

Une vérification réussit, ou fait échouer l'exécution. Les quatre vérifications de réponse lisent la dernière réponse HTTP sur leur chemin, si bien qu'une requête HTTP — pas une sous charge — doit les précéder sur chaque chemin.

Statut HTTP ​

Réussit quand le statut de la dernière réponse est exactement celui donné.

ChampDans le fichierQuoiDéfaut et limitesModèles
Statut attendustatus200 ; 100–599Non

Sorties : Sortie. Aucun réglage.

json
{ "id": "ok", "type": "assert_status", "x": 500, "y": 80, "status": 200 }

Texte de la réponse ​

Réussit quand le corps de la dernière réponse contient le texte, exactement (casse comprise). Seuls les 256 premiers Kio d'un corps sont conservés : un texte introuvable dans un corps qui a été coupé échoue avec cette raison.

ChampDans le fichierQuoiDéfaut et limitesModèles
Contient le textecontainsok ; obligatoireOui

Sorties : Sortie. Aucun réglage.

json
{ "id": "ready", "type": "assert_body", "x": 500, "y": 80, "contains": "ready" }

En-tête de la réponse ​

Réussit quand la dernière réponse a l'en-tête et que sa valeur contient le texte. Le nom de l'en-tête est comparé sans tenir compte de la casse ; la valeur exactement.

ChampDans le fichierQuoiDéfaut et limitesModèles
Nom de l’en-têtenamecontent-type ; obligatoireOui
Contient le textecontainsCe que sa valeur doit contenir ; vide : l'en-tête doit seulement être làapplication/jsonOui

Sorties : Sortie. Aucun réglage.

json
{ "id": "json", "type": "assert_header", "x": 500, "y": 80, "name": "Content-Type", "contains": "json" }

Temps de réponse ​

Réussit quand la dernière réponse a pris au plus ce temps, de l'envoi de la requête à la fin de son corps.

ChampDans le fichierQuoiDéfaut et limitesModèles
Durée maximale, msmax_ms1 000 ; 1–120 000Non

Sorties : Sortie. Aucun réglage.

json
{ "id": "fast", "type": "assert_latency", "x": 500, "y": 80, "max_ms": 250 }

Vérifier une valeur ​

Compare une valeur — le plus souvent une variable, écrite comme un modèle — avec une valeur attendue, et réussit quand la comparaison tient.

ChampDans le fichierQuoiDéfautModèles
ValeurvalueCe qui est comparé : {{token}}, {{reply.args[0]}}{{token}}Oui
ConditionopVoir Comparaisonsn’est pas videNon
AttenduexpectedInutilisé par est vide et n’est pas videvide (aussi si absent)Oui

Sorties : Sortie. Aucun réglage.

json
{ "id": "state", "type": "assert_value", "x": 730, "y": 80, "value": "{{state}}", "op": "eq", "expected": "ready" }

Comparaisons ​

Vérifier une valeur, Branche sur valeur, la condition de sortie d'une Boucle, les règles d'arguments OSC et les conditions HTTP comparent de la même façon :

OptionDans le fichierTient quand la valeur
égal àeqest égale à la valeur attendue — comme nombres quand les deux sont des nombres (200 = 200.0), sinon comme texte exact
différent denen'est pas égale, selon la même règle
inférieur à, au plus, supérieur à, au moinslt, le, gt, geest inférieure, au plus, supérieure, au moins — les deux doivent être des nombres : sinon une vérification, une bifurcation ou une Boucle fait échouer l'étape, et une règle d'argument ou une condition HTTP ne tient pas
contientcontainscontient le texte attendu
correspond à la regexmatchescorrespond à l'expression régulière attendue
est vide, n’est pas videempty, not_emptyest vide (les espaces comptent comme vide) / ne l'est pas

Flux ​

Des nœuds qui décident où va l'exécution. Pour en savoir plus sur les branches, les jointures et les boucles, voir Flux.

Début ​

Là où l'exécution commence ; chaque expérience en a exactement un. Il n'a aucune entrée ni aucun champ. La première ligne de la chronologie donne la graine de l'exécution.

Sorties : Sortie, obligatoire. Plusieurs fils partant de là démarrent des branches parallèles en même temps.

json
{ "id": "start", "type": "start", "x": 40, "y": 80 }

Fin ​

Là où l'exécution se termine ; chaque expérience en a exactement une, et elle n'a aucune sortie. Plusieurs branches peuvent y mener : l'exécution passe une fois, après la fin de la dernière branche, et seulement si aucune n'a échoué. Une exécution qui n'atteint jamais Fin échoue.

json
{ "id": "end", "type": "end", "x": 960, "y": 80 }

Délai ​

Attend un temps fixe avant l'étape suivante.

ChampDans le fichierQuoiDéfaut et limitesModèles
Délai (ms)ms300 ; 0–60 000Non

Sorties : Sortie. Aucun réglage. Pour des attentes plus longues, mettez-en plusieurs à la suite ou dans une Boucle.

json
{ "id": "pause", "type": "delay", "x": 500, "y": 80, "ms": 500 }

Bifurcation sur statut ​

Choisit Oui quand la dernière réponse HTTP a ce statut, sinon Non. Une requête HTTP doit la précéder sur chaque chemin.

ChampDans le fichierQuoiDéfaut et limitesModèles
Statut attendustatus200 ; 100–599Non

Sorties : Oui et Non, toutes deux obligatoires. Aucun réglage.

json
{ "id": "branch", "type": "branch_status", "x": 500, "y": 80, "status": 200 }

Bifurcation sur valeur ​

Choisit Oui quand une comparaison tient, sinon Non. Ses champs et ses comparaisons sont ceux de Vérifier une valeur ; une comparaison qui ne peut pas être faite (lt sur du texte) fait échouer l'étape.

ChampDans le fichierQuoiDéfautModèles
ValeurvalueCe qui est comparé{{token}}Oui
Conditionopégal àNon
Attenduexpectedvide (aussi si absent)Oui

Sorties : Oui et Non, toutes deux obligatoires. Aucun réglage.

json
{ "id": "ok", "type": "branch_value", "x": 730, "y": 80, "value": "{{reply.args[0]}}", "op": "eq", "expected": "ok" }

Branche parallèle ​

Exécute ce qui suit Branche 1 et Branche 2 en même temps, chaque branche avec sa propre copie des variables. Chaque sortie peut avoir plus de fils pour plus de branches. Aucun champ.

Sorties : Branche 1 et Branche 2, toutes deux obligatoires.

json
{ "id": "split", "type": "fork", "x": 270, "y": 80 }

Joindre les branches ​

Attend que chaque fil qui y mène ait été atteint, puis continue une fois, avec les variables des branches fusionnées — quand deux branches définissent la même variable, celle dont le fil vient plus tard dans le fichier l'emporte — et la dernière réponse HTTP de la dernière d'entre elles qui en avait une. Aucun champ.

Seules les branches qui s'exécutent toutes se rejoignent ici : un Jonction de branches derrière une Branche sur statut, dont Oui et Non ne se produisent jamais toutes les deux, ne continue jamais ; quand aucun autre chemin n'atteint Fin, l'exécution échoue sur ce nœud, en indiquant combien de branches elle attendait encore.

Sorties : Sortie, obligatoire.

Tout autre nœud avec plusieurs fils qui y mènent s'exécute une fois par arrivée.

json
{ "id": "joined", "type": "join", "x": 730, "y": 80 }

Boucle ​

Exécute les étapes sur Corps — qui y ramènent — encore et encore : au plus un certain nombre de fois, et, quand elle a une condition de sortie, jusqu'à ce que celle-ci tienne.

ChampDans le fichierQuoiDéfaut et limitesModèles
Itérations au plusmaxItérations au plus5 ; 1–1 000Non
arrêter plus tôt quanduntilCondition de sortie facultative { "value", "op", "expected" }, comme Vérifier une valeurdésactivéeValeur et attendue : oui
  • Le corps s'exécute toujours au moins une fois. La condition de sortie est lue après chaque itération, si bien que le corps peut définir ce qu'elle teste.
  • Terminé suit quand la condition tient — ou, sans condition, après la dernière itération.
  • Limite suit quand les itérations se sont épuisées avant que la condition ne tienne. Sans fil sur cette sortie, cela fait échouer l'étape.
  • Dans le corps, {{counter}} est le numéro de l'itération.
  • Un corps s'exécute comme une seule branche : chaque sortie à l'intérieur a un seul fil ; il ne contient ni Début, ni Fin, ni Branche parallèle, ni Jonction de branches, ni autre Boucle ; on n'y entre que par Corps ; et chaque fil y mène plus loin dans le corps ou revient à la boucle.

Sorties : Corps et Terminé (obligatoires), Limite (facultative). Aucun réglage.

json
{ "id": "poll", "type": "loop", "x": 270, "y": 80, "max": 10,
  "until": { "value": "{{status.args[0]}}", "op": "eq", "expected": "ready" } }