본문으로 건너뛰기

노드 참조 ​

실험이 담을 수 있는 모든 종류의 노드를 추가 메뉴의 그룹별로 정리했습니다: 동작, 대기, 에뮬레이션, 장애, 데이터, 검사, 흐름. 추가하고 연결하는 방법은 편집기에 있으며, signallab nodes는 같은 목록을 JSON으로 출력해 스크립트와 어시스턴트가 쓸 수 있습니다(명령줄).

이 페이지 읽기 ​

각 노드에는 필드 표가 있습니다:

  • 필드는 속성 창에 표시되는 이름이고, 파일에서는 실험 JSON의 키입니다.
  • 기본값은 편집기에서 노드를 추가할 때 가지는 값입니다. 파일에서 키를 생략할 수 있는 경우, 그때 가지는 값을 없으면으로 표시하며, 나머지 키는 파일에서 필수입니다.
  • 템플릿: 예 — 필드에 {{templates}}를 쓸 수 있습니다. 매개변수, 앞서 설정한 변수, 시크릿, 생성기이며, 단계가 실행될 때 해석됩니다(데이터와 템플릿). 매개변수만 — 첫 단계 전에 열리므로 매개변수만 알 수 있습니다. 아니요 — 쓴 그대로 값을 씁니다.

시간은 밀리초 단위입니다. 한도는 실행이 시작되기 전에 검사하며, 범위를 벗어난 필드는 실험이 실행되지 않게 하고 노드에 표시됩니다.

파일 안의 노드 ​

실험 파일에서 노드는 id(실험 안에서 고유), type, 캔버스에서의 위치(x, y, 0 이상), 필드, 사용하는 설정(retry, repeat, load, 꺼져 있으면 생략)을 가진 객체입니다. 와이어는 한 노드의 출력(port, 없으면 next)에서 다른 노드로 가는 에지입니다:

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" }
  ]
}

아래 예제는 각각 노드 하나를 파일에 담긴 모습 그대로 보여 줍니다.

여러 노드가 공유하는 설정 ​

이 설정은 노드 속성의 아래쪽에서 켭니다. 어떤 노드가 어떤 설정을 받는지는 각 노드 아래에 적혀 있습니다.

설정받는 노드하는 일
재시도보내거나 수신하는 노드: HTTP 요청, TCP 메시지, OSC 메시지, UDP 데이터그램, MQTT 발행, WebSocket 연결, WebSocket 보내기, 그리고 모든 대기단계가 실패하면 다시 시도합니다
반복보내는 노드: HTTP 요청, TCP 메시지, OSC 메시지, UDP 데이터그램, MQTT 발행, WebSocket 보내기여러 번 또는 일정 시간 동안 계속 보냅니다
부하HTTP 요청부하 프로필에 따라 요청을 보내고, 측정하여 임계값으로 판정합니다
회신 대기OSC 메시지, UDP 데이터그램같은 단계에서 보내고 답을 기다립니다

재시도 ​

실패 시 재시도: 단계가 실패하면 — 연결되지 않거나, 시간 초과이거나, 대기에서 아무것도 일치하지 않으면 — 잠시 멈췄다가 다시 실행합니다. 실패한 시도마다 타임라인에 행이 하나씩 생기며, 마지막 시도까지 실패하면 단계가 실패합니다. 해석할 수 없는 템플릿은 다시 시도하지 않습니다. 중지도 멈춤을 끝냅니다.

필드파일에서내용기본값과 한도
시도 횟수retry.attempts첫 시도를 포함한 전체 시도 횟수3; 편집기에서는 2–10(파일은 1도 가능)
일시 정지, msretry.delay_ms두 번째 시도 전의 멈춤500; 0–60 000
일시 정지 방식retry.backoff동일 (fixed): 매번 같은 시간만큼 멈춤; 두 배씩 (exponential): 실패할 때마다 두 배로 김fixed (없으면 이것)

아무리 두 배가 되어도 멈춤이 60초를 넘지 않습니다. 시간 초과 출력에 와이어가 있는 대기는 시간 초과로 실패하지 않고 그 출력으로 빠져나가므로, 그때는 다시 시도하지 않습니다.

반복 ​

반복 전송: 노드가 그래프의 루프 없이 계속 보냅니다 — 하트비트, 폴링, 지속적인 스트림처럼. 보낼 때마다 템플릿을 새로 읽으며({{counter}}는 번호, {{now}}는 시각), 재시도가 켜져 있으면 보낼 때마다 적용됩니다. 모든 전송이 통과하면 단계가 통과하고, 끝내 실패하는 전송이 있으면 단계가 실패합니다. 타임라인은 1초에 최대 한 번 진행을 보고합니다.

필드파일에서내용기본값과 한도
반복 기준repeat.until횟수 (count) 또는 시간 (duration)count (없으면 이것)
횟수repeat.count첫 전송을 포함한 전체 전송 횟수10 (없으면 이것); 2–10 000
기간, msrepeat.duration_ms첫 전송부터 계속 보낼 시간10 000 (없으면 이것); 1–300 000
간격, msrepeat.interval_ms두 전송 사이의 멈춤1 000; 10–60 000; 파일에서 필수
지터, msrepeat.jitter_ms멈춤마다 최대 이만큼 더 길어지며, 실행의 시드에서 뽑음0 (없으면 이것); 0–60 000

반복은 실행의 300초 안에 들어가야 하며, 일정 시간 동안은 전송이 10 000회 미만이어야 합니다(시간을 간격으로 나눈 값).

부하 ​

부하 전송, HTTP 요청에서만: 요청을 프로필에 따라 보냅니다 — 일정한 속도, 램프, 계단, 스파이크 또는 무작위 도착 — 동시에 최대 512개까지 진행하며(기본 32개), 지연 시간, 오류, 달성한 속도를 측정합니다. 임계값이 단계의 통과 여부를 정합니다. 부하는 반복과 재시도를 대신하며(실패한 요청은 세기만 하고 다시 시도하지 않음), 뒤따르는 검사에 남길 응답이 없습니다. 필드와 결과는 부하 테스트에 있습니다.

회신 대기 ​

회신 대기, OSC 메시지나 UDP 데이터그램에서: 회신을 기다리는 포트에서 메시지를 보내므로, 보낸 쪽에 답하는 장치의 응답을 들을 수 있고, 일치하는 회신이 제때 도착해야만 단계가 통과합니다. 회신이 없으면 단계가 실패하며, 재시도가 다시 보냅니다. 회신은 대기 노드처럼 변수에 저장됩니다.

필드파일에서내용기본값과 한도템플릿
회신 수신 주소(IP:포트)reply.bind보내고 수신할 IP:port; 포트 0은 아무 빈 포트나 사용0.0.0.0:0아니요
회신 주소 패턴 (OSC)reply.address회신의 주소 패턴, OSC 대기에서처럼/*예
인수 규칙 (OSC)reply.args인수 규칙, OSC 대기에서처럼없음; 최대 16개값: 예
회신 페이로드 (UDP)reply.modeany, contains, regex 또는 hex — 페이로드 일치 참고any (없으면 이것)아니요
패턴 (UDP)reply.pattern회신이 포함하거나 일치해야 하는 것비어 있음; any가 아니면 필수예
제한 시간, msreply.timeout_ms기다릴 시간2 000 (없으면 이것); 1–120 000아니요
회신 변수reply.variable회신을 저장할 변수reply (없으면 이것)아니요

회신의 포트는 대기 노드처럼 첫 단계 전에 열립니다.

동작 ​

보내는 노드입니다. 동작 뒤의 대기는 동작이 시작된 순간부터 메시지를 셉니다.

HTTP 요청 ​

HTTP 요청 하나를 보내고, 뒤따르는 검사, 분기, 값 추출 노드를 위해 응답을 보관합니다.

필드파일에서내용기본값과 한도템플릿
메서드request.methodGET, HEAD, POST, PUT, PATCH, DELETE 또는 OPTIONS(파일은 아무 메서드나 쓸 수 있음)GET아니요
URLrequest.urlhttp:// 또는 https:// URLhttp://127.0.0.1:8080/예
제한 시간(ms)request.timeout_ms교환 전체에 대해4 000 (없으면 10 000); 1–120 000아니요
요청 헤더request.headers[[name, value], …]; 이름이 빈 행은 건너뜀없음예, 이름과 값
본문request.body텍스트, 또는 없으면 nullnull예
인증request.auth없음, Basic, Bearer 토큰 또는 Digest, 사용자 이름과 비밀번호, 또는 토큰과 함께없음예
  • 404와 500을 포함해 어떤 응답이든 단계를 통과합니다: 상태는 HTTP 상태로 검사하거나 상태 분기로 분기하십시오. 답을 받지 못한 요청 — 거부됨, 시간 초과, 이름이 확인되지 않음, 신뢰할 수 없는 인증서 — 은 단계를 실패시킵니다.
  • 리다이렉트는 최대 열 번까지 따라갑니다. https:// 인증서는 검증합니다.
  • 응답 본문은 검사를 위해 최대 256 KiB까지 보관하며, 더 큰 본문은 그 지점에서 잘립니다(찾는 것이 잘린 뒤에 있을 수 있으면 검사가 그렇게 알려 줍니다).
  • Digest는 서버의 401 챌린지에 답하고 요청을 다시 보냅니다. 자격 증명은 요청에만 들어갑니다: 단계, 보고서, 인스펙터는 Authorization 헤더를 절대 보여 주지 않습니다. 비밀번호는 {{secret.NAME}}으로 쓰십시오.
  • 실험이 쿠키를 보관하는 동안(매개변수 아래에서 기본으로 켜짐), 서버가 설정한 쿠키는 실행의 이후 요청에 함께 돌아갑니다.

출력: 출력. 설정: 재시도, 반복, 부하.

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}}" } } }

HTTP도 참고하십시오.

TCP 메시지 ​

TCP로 호스트에 연결하고, 페이로드를 쓰고, 답의 첫 바이트를 최대 250 ms 기다린 뒤(한 번, 최대 1 024바이트를 읽음) 연결을 닫습니다. 답의 크기는 보고만 하고 검사하지는 않습니다.

인스펙터에서 이 단계는 출처가 experiment인 두 개의 tcp 프레임입니다: 쓴 페이로드와, 답이 왔으면 읽은 답입니다. 사용 중인 시크릿은 여느 프레임처럼 둘 다에서 마스킹됩니다.

필드파일에서내용기본값과 한도템플릿
호스트host호스트 이름 또는 IP 주소127.0.0.1예
포트port9000; 1–65 535아니요
제한 시간(ms)timeout_ms연결, 쓰기, 답을 합쳐서4 000 (없으면 이것); 1–120 000아니요
페이로드payload연결되면 UTF-8로 한 번 쓰는 텍스트hello예

연결이 거부되거나, 이름이 확인되지 않거나, 시간이 다 되면 단계가 실패합니다. 출력: 출력. 설정: 재시도, 반복. 지금 보내기는 한 번 연결해 페이로드를 쓰며, 노드의 결과가 몇 바이트를 보내고 돌려받았는지 알려 줍니다.

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

OSC 메시지 ​

OSC 1.0 메시지 하나를 UDP로 보냅니다.

필드파일에서내용기본값과 한도템플릿
대상 호스트:포트targetIP:port 또는 host:port; 호스트 이름은 단계가 보낼 때 조회하며, IPv4 주소가 있으면 그것을 씁니다127.0.0.1:9000예
OSC 주소address/로 시작/test예
인수args[{ "type", "value" }, …] — int, float, str, long, double, bool, blob(바이트), nil(값 없음)없음텍스트(str) 값: 예
회신 대기reply선택 사항: 보내고 답을 기다림 — 회신 대기 참고꺼짐

출력: 출력; 회신을 기대하면, 회신이 왔을 때만 이어집니다. 설정: 재시도, 반복, 회신. ⚡ 속성의 네트워크 장애 경유는 노드 앞에 네트워크 장애를 둡니다.

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

OSC도 참고하십시오.

UDP 데이터그램 ​

텍스트 페이로드를 UDP 데이터그램 하나로 하나 이상의 대상에 보냅니다.

필드파일에서내용기본값과 한도템플릿
대상 호스트:포트targetIP:port 또는 host:port; 쉼표, 세미콜론, 줄바꿈으로 구분한 여러 대상은 각각 데이터그램을 받습니다. 호스트 이름은 단계가 보낼 때 조회하며, IPv4 주소가 있으면 그것을 씁니다127.0.0.1:9000예
페이로드textUTF-8로 된 페이로드hello; 최대 65 507바이트예
회신 대기reply선택 사항: 보내고 답을 기다림 — 회신 대기 참고꺼짐

대상 하나라도 도달할 수 없으면 단계가 실패합니다. 출력: 출력. 설정: 재시도, 반복, 회신.

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" } }

MQTT 발행 ​

MQTT 브로커에 연결하고, 메시지 하나를 발행한 뒤 연결을 끊습니다. 연결은 일반 TCP 위의 MQTT 3.1.1이며, clean session이고 사용자 이름도 비밀번호도 없습니다. 연결, 발행, 브로커의 승인이 모두 15초 안에 일어나야 합니다.

필드파일에서내용기본값과 한도템플릿
브로커 호스트host브로커의 호스트 이름 또는 주소127.0.0.1예
포트port1883; 1–65 535아니요
토픽topic와일드카드(+, #) 없음lab/test예
페이로드payload텍스트로 된 메시지hello예
QoSqos0, 1 또는 20아니요
메시지 retainretaintrue: 브로커가 토픽의 값으로 보관false아니요

파일에서는 여섯 키가 모두 필수입니다. 브로커에 도달할 수 없거나 연결이나 메시지를 거부하면 단계가 실패합니다. 출력: 출력. 설정: 재시도, 반복.

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

MQTT도 참고하십시오.

WebSocket 연결 ​

실행이 끝날 때까지, 또는 WebSocket 닫기까지 WebSocket을 엽니다. 그때부터 도착하는 것은 그 위의 WebSocket 대기 단계를 위해 보관됩니다. URL과 헤더는 단계가 실행될 때 해석되므로, 앞서 추출한 토큰을 넣을 수 있습니다. 루프 안에서 다시 실행하면 이전 연결을 먼저 닫고 새로 엽니다. 실행이 어떻게 끝나든 연결은 close 프레임과 함께 닫힙니다.

필드파일에서내용기본값과 한도템플릿
URLurlws:// 또는 wss:// URLws://127.0.0.1:9001/예
요청 헤더headers업그레이드 요청과 함께 보내는 [[name, value], …]없음예, 이름과 값
서브프로토콜protocols선호 순서대로 제안할 하위 프로토콜; 서버가 하나를 고름없음아니요
제한 시간(ms)timeout_ms연결과 업그레이드에 대해5 000 (없으면 10 000); 1–120 000아니요

wss://는 https://와 같은 인증서를 신뢰합니다. 연결이나 업그레이드가 실패하면 단계가 실패하며, 서버의 상태가 이유에 들어 있습니다. 출력: 출력. 설정: 재시도(반복 아님).

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 }

WebSocket도 참고하십시오.

WebSocket 보내기 ​

WebSocket 연결가 연 연결로 메시지 하나를 보냅니다.

필드파일에서내용기본값과 한도템플릿
연결connection이 실험의 WebSocket 연결 노드 id첫 번째 것아니요
형식binary텍스트 (false) 또는 바이너리(hex) (true): 페이로드는 hex로 쓴 바이트, de ad be effalse (없으면 이것)아니요
페이로드text메시지hello; 최대 16 MiB예

연결은 그 경로에서 보내기보다 앞서야 하며, 연결이 열려 있지 않은 보내기는 실패합니다. 답은 메시지를 쓴 순간부터 셉니다. 출력: 출력. 설정: 재시도, 반복.

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

WebSocket 닫기 ​

close 핸드셰이크로 연결을 닫습니다. 타임라인은 누가 닫았는지 알려 줍니다: 이 단계, 앞서 서버(코드와 함께), 또는 이미 끊어진 연결입니다.

필드파일에서내용기본값과 한도템플릿
연결connectionWebSocket 연결 노드 id첫 번째 것아니요
닫기 코드code1000(정상), 또는 애플리케이션 고유의 3000–49991000 (없으면 이것)아니요
사유reason코드와 함께 보냄비어 있음; 템플릿을 적용한 뒤 최대 123바이트예

출력: 출력. 설정 없음.

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

로그 표시 ​

타임라인과 보고서에 한 줄을 씁니다 — 체크포인트, 또는 실행이 도달한 값입니다.

필드파일에서내용기본값과 한도템플릿
메시지message텍스트Check point; 최대 10 000자예

출력: 출력. 설정 없음.

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

대기 ​

대기 그룹: 무언가 도착하기를 기다리는 노드입니다. 다음과 같은 규칙을 공유합니다:

  • 실행이 시작될 때부터 수신합니다. 대기의 포트나 브로커 구독은 첫 단계 전에 열리므로, 다음 단계가 시작되기보다 빠르게 답하는 장치를 놓치지 않습니다. 같은 주소의 대기 두 개는 소켓 하나를 공유합니다.
  • 자기 분기의 마지막 동작부터 셉니다. 분기의 마지막 요청 전에 도착한 메시지는 그 요청의 답이 아닙니다. 동작이 하나도 없으면 실행이 시작된 이후의 모든 것이 해당합니다.
  • 처음 일치하는 메시지를 가져갑니다. 한 대기가 가져간 메시지는 다른 대기가 보지 못합니다.
  • 일치 또는 시간 초과. 일치하면 메시지가 대기의 변수에 저장되고 흐름은 일치를 따릅니다. 시간이 다 되면, 그 출력에 와이어가 있으면 시간 초과을 따르고, 없으면 단계가 실패하면서 다른 메시지가 몇 개 도착했는지 알려 줍니다.
  • 각 소켓은 최신 메시지 1 024개(그리고 64 MiB)를 보관하며, 더 오래된 것은 버려지고, 시간 초과 시 몇 개였는지 알려 줍니다.
  • 지금 수신 대기는 그 한 단계만 지금부터 수신합니다.

출력: 일치 (필수), 시간 초과 (선택). 설정: 재시도.

페이로드 일치 ​

UDP 대기, MQTT 대기, WebSocket 대기와 UDP 회신은 페이로드가 어떻게 생겨야 하는지 고릅니다:

옵션파일에서페이로드가 이럴 때 일치
모든 데이터그램any무엇이든
텍스트 포함containsUTF-8 텍스트로 읽어 패턴을 포함(대소문자 구분)
정규식 일치regexUTF-8 텍스트로 읽어 정규식과 일치
바이트 포함(hex)hexhex 쌍으로 쓴 바이트를 포함: de ad be ef, deadbeef, 0xde,0xad, DE:AD

일치한 메시지는 객체로 저장됩니다. 이후 단계는 그 필드를 {{reply.text}}로 읽습니다(reply 자리에 변수 이름):

필드내용
text텍스트로 된 페이로드
hex, byteshex로 된 페이로드(처음 1 024바이트)와 바이트 단위 크기
match일치한 것: 텍스트, 정규식의 첫 번째 그룹(또는 일치한 전체), 또는 바이트
from보낸 쪽의 IP:port
ms분기의 마지막 동작(또는 실행 시작)부터 메시지까지의 밀리초
topicMQTT 대기: 발행된 토픽
json, kindWebSocket 대기: JSON으로 파싱한 메시지(아니면 null)와 text 또는 binary

OSC 대기 ​

주소가 패턴과 일치하고 인수가 모든 규칙을 만족하는 OSC 메시지를 기다립니다. 번들에서는 일치하는 첫 번째 메시지를 가져갑니다.

필드파일에서내용기본값과 한도템플릿
수신 주소(IP:포트)bind수신할 IP:port; 모든 네트워크 카드는 0.0.0.0127.0.0.1:9001아니요
주소 패턴address*는 임의의 문자, ?는 한 글자, [0-9]는 문자 집합([!0-9]는 그 밖), {ping,pong}은 둘 중 하나; 와일드카드는 하나의 / 세그먼트 안에 머묾/pong; 최대 512자예
인수 규칙args[{ "index", "op", "value" }, …]: index 인수를 op로 value와 비교(비교); 모두 성립해야 함없음; 최대 16개, index 0–63값: 예
제한 시간, mstimeout_ms2 000 (없으면 이것); 1–120 000아니요
회신 변수variable메시지를 저장할 곳reply (없으면 이것)아니요

인수는 텍스트로 비교합니다: 숫자는 쓴 그대로, 문자열은 따옴표 없이, true/false, blob은 hex로. 메시지에 없는 인수에 대한 규칙은 성립하지 않습니다. 저장된 메시지에는 address, args ({{reply.args[0]}}), from, 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" }

UDP 대기 ​

페이로드가 일치하는 UDP 데이터그램을 기다립니다.

필드파일에서내용기본값과 한도템플릿
수신 주소(IP:포트)bind수신할 IP:port127.0.0.1:9001아니요
페이로드mode페이로드 일치 참고contains (없으면 any)아니요
패턴pattern페이로드가 포함하거나 일치해야 하는 것pong; any가 아니면 필수예
제한 시간, mstimeout_ms2 000 (없으면 이것); 1–120 000아니요
회신 변수variablereply (없으면 이것)아니요
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" }

MQTT 대기 ​

브로커의 토픽에 발행된 메시지 중 페이로드가 일치하는 것을 기다립니다. 실행은 첫 단계 전에 연결하고 구독합니다. 구독할 때 브로커가 재생하는 retained 메시지는 무시하며, 실행이 시작된 뒤 발행된 것만 해당합니다.

필드파일에서내용기본값과 한도템플릿
브로커 호스트host브로커127.0.0.1매개변수만
포트port1883; 1–65 535아니요
토픽 필터topic필터: +는 한 단계, #는 그 아래 전부(마지막에만)lab/#매개변수만
페이로드mode페이로드 일치 참고any (없으면 이것)아니요
패턴pattern비어 있음; any가 아니면 필수예
제한 시간, mstimeout_ms2 000 (없으면 이것); 1–120 000아니요
회신 변수variablereply (없으면 이것)아니요
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" }

HTTP 요청 대기 ​

웹훅, 콜백 같은 HTTP 요청이 그 주소의 실행의 에뮬레이터에 도착하기를 기다리거나, 그 주소에 실행의 HTTP 에뮬레이터가 없으면 모든 요청에 204로 답하는 실행 자체의 리스너에 도착하기를 기다립니다. 요청은 메서드, 경로, 모든 조건과 일치해야 합니다.

필드파일에서내용기본값과 한도템플릿
수신 주소(IP:포트)bindIP:port127.0.0.1:18080 — 새 에뮬레이터가 수신하는 곳아니요
메서드method메서드, 또는 모두 (ANY); GET은 HEAD도 받음ANY (없으면 이것)아니요
경로path/hooks/:name은 한 세그먼트에 이름을 붙임({{request.params.name}}); 마지막 /*는 나머지를 받음/* (없으면 이것); 최대 512자예
조건whenheader, query 매개변수, body 또는 json 경로에 대한 [{ "on", "name", "op", "value" }, …]; 모두 성립해야 함없음; 최대 16개예, 이름과 값
제한 시간, mstimeout_ms5 000 (없으면 2 000); 1–120 000아니요
회신 변수variablerequest (없으면 이것)아니요

저장된 요청에는 method, path, query, headers, body, json, params, from, 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" }

WebSocket 대기 ​

WebSocket 연결가 연 연결에서 페이로드가 일치하는 메시지를 기다립니다. 분기의 마지막 동작 이후의 메시지가 해당합니다 — 연결 자체, 보내기, 또는 다른 요청.

필드파일에서내용기본값과 한도템플릿
연결connectionWebSocket 연결 노드 id첫 번째 것아니요
페이로드mode페이로드 일치 참고any (없으면 이것)아니요
패턴pattern비어 있음; any가 아니면 필수예
제한 시간, mstimeout_ms2 000 (없으면 이것); 1–120 000아니요
회신 변수variablereply (없으면 이것)아니요

JSON 메시지는 필드별로 읽을 수 있습니다: {{reply.json.type}}. 연결은 그 경로에서 대기보다 앞서야 합니다.

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

에뮬레이션 ​

에뮬레이터 ​

실행 내내 의존 대상 — HTTP API, OSC·UDP·TCP 장치, MQTT 브로커 — 의 역할을 맡습니다. 첫 단계 전에 열려 실행이 끝날 때까지 응답하며, 흐름에서는 바로 통과합니다. 받은 내용은 실행 보고서에 규칙별로 집계됩니다.

필드파일에서내용기본값
편집…emulator에뮬레이터: name, bind (IP:port), protocol (http, osc, udp, tcp, mqtt), 라우트 또는 규칙, 선택적 outage127.0.0.1:18080에서 /health에 응답하는 API라는 이름의 HTTP API

속성은 무엇을 맡는지 한 줄로 보여 줍니다. 편집…은 규칙을 열며, 에뮬레이터 화면과 같은 편집기입니다. 라이브러리로는 에뮬레이터 라이브러리에 사본을 보관하고, 라이브러리에서는 라이브러리의 사본으로 이것을 바꿉니다. 규칙 — 라우트, 응답, 장애, 다운 일정 — 은 그곳에 설명되어 있습니다.

  • HTTP 에뮬레이터는 그 주소의 HTTP 요청 대기가 수신하는 대상이기도 하며, OSC나 UDP 에뮬레이터는 그 포트의 실행 대기 노드와 포트를 공유합니다.
  • 한 실행에서 같은 전송 방식의 에뮬레이터 두 개는 포트를 공유할 수 없습니다.
  • 에뮬레이터 다운/복구가 다운시키고 다시 복구합니다.

출력: 출력. 설정 없음.

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}}\"}" }] }] } }

장애 ​

신호에 맞춰 망가뜨리는 노드입니다. 지연 노드와 이것들을 트래픽 옆에 나란히 두면 일정처럼 읽히며, 일정에 따른 장애에서 방법을 보여 줍니다.

네트워크 장애 ​

실행 내내 동작하는 장애 릴레이입니다: 테스트 대상 시스템은 실제 대상 대신 수신 주소로 보내거나 연결하고, 릴레이는 전달 대상으로 전달하며, 응답은 같은 길로 프로필에 따라 장애를 입고 돌아옵니다. 첫 단계 전에 열려 실행이 어떻게 끝나든 닫히므로, 장애가 남아 있는 일이 없습니다. 흐름에서는 바로 통과합니다. 모든 결정은 실행의 시드에서 뽑습니다: 같은 시드와 같은 트래픽은 같은 운명을 겪습니다.

필드파일에서내용기본값과 한도템플릿
수신 주소listen테스트 대상 시스템이 보내는 IP:port127.0.0.1:9010매개변수만
전달 대상target실제 목적지의 IP:port, 또는 host:port — 호스트 이름은 실행이 시작될 때 조회하며, 찾을 수 없는 이름은 이 노드에서 실행을 멈춤127.0.0.1:9000매개변수만
프로토콜protocolUDP (udp): 데이터그램마다 따로 결과가 정해짐; TCP (tcp): 연결마다 대상으로 가는 연결을 하나씩 이어 주고, 양쪽 스트림에 장애를 적용UDP (없으면 udp)아니요
프리셋 및 그 아래 값profile릴레이가 트래픽에 하는 일 — 프로필 참고LAN (없으면 장애 없음)아니요

릴레이의 수신 주소는 실행의 다른 소켓일 수 없으며, 릴레이는 서로에게 순환으로 전달할 수 없습니다. 이름으로 준 대상은 조회된 뒤 따라가므로, 이름을 거친 순환은 실행이 시작될 때 멈춥니다. 보고서는 릴레이의 각 구간을 따로 집계합니다.

출력: 출력. 설정 없음.

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 } }

프로필 ​

프리셋 칩 — LAN, 혼잡한 Wi-Fi, 4G, 위성, 간헐적, 오프라인 — 이 모든 값을 채웁니다. 이후에 아무 값이나 바꿔도 됩니다. 릴레이는 자기 프로토콜의 값만 읽으며, 파일에서는 모든 키를 생략할 수 있습니다(0, 꺼짐).

필드파일에서내용한도프로토콜
—name타임라인과 보고서에 쓸 이름표: 프리셋의 키 (lan, wifi, 4g, satellite, intermittent, offline) 또는 직접 정한 이름최대 60자둘 다
오프라인 — 아무것도 통과하지 않음offline아무것도 통과하지 못함true / false둘 다
지연 시간latency_ms모든 패킷, 또는 스트림의 청크에 더하는 지연0–60 000 (슬라이더는 1 000까지)둘 다
지터jitter_ms최대 이만큼의 무작위 추가 지연; TCP 스트림은 순서를 유지0–60 000 (슬라이더는 500까지)둘 다
대역폭, kbit/srate_kbps대역폭 제한, 0이면 없음. UDP: 1초 분량 이상 대기열에 쌓이면 데이터그램을 대역 제한으로 버림; TCP: 송신 측이 느려질 뿐 아무것도 버리지 않음0, 또는 8–10 000 000둘 다
패킷 손실loss데이터그램이 버려질 확률0–1 (슬라이더는 %로 표시)UDP
버스트 손실, 버스트 길이, 데이터그램burst_start, burst_length손실 버스트가 시작될 확률과, 버스트가 평균 몇 데이터그램 동안 이어지는지0–1; 버스트가 켜져 있으면 1–1 000UDP
중복duplicate데이터그램이 두 번 전송될 확률0–1UDP
손상corrupt데이터그램의 한 비트가 뒤집힐 확률0–1UDP
순서 바뀜reorder데이터그램이 붙잡혀 뒤의 것들이 앞지르게 될 확률0–1UDP
연결 리셋reset스트림의 청크가 대신 연결을 리셋할 확률 — 양쪽 모두 리셋을 받음0–1TCP
반개방stall청크가 연결을 반개방 상태로 남길 확률: 어느 방향으로도 더 이상 통과하지 못하고, 어느 쪽도 통보받지 않음0–1TCP

릴레이, 프리셋, 그것들이 모델링하는 것에 대한 더 자세한 내용은 네트워크 장애 페이지에 있습니다.

장애 변경 ​

실행의 네트워크 장애 노드 하나를 이 단계부터 다른 프로필로 전환하며, 포트는 그대로 유지합니다. 지금까지의 구간은 닫히고 보고서에 집계됩니다.

필드파일에서내용기본값템플릿
네트워크 장애relay이 실험의 네트워크 장애 노드 id첫 번째 것아니요
프리셋 및 그 아래 값profile지금부터 무엇으로 장애를 입힐지 — 프로필 참고; 릴레이는 자기 프로토콜의 값을 읽음오프라인 (없으면 장애 없음)아니요

릴레이가 실행 중이 아니면 — 예컨대 중계에 실패했으면 — 단계가 실패합니다. 출력: 출력. 설정 없음.

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

에뮬레이터 다운과 복구 ​

실행의 에뮬레이터 하나를 다운시키거나 다시 복구합니다. 다운된 동안 HTTP 에뮬레이터는 다운 중 동작에 따라 응답하고, TCP 장치와 MQTT 브로커는 연결을 끊고 새 연결을 거부하며, OSC와 UDP 장치는 아무것도 응답하지 않습니다. 다시 복구되면 에뮬레이터는 자체 다운 일정이 있으면 그것을 따릅니다.

필드파일에서내용기본값
에뮬레이터emulator이 실험의 에뮬레이터 노드 id첫 번째 것
상태down다운 (true) 또는 복구 (false)다운 (없으면 false)
다운 중 동작faultHTTP 전용: 503 사용 불가 (unavailable), 연결 닫기 (reset: 응답 없이 연결이 닫힘) 또는 응답 없음 (timeout: 클라이언트가 포기할 때까지 요청을 붙잡아 둠, 최대 120초)unavailable (없으면 이것)

출력: 출력. 설정 없음. 템플릿은 쓰지 않습니다.

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

데이터 ​

값 추출 ​

그 경로의 최신 HTTP 응답 일부를 변수로 저장하여, 이후 필드({{token}}), 검사, 분기에서 씁니다. 모든 경로에서 HTTP 요청이 그보다 앞서야 합니다. 지금 보내기 응답에서 값을 클릭하면 하나가 대신 추가됩니다.

필드파일에서내용기본값과 한도템플릿
변수variable이름: 글자, 숫자, _, 숫자로 시작하지 않음, 예약어 아님, 매개변수 이름 아님token아니요
추출 위치fromJSON 필드 (json), 헤더 (header), 상태 코드 (status), 본문 전체 (body) 또는 정규식 (regex)json아니요
JSON 경로, 헤더 이름 또는 패턴(그룹 1이 있으면 그룹 1)exprJSON 경로 ($.data.token, $.items[0], $["first name"]), 헤더 이름(대소문자 무관), 또는 정규식 — 첫 번째 그룹, 또는 일치한 전체$.token; status와 body에는 쓰지 않음아니요

가져올 것이 없으면 단계가 실패합니다: 본문이 JSON이 아니거나, 경로나 헤더가 없거나, 표현식이 일치하지 않거나, — JSON 필드나 본문 전체의 경우 — 본문이 보관한 256 KiB보다 길면. status는 숫자로 저장하고, 나머지는 텍스트로, 또는 찾은 JSON 값으로 저장합니다. 출력: 출력. 설정 없음.

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

변수에 대한 더 자세한 내용은 데이터와 템플릿에 있습니다.

검사 ​

검사는 통과하거나 실행을 실패시킵니다. 네 가지 응답 검사는 그 경로의 최신 HTTP 응답을 읽으므로, 모든 경로에서 부하가 아닌 HTTP 요청이 그보다 앞서야 합니다.

HTTP status ​

최신 응답의 상태가 주어진 값과 정확히 같으면 통과합니다.

필드파일에서내용기본값과 한도템플릿
기대 상태status200; 100–599아니요

출력: 출력. 설정 없음.

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

응답 텍스트 ​

최신 응답의 본문이 그 텍스트를 정확히(대소문자 포함) 포함하면 통과합니다. 본문은 처음 256 KiB만 보관하므로, 잘린 본문에서 찾지 못한 텍스트는 그 이유로 실패합니다.

필드파일에서내용기본값과 한도템플릿
포함할 텍스트containsok; 필수예

출력: 출력. 설정 없음.

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

응답 헤더 ​

최신 응답에 그 헤더가 있고 그 값이 텍스트를 포함하면 통과합니다. 헤더 이름은 대소문자 무관하게, 값은 정확히 비교합니다.

필드파일에서내용기본값과 한도템플릿
헤더 이름namecontent-type; 필수예
포함할 텍스트contains그 값이 포함해야 하는 것; 비어 있으면 헤더가 있기만 하면 됨application/json예

출력: 출력. 설정 없음.

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

응답 시간 ​

요청을 보낸 순간부터 본문이 끝날 때까지, 최신 응답이 최대 이 시간만 걸렸으면 통과합니다.

필드파일에서내용기본값과 한도템플릿
최대 시간, msmax_ms1 000; 1–120 000아니요

출력: 출력. 설정 없음.

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

값 검사 ​

값 — 보통 템플릿으로 쓴 변수 — 을 기대값과 비교하여, 비교가 성립하면 통과합니다.

필드파일에서내용기본값템플릿
값value비교할 것: {{token}}, {{reply.args[0]}}{{token}}예
조건op비교 참고비어 있지 않음아니요
기대값expected비어 있음와 비어 있지 않음는 쓰지 않음비어 있음 (없으면 이것)예

출력: 출력. 설정 없음.

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

비교 ​

값 검사, 값 분기, 루프의 종료 조건, OSC 인수 규칙, HTTP 조건은 같은 방식으로 비교합니다:

옵션파일에서값이 이럴 때 성립
같음eq기대값과 같음 — 둘 다 숫자이면 숫자로(200 = 200.0), 아니면 정확한 텍스트로
같지 않음ne같은 규칙으로, 같지 않음
미만, 이하, 초과, 이상lt, le, gt, ge작음, 이하, 큼, 이상 — 둘 다 숫자여야 함: 아니면 검사, 분기, 루프는 단계를 실패시키고, 인수 규칙이나 HTTP 조건은 성립하지 않음
포함contains기대한 텍스트를 포함
정규식 일치matches기대한 정규식과 일치
비어 있음, 비어 있지 않음empty, not_empty비어 있음(공백도 비어 있는 것으로 봄) / 아님

흐름 ​

실행이 어디로 가는지 정하는 노드입니다. 분기, 합류, 루프에 대한 더 자세한 내용은 흐름에 있습니다.

시작 ​

실행이 시작하는 곳이며, 모든 실험에 정확히 하나가 있습니다. 입력도 필드도 없습니다. 타임라인의 첫 행이 실행의 시드를 보여 줍니다.

출력: 출력, 필수. 여기서 나가는 여러 와이어는 병렬 분기를 동시에 시작합니다.

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

끝 ​

실행이 완료되는 곳이며, 모든 실험에 정확히 하나가 있고 출력이 없습니다. 여러 분기가 여기로 올 수 있습니다: 실행은 마지막 분기가 끝난 뒤 한 번 통과하며, 아무것도 실패하지 않았을 때만 그렇습니다. 종료에 도달하지 못한 실행은 실패합니다.

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

지연 ​

다음 단계 전에 정해진 시간만큼 기다립니다.

필드파일에서내용기본값과 한도템플릿
지연(ms)ms300; 0–60 000아니요

출력: 출력. 설정 없음. 더 긴 대기는 여러 개를 이어 놓거나 루프 안에 두십시오.

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

상태 분기 ​

최신 HTTP 응답이 이 상태이면 예, 아니면 아니요를 고릅니다. 모든 경로에서 HTTP 요청이 그보다 앞서야 합니다.

필드파일에서내용기본값과 한도템플릿
기대 상태status200; 100–599아니요

출력: 예와 아니요, 둘 다 필수. 설정 없음.

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

값 분기 ​

비교가 성립하면 예, 아니면 아니요를 고릅니다. 필드와 비교는 값 검사의 것과 같으며, 할 수 없는 비교(텍스트에 lt)는 단계를 실패시킵니다.

필드파일에서내용기본값템플릿
값value비교할 것{{token}}예
조건op같음아니요
기대값expected비어 있음 (없으면 이것)예

출력: 예와 아니요, 둘 다 필수. 설정 없음.

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

병렬 분기 ​

분기 1과 분기 2 뒤에 오는 것을 동시에 실행하며, 각 분기는 자기 변수 사본을 가집니다. 출력마다 더 많은 분기를 위해 와이어를 더 둘 수 있습니다. 필드 없음.

출력: 분기 1과 분기 2, 둘 다 필수.

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

분기 합류 ​

자기에게 들어오는 모든 와이어에 도달할 때까지 기다린 뒤, 분기들의 변수를 합쳐 한 번 이어갑니다 — 두 분기가 같은 변수를 설정하면 파일에서 와이어가 더 뒤에 오는 쪽이 이김 — 그리고 그것들 중 하나라도 가진 마지막 분기의 최신 HTTP 응답을 씁니다. 필드 없음.

모두 실행되는 분기만 여기서 만납니다: 상태 분기 뒤에 있는 분기 합류은 예와 아니요가 둘 다 일어나는 일이 없어 이어지지 않으며, 다른 경로가 종료에 도달하지 못하면 실행은 이 노드에서 실패하면서 아직 몇 개의 분기를 기다렸는지 알려 줍니다.

출력: 출력, 필수.

들어오는 와이어가 여러 개인 다른 노드는 도착마다 한 번씩 실행됩니다.

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

루프 ​

본문의 단계 — 루프로 되돌아오는 — 를 반복해서 실행합니다: 최대 정해진 횟수까지, 그리고 종료 조건이 있으면 그것이 성립할 때까지.

필드파일에서내용기본값과 한도템플릿
최대 반복 횟수max최대 반복 횟수5; 1–1 000아니요
다음 조건이면 일찍 종료until선택적 종료 조건 { "value", "op", "expected" }, 값 검사에서처럼꺼짐value와 expected: 예
  • 본문은 항상 최소 한 번 실행됩니다. 종료 조건은 매 반복 뒤에 읽으므로, 본문이 검사할 값을 설정할 수 있습니다.
  • 조건이 성립하면 완료으로 이어지며, 조건이 없으면 마지막 반복 뒤에 이어집니다.
  • 조건이 성립하기 전에 반복이 다하면 한도으로 이어집니다. 거기에 와이어가 없으면 단계가 실패합니다.
  • 본문 안에서 {{counter}}는 반복 번호입니다.
  • 본문은 하나의 분기로 실행됩니다: 그 안의 각 출력에는 와이어가 하나이고, 시작, 종료, 병렬 분기, 분기 합류 또는 다른 루프을 담지 않으며, 본문를 통해서만 들어가고, 그 안의 모든 와이어는 본문 안으로 이어지거나 루프로 되돌아갑니다.

출력: 본문와 완료 (필수), 한도 (선택). 설정 없음.

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