Aller au contenu

Émulateurs ​

Un émulateur, c’est Signal Lab qui joue l’API, l’appareil ou le service auquel votre système s’adresse. Il écoute sur une adresse et répond selon des règles : une API HTTP par routes, un appareil OSC, UDP ou TCP par « sur ceci, répondre cela », un broker MQTT comme le fait tout broker, plus des règles qui lui sont propres. Il peut être lent, échouer ou tomber en panne de temps en temps, pour que vous puissiez tester ce que fait votre système quand sa dépendance se comporte mal. Chaque échange est compté, listé et envoyé à l’Inspecteur.

Un émulateur est un seul document. L’écran Émulateurs en conserve une bibliothèque ; le même document s’exécute dans une expérience comme nœud Émulateur, depuis la ligne de commande avec signallab emulate, et via l’API et MCP, et répond de la même façon partout.

L’écran ​

À gauche se trouve la bibliothèque (Bibliothèque) : chaque émulateur avec son protocole et son adresse, un point qui pulse et un compteur de requêtes sur ceux qui tournent. À droite se trouvent les réglages et les règles de l’émulateur sélectionné, et en dessous ce qu’il a reçu (En direct).

Créer un émulateur ​

  1. Appuyez sur l’un des boutons en haut de la bibliothèque :

    BoutonCréeÉcoute surAvec une règle qui fonctionne telle quelle
    + API HTTPUne API HTTP127.0.0.1:18080GET /health → 200 {"status":"ok"}
    + Appareil OSCUn appareil OSC127.0.0.1:9100/ping → /pong avec le compteur en int
    + Appareil UDPUn appareil UDP127.0.0.1:7100un datagramme contenant PING → PONG 1, PONG 2, …
    + Appareil TCPUn appareil TCP127.0.0.1:7200une ligne contenant PING → PONG
    + Broker MQTTUn broker MQTT127.0.0.1:1883une publication sur lab/<name>/set → la même charge utile, retenue, sur lab/<name>/state

    Quand un autre émulateur de la bibliothèque utilise déjà ce port, le port libre suivant est pris.

  2. Donnez-lui un nom dans le champ Nom (120 caractères au plus).

  3. Réglez le champ Écouter sur : IP:port. 127.0.0.1 ne répond qu’à cet ordinateur ; 0.0.0.0 répond aussi au réseau.

  4. Modifiez les règles (voir plus bas), et indiquez dans le champ Note ce qu’il remplace.

Les modifications s’enregistrent d’elles-mêmes. Le bouton Dupliquer crée une copie sur le port libre suivant. Le bouton Supprimer demande une confirmation (Supprimer ?), arrête l’émulateur s’il tourne et le retire de la bibliothèque.

Les règles sont essayées dans l’ordre, de la première à la dernière ; la première qui correspond répond. L’en-tête de chaque règle affiche un résumé d’une ligne ; cliquez dessus pour déplier ou replier la règle. Les boutons ↑ et ↓ déplacent une règle, × la supprime.

L’exécuter ​

  1. Sélectionnez l’émulateur et appuyez sur Démarrer. Son port s’ouvre avant que le bouton ne revienne : un port déjà pris, ou un émulateur qui a un problème, est refusé à ce moment-là avec la raison.
  2. Dirigez votre système vers lui. Pour une API HTTP, le bouton Copier l’URL copie son adresse (http://127.0.0.1:18080), et chaque route a son propre bouton Copier l’URL (sauf quand son chemin contient un modèle {{…}}).
  3. Regardez la liste Reçus se remplir.
  4. Appuyez sur Arrêter, ou arrêtez sa tâche depuis le bandeau de la console.

L’état affiché à côté des boutons indique Arrêté, l’adresse où il répond, ou qu’il est en panne.

Un émulateur continue de répondre avec les règles avec lesquelles il a démarré. Quand vous le modifiez pendant qu’il tourne, le bouton Redémarrer apparaît : appuyez dessus pour redémarrer avec les règles telles qu’elles sont maintenant. D’ici là, les compteurs de correspondances des règles sont masqués, car ils appartiennent aux anciennes règles.

Le bouton Mettre en panne rend un émulateur en cours indisponible jusqu’à ce que vous appuyiez sur Réactiver : une requête HTTP reçoit 503, un appareil TCP et un broker MQTT coupent leurs connexions et refusent les nouvelles, un appareil OSC ou UDP ne répond plus. Voir Tomber en panne.

Deux émulateurs d’un même transport ne peuvent pas partager un port : les émulateurs HTTP, TCP et MQTT écoutent sur des ports TCP, les émulateurs OSC et UDP sur des ports UDP. Une API HTTP et un appareil OSC peuvent tous deux utiliser le port 8080 ; deux API HTTP ne le peuvent pas. Un second émulateur sur un port pris est refusé au démarrage.

TIP

Dans un navigateur connecté à un serveur, l’émulateur tourne sur le serveur. Celui qui écoute sur 0.0.0.0 est joint par le nom du serveur, et Copier l’URL copie cette adresse ; celui qui écoute sur 127.0.0.1 ne répond qu’aux programmes du serveur lui-même.

Ce qui est arrivé ​

Pendant qu’il tourne, le panneau En direct compte :

CompteurQuoi
RequêtesTout ce qui est arrivé : requêtes, messages, lignes.
Sans règleCe qu’aucune règle n’a pris. Une requête HTTP sans route reçoit tout de même sa réponse (voir Requêtes qu’aucune route ne prend) ; les autres n’en reçoivent aucune.
En échecLes échanges pour lesquels une réponse n’a pas pu être construite ou envoyée.
Pendant la panneCe qui est arrivé pendant que l’émulateur était en panne. Affiché quand une panne est programmée ou que quelque chose l’a trouvé en panne. Jamais compté comme Sans règle.
Non remisMQTT uniquement, quand cela se produit : les messages qu’un client avait trop de retard pour recevoir.

L’en-tête de chaque règle indique combien de fois elle a correspondu depuis le démarrage.

La liste Reçus affiche les 300 échanges les plus récents, le plus récent en premier :

ColonneQuoi
HeureQuand il est arrivé.
SourceL’adresse du client.
RequêteCe qui est arrivé, en notation du protocole : GET /users/7, /ping 1, POWER?.
RègleLa règle qui l’a pris (#2), ou —.
RéponseCe qui est reparti : 200 OK · 37 B, /pong 3, une charge utile ; retenu ou fermé pour une défaillance ; l’erreur quand la réponse a échoué ; en panne quand il est arrivé pendant une panne.
msDe l’arrivée jusqu’au départ de la réponse, délai compris.

Le bouton ⌕ d’une ligne (Ouvrir dans l’Inspecteur) ouvre cet échange dans l’Inspecteur, si la capture était active. Quand plus de 200 échanges arrivent en un cinquième de seconde, la liste en saute certains et indique combien. Le moteur conserve les 500 échanges les plus récents de chaque émulateur en cours, avec ce qui est arrivé, pour la ligne de commande, l’API et MCP.

API HTTP ​

Un serveur HTTP/1.1. Chaque requête reçoit la réponse de la première route qui la prend.

Routes ​

Une route prend une requête quand sa méthode, son chemin et toutes ses conditions correspondent.

ChampQuoi
MéthodeGET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, ou Toutes. Une route GET répond aussi à HEAD.
CheminCommence par /. Un segment :name prend n’importe quel segment unique, lu comme {{request.params.name}} ; un dernier segment * prend tout ce qui se trouve en dessous. Un / final ne change rien ; la chaîne de requête ne fait pas partie du chemin.
ConditionsChacune doit être remplie. Ajoutez-en une avec + Condition.

Exemples de chemins :

CheminPrendNe prend pas
/health/health, /health//health/db, /Health
/users/:id/users/7 (params.id vaut 7), /users/a%20b (a b)/users, /users/7/orders
/files/*/files, /files/a, /files/a/b/c/file, /other/files/a

Une condition lit une partie de la requête (Où) et la compare :

OùNomLit
En-têteUn nom d’en-tête, casse indifférenteLa valeur de l’en-tête ; pour un en-tête envoyé plusieurs fois, ses valeurs jointes par , .
Paramètres d’URLUn paramètre de la chaîne de requêteSa valeur, décodée ; la première, s’il est répété.
Corps—Tout le corps, en texte.
JSONUn chemin JSON, comme $.user.idCe champ d’un corps JSON.

Les comparaisons sont égal à, différent de, inférieur à, au plus, supérieur à, au moins, contient, correspond à la regex, est vide et n’est pas vide. Les nombres se comparent comme des nombres, le texte à l’identique. Un en-tête, un paramètre ou un champ absent est vide. Une comparaison impossible — du texte face à un nombre — n’est pas remplie.

Réponses ​

Une route a de une à 16 réponses (Réponses).

ChampQuoiPar défaut
Statut100–599.200
DéfaillanceAutre chose qu’une réponse ; voir Défaillances.Aucune — répondre
Délai, msCombien de temps attendre avant de répondre, 0–60 000 ms.0
Gigue, msJusqu’à autant de plus, au hasard, 0–60 000 ms.0
PoidsSa part quand la route répond au hasard. Affiché seulement dans ce cas.1
En-têtesJusqu’à 32. Les noms peuvent utiliser des paramètres ; les valeurs sont des modèles.aucun
CorpsUn modèle, jusqu’à 256 Kio tel qu’écrit.vide

Sans en-tête Content-Type, un corps qui est du JSON valide part en application/json et tout autre corps en text/plain; charset=utf-8.

Avec deux réponses ou plus, le champ Quelle réponse décide laquelle une requête reçoit :

Quelle réponseLes requêtes reçoiventPour
Dans l’ordre, puis la dernièreLa première, la deuxième, …, puis la dernière à partir de là : 500, 500, 200, 200, 200…Les réessais : échouer deux fois, puis fonctionner.
À tour de rôleDe nouveau la première après la dernière : 200, 500, 200, 500…Une dépendance qui échoue de temps en temps, régulièrement.
Au hasard, selon le poidsChacune tirée selon son poids. Des poids de 8 et 2 donnent la première environ 80 % du temps. Au moins un poids doit être supérieur à 0.Une part réaliste d’échecs.

Le menu Ajouter une réponse ajoute à la route une réponse toute prête :

PréréglageAjoute
200 JSON200, {"ok":true}
201 Created201, {"id":"{{uuid}}"}, en-tête Location: {{request.path}}/{{counter}}
404 Not found404, {"error":"not found"}
500 Server error500, {"error":"internal"}
503 Unavailable503, {"error":"unavailable"}, en-tête Retry-After: 1
Lente — 2 s200, {"ok":true} au bout de 2000 ms
Pas de réponseLa défaillance Pas de réponse
Connexion ferméeLa défaillance Fermer la connexion
JSON mal formé200, {"items":[{"id":1},{"id":2}]} avec la défaillance Corps mal formé

Défaillances ​

DéfaillanceCe que rencontre le client
Aucune — répondreLa réponse.
Pas de réponseRien. La requête est retenue jusqu’à 2 minutes, puis la connexion est fermée — c’est donc le délai d’attente du client lui-même qui est testé. Le délai ne s’applique pas.
Fermer la connexionLa connexion se ferme sans réponse, après le délai.
Corps mal forméUne réponse HTTP complète, avec le statut et les en-têtes définis, dont le corps s’arrête à mi-chemin : du JSON qui ne s’analyse pas. Quand tout le corps était du JSON, le type de contenu indique toujours application/json.

Requêtes qu’aucune route ne prend ​

Le champ Requêtes qu’aucune route ne prend décide de ce que reçoit une requête qui ne correspond à aucune route :

  • 404 Not found — 404 avec le corps {"error":"no_route"} ;
  • Cette réponse — une réponse que vous définissez, avec tout ce qu’a la réponse d’une route. Son {{counter}} compte les requêtes qu’aucune route n’a prises.

Dans les deux cas, la requête compte comme Sans règle.

Ce qu’une réponse HTTP peut lire ​

ModèleValeur
{{request.method}}GET, POST, …
{{request.path}}Le chemin, sans la chaîne de requête.
{{request.params.id}}Le segment de chemin nommé :id.
{{request.query.page}}Un paramètre de la chaîne de requête, décodé.
{{request.headers.x-key}}Un en-tête ; noms en minuscules.
{{request.body}}Le corps en texte : ses 64 premiers Kio.
{{request.json.name}}Un champ d’un corps JSON, quand le corps est du JSON et tient dans 64 Kio.
{{request.from}}L’IP:port du client.

Un corps de requête de plus de 1 Mio reçoit 413 et est compté comme En échec. Une réponse qui ne peut pas être construite — un modèle qui nomme quelque chose que la requête n’a pas — reçoit 500 avec l’erreur dans son corps, et est comptée comme En échec.

Appareil OSC ​

Chaque message qui arrive — chaque message d’un bundle séparément — reçoit la réponse de la première règle à laquelle il correspond. Un datagramme qui n’est pas de l’OSC est compté comme Sans règle.

ChampQuoi
Motif d’adresseUn motif d’adresse OSC 1.0 : * n’importe quels caractères, ? un seul, [a-z] un ensemble, {a,b} l’un ou l’autre, chacun à l’intérieur d’un segment (voir OSC).
Règles d’argumentsJusqu’à 16 conditions sur les arguments, comme dans Attente OSC (voir Nœuds).
RépondreDésactivé : prendre le message sans rien répondre.
Adresse de réponseL’adresse de la réponse, un modèle.
Arguments de réponseJusqu’à 16 arguments, chacun avec un Type (int, float, str, long, double, bool, blob, nil) et une Valeur sous forme de modèle.
Répondre àVide : retour à l’adresse et au port de l’expéditeur. Sinon IP:port.
Délai, ms, Gigue, ms0–60 000 ms chacun.

La valeur d’un argument est lue selon son type une fois le modèle rempli : {{request.args[0]}} renvoie le premier argument comme nombre quand le type est numérique. Un bool accepte true, 1, yes, on ou false, 0, no, off ; un blob accepte des octets en hex ; une valeur vide est le zéro du type.

Les réponses partent du port propre à l’émulateur : un client qui écoute sur le port depuis lequel il a envoyé les entend.

Une réponse OSC peut lire {{request.address}}, {{request.args[0]}} et {{request.from}}.

Appareil UDP ​

Chaque datagramme reçoit la réponse de la première règle à laquelle il correspond.

ChampQuoi
CorrespondanceN’importe quel datagramme, Contient le texte, Correspond à la regex ou Contient les octets (hex).
MotifLe texte, l’expression régulière ou les octets à rechercher.
RéponseRecevoir sans répondre, Texte ou Hex, puis la réponse elle-même sous forme de modèle.
Répondre àVide : retour à l’expéditeur. Sinon IP:port.
Délai, ms, Gigue, ms0–60 000 ms chacun.

Une réponse UDP ou TCP peut lire :

ModèleValeur
{{request.text}}La charge utile en texte.
{{request.match}}Ce qui a correspondu : le texte, le premier groupe d’une expression régulière (ou toute la correspondance), les octets.
{{request.hex}}La charge utile en octets hex, ses 1024 premiers.
{{request.bytes}}La taille de la charge utile.
{{request.from}}L’IP:port de l’expéditeur.

Une réponse texte fait au plus 65 507 octets.

Appareil TCP ​

Un appareil qui parle par lignes sur une connexion TCP, comme un projecteur ou une matrice de commutation. Chaque message qu’envoie un client reçoit la réponse de la première règle à laquelle il correspond ; la réponse revient sur la même connexion.

ChampQuoi
Fin de messageCe qui termine un message, et qui est ajouté après chaque réponse et après l’accueil : LF (\n) (un \r qui le précède est supprimé), CR LF (\r\n), CR (\r), ou Aucune — chaque segment. Les lignes vides sont ignorées.
AccueilEnvoyé quand un client se connecte ; vide pour aucun. Il peut lire {{request.from}}.
Correspondance, Motif, RéponseComme pour un appareil UDP.
Puis fermer la connexionFermer la connexion après la réponse de cette règle — à QUIT, par exemple.
Délai, ms, Gigue, ms0–60 000 ms chacun.

Un message de plus de 64 Kio sans son délimiteur est pris tel quel.

Broker MQTT ​

Un petit broker MQTT 3.1.1 sur TCP simple. Il fait ce que fait un broker : les clients se connectent, s’abonnent avec + et #, publient en QoS 0, 1 et 2, les messages retenus et les messages de dernière volonté fonctionnent, et une seconde connexion avec l’identifiant d’un client prend le relais de la première. Les sessions sont toujours propres : un client qui demande à garder sa session en reçoit une neuve, et rien n’est mis en file pour un client absent.

En plus, chaque message qui lui est publié est confronté aux règles : la première qui correspond publie aussi une réponse — un appareil qui rend compte de ce qu’il a fait.

ChampQuoi
Nom d’utilisateur, Mot de passeQuand un nom d’utilisateur est défini, un client doit se connecter avec celui-ci et le mot de passe ; vide : tout le monde peut se connecter. Un mot de passe sans nom d’utilisateur est refusé, car MQTT 3.1.1 ne peut pas le transporter.
RetenusJusqu’à 64 messages (Topic, Charge utile, QoS) présents dès le démarrage, comme s’ils avaient été publiés avec retain : un client qui s’abonne les reçoit en premier.
Filtre de topicLes topics que prend une règle : + un niveau, # le reste — lab/+/set.
Correspondance, MotifUne condition sur la charge utile, comme pour un appareil UDP.
RépondreDésactivé : prendre le message sans rien publier de plus.
Topic de réponse, Charge utile de réponseDes modèles. Le topic ne peut pas contenir + ni #.
QoS, RetainCeux de la réponse.
Délai, ms, Gigue, ms0–60 000 ms chacun.

Une réponse MQTT peut lire {{request.topic}}, {{request.levels[1]}} (les niveaux du topic, à partir de 0), {{request.payload}}, {{request.json.state}}, {{request.match}}, {{request.qos}}, {{request.retain}}, {{request.client}} (l’identifiant du client) et {{request.from}}.

Modèles dans les réponses ​

Les réponses s’écrivent dans le même langage de modèles que les expériences : un champ signifie donc la même chose ici et là. Une réponse peut lire :

  • request — ce qui est arrivé, comme listé plus haut pour chaque protocole ;
  • {{counter}} — combien de messages cette règle a pris depuis le démarrage de l’émulateur, celui-ci compris ;
  • les générateurs — {{uuid}}, {{now.iso}}, les valeurs aléatoires et les autres ; les aléatoires sont tirés de la graine de l’émulateur ;
  • les paramètres, quand l’émulateur tourne dans une expérience ou est démarré avec signallab emulate --param.

Une réponse ne lit jamais de secrets, et un nom inconnu est une erreur, pas un texte vide.

Certains champs sont fixés au démarrage de l’émulateur, avant que quoi que ce soit n’arrive : un chemin, une condition, un motif d’adresse, un motif de charge utile, un filtre de topic, Répondre à, le nom d’un en-tête, les messages retenus et les identifiants de connexion du broker. Ils n’acceptent que du texte et des paramètres, ni request ni générateurs.

La graine pilote l’ordre aléatoire des réponses, la gigue et les générateurs aléatoires. Sur l’écran Émulateurs, chaque démarrage prend une nouvelle graine ; une expérience utilise la graine de l’exécution, et signallab emulate --seed prend celle que vous donnez.

Tomber en panne ​

Pour tester ce que fait votre système quand une dépendance flanche par intermittence, cochez Tombe en panne de temps en temps :

ChampQuoiPar défaut
En service, msCombien de temps il répond, 10–3 600 000 ms.10 000
En panne, msCombien de temps il est en panne, 10–3 600 000 ms.3000
Pendant la panneHTTP uniquement : ce que rencontre une requête pendant la panne.503 Unavailable

Le calendrier démarre avec l’émulateur et se répète : en service, en panne, en service, en panne… Pendant la panne :

ÉmulateurCe qui se passe
HTTP503 Unavailable : 503 avec Retry-After réglé sur le nombre de secondes avant son retour (au moins 1). Fermer la connexion : la connexion se ferme sans réponse. Pas de réponse : retenue jusqu’à 2 minutes, puis fermée.
Appareil TCPLes connexions ouvertes sont coupées en moins de 0,1 s ; les nouvelles sont fermées dès leur arrivée.
Broker MQTTToutes les connexions sont coupées ; les nouvelles sont refusées (code de retour CONNACK 3, serveur indisponible).
Appareil OSC, UDPRien ne reçoit de réponse.

Ce qui arrive pendant la panne compte comme Pendant la panne, pas comme Sans règle, et ses règles ne sont pas consultées.

Le bouton Mettre en panne fait la même chose à la demande, quoi que dise le calendrier, jusqu’à ce que vous appuyiez sur Réactiver ; HTTP reçoit alors 503 sans Retry-After. Dans une expérience, le nœud Émulateur en panne/en service le fait à une étape de l’exécution (voir Nœuds et Défaillances).

Problèmes ​

Pendant que vous le modifiez, l’émulateur est vérifié un instant après chaque changement, et un problème s’affiche sous ses boutons avant que vous n’appuyiez sur Démarrer. Un problème indique où il se trouve — la règle, la réponse ou le message retenu, et le champ — et ce qui ne va pas : un chemin sans son /, une expression régulière qui ne compile pas, un modèle de réponse qui nomme autre chose que request, les paramètres et les générateurs, une valeur hors limites. Le bouton Démarrer refuse un émulateur qui a un problème.

Limites ​

QuoiLimiteÀ la limite
Routes ou règles par émulateur64Refusé à la vérification.
Réponses par route16Refusé.
Conditions par route16Refusé.
En-têtes par réponse32Refusé.
Conditions sur les arguments, arguments de réponse (OSC)16 chacunRefusé.
Messages retenus (MQTT)64Refusé.
Un corps, une réponse ou un accueil tel qu’écrit256 KioRefusé.
Un délai ou une gigue60 000 msRefusé.
Corps de requête HTTP1 Mio413.
Connexions HTTP simultanées512Les suivantes sont fermées dès leur arrivée.
En-tête de requête HTTP30 sUn client doit l’envoyer dans ce délai.
Connexions TCP simultanées256Les suivantes sont fermées dès leur arrivée.
Réponses OSC et UDP en attente de leur délai1024Les suivantes sont abandonnées et comptées comme En échec.
Clients MQTT simultanés256Les suivants sont fermés dès leur arrivée.
Paquet MQTT256 KioLa connexion du client prend fin.
Abonnements MQTT par client100Les suivants sont refusés.
Topics MQTT retenus1000 topics, 16 MioUn nouveau message retenu est acheminé, mais pas retenu.
Messages MQTT en attente pour un client lent1024 messages, 8 MioIl les manque ; comptés comme Non remis.

Émuler ceci ​

Pour créer un émulateur à partir d’une réponse qui a fonctionné :

  1. Sur l’écran HTTP, envoyez une requête et obtenez une réponse — ou utilisez le bouton Envoyer maintenant sur un nœud HTTP d’une expérience.
  2. Appuyez sur ⧉ Émuler ceci à côté de la réponse. La boîte de dialogue Émuler cette réponse montre la route qu’elle va créer.
  3. Dans le champ Ajouter à, choisissez l’un de vos émulateurs HTTP, ou Un nouvel émulateur.
  4. Appuyez sur Ajouter la route. L’écran Émulateurs s’ouvre sur cet émulateur.

La route répond à la méthode et au chemin de la requête (sans la chaîne de requête) avec le statut, les en-têtes et le corps de la réponse. Les en-têtes propres à cet échange-là (Content-Length, Date, Server, ETag et autres) sont omis, et le corps est envoyé tel quel, même s’il contient {{. Un nouvel émulateur ne contient que cette route. Ajoutée à un émulateur existant, la route passe en premier, pour répondre avant une route plus large ; un émulateur en cours la prend en compte quand vous appuyez sur Redémarrer.

Depuis une expérience, une URL écrite avec des modèles devient un motif : sa base ({{api}}) est supprimée, un segment qui est un seul modèle (/orders/{{order_id}}) devient :order_id, et un segment modélisé seulement en partie termine le chemin par *.

Le jeu de départ ​

La première fois que Signal Lab ne trouve pas de bibliothèque d’émulateurs, il en écrit cinq, tous sur cet ordinateur. Leurs noms et leurs notes sont écrits dans la langue de l’interface à ce moment-là.

ÉmulateurÉcoute surFait
API de démonstration127.0.0.1:8080GET /health → {"status":"ok","time":…} ; GET /users/:id → un utilisateur avec cet identifiant ; POST /users → 201 avec un Location ; GET /slow → au bout de 1500 ms ; /flaky → 503, 503, puis 200 à partir de là.
Appareil OSC de démonstration127.0.0.1:9100/ping → /pong avec le compteur ; /fader/* → /ack avec l’adresse reçue ; /cue/* pris sans réponse.
Appareil UDP de démonstration127.0.0.1:7100PING → PONG et le compteur ; tout le reste → ACK et sa taille en octets.
Appareil TCP de démonstration127.0.0.1:7200Lignes terminées par CR LF. Accueille avec READY ; POWER? → POWER=ON ; POWER ON ou POWER OFF → OK ON / OK OFF ; QUIT → BYE, puis raccroche.
Broker MQTT de démonstration127.0.0.1:1883Retient online sur lab/status ; ON ou OFF publié sur lab/<name>/set → la même chose, retenue, sur lab/<name>/state.

Le signal de départ Le service répond-il ? de la bibliothèque de signaux interroge http://127.0.0.1:8080/, l’adresse de l’émulateur API de démonstration : celui-ci n’a pas de route pour /, il reçoit donc 404.

Le fichier de la bibliothèque ​

La bibliothèque est emulators.json dans le dossier de données (voir Fichiers) ; survolez le compteur sous la liste pour voir son chemin. Il est écrit en entier 0,7 s après la dernière modification, via un fichier temporaire : une écriture ratée laisse donc le précédent intact. Si le fichier ne peut pas être lu, la liste affiche l’erreur avec le chemin, la ligne et la colonne, et le fichier est laissé tel quel : corrigez-le et appuyez sur Recharger le fichier. Appuyez aussi sur Recharger le fichier après l’avoir modifié à la main. Sans fichier, le jeu de départ est réécrit.

json
{
  "version": 1,
  "emulators": [
    {
      "id": "orders-api",
      "note": "Stands in for the orders service.",
      "emulator": {
        "name": "Orders API",
        "bind": "127.0.0.1:18080",
        "protocol": "http",
        "routes": [
          { "method": "GET", "path": "/orders/:id",
            "responses": [{ "body": "{\"id\":\"{{request.params.id}}\",\"state\":\"open\"}" }] },
          { "method": "POST", "path": "/orders", "order": "sequence",
            "responses": [{ "status": 503 }, { "status": 201, "body": "{\"id\":\"{{uuid}}\"}" }] }
        ],
        "outage": { "up_ms": 20000, "down_ms": 2000, "fault": "unavailable" }
      }
    }
  ]
}

L’objet emulator seul est un document que signallab emulate lit aussi.

Dans les expériences et les scripts ​

  • Dans une expérience, un nœud Émulateur ouvre son émulateur avant la première étape et répond jusqu’à la fin de l’exécution ; ce qu’il a reçu est compté dans le rapport. Un émulateur HTTP y est aussi ce qu’écoute Attente de requête HTTP (Nœuds), et un émulateur OSC ou UDP partage son port avec les attentes de l’exécution. Deux émulateurs d’un même transport dans une même expérience ne peuvent pas partager un port. Voir Nœuds et Défaillances.
  • signallab emulate exécute des émulateurs depuis des fichiers ou depuis cette bibliothèque jusqu’à Ctrl+C ou --for, en affichant ce qu’ils répondent ; voir La ligne de commande.