Kompletny przykład pokazujący, jak jeden kontrakt URI/Markpact steruje tym samym procesem na różnych platformach i transportach.
Kod źródłowy jest w src/:
src/
├── host/ # Go host bridge: Docker/RPi3/Linux/Windows, USB przez ticcmd
├── web/ # statyczny panel HTML/JS
└── firmware/
├── esp32-i2c-http-mqtt/ # ESP32: HTTP/MQTT -> I²C -> Tic T249
└── esp32p4-usb-http-mqtt/ # ESP32-P4: HTTP/MQTT -> USB Host -> Tic T249
Ten sam envelope działa przez HTTP i MQTT:
{
"uri": "stepper://tic-t249/axis/x/command/move-relative",
"payload": {"steps": 100, "speed_sps": 200},
"context": {"approved": true, "dry_run": true, "environment": "mock"}
}
/uri/call, MQTT/TCP, sterowanie Tic T249 przez I²C./uri/call, MQTT/TCP, sterowanie Tic T249 przez natywny USB Host.uritic-host-rpi3-armv7 lub arm64, HTTP/MQTT, USB przez ticcmd.ticcmd.docker-compose.yml: uritic-pc + web + mqtt, USB przez /dev/bus/usb + ticcmd.ticcmd.exe.src/web, bez backendu JS; wysyła bezpośrednio fetch() albo MQTT over WebSocket.markpacts/pololu-tic-t249.stepper.markpact.md
Główne URI:
stepper://{device}/axis/{axis}/query/status
stepper://{device}/axis/{axis}/command/enable
stepper://{device}/axis/{axis}/command/disable
stepper://{device}/axis/{axis}/command/stop
stepper://{device}/axis/{axis}/command/home
stepper://{device}/axis/{axis}/command/move-relative
stepper://{device}/axis/{axis}/command/move-absolute
cp .env.example .env
./scripts/docker-up.sh
Po starcie:
Website: http://127.0.0.1:8080/
HTTP URI: http://127.0.0.1:8791/uri/call
Routes: http://127.0.0.1:8791/uri/routes
Contract: http://127.0.0.1:8791/.well-known/markpact
MQTT TCP: mqtt://127.0.0.1:1883
MQTT WS: ws://127.0.0.1:9001/mqtt
Smoke testy:
./scripts/docker-smoke-http.sh
./scripts/docker-smoke-mqtt.sh
./scripts/docker-tic-list.sh
Compose dokumentuje kontrakt URI przez x-uri-contract oraz labelki org.markpact.*. Dockerfile też ma labelki org.markpact.uri.*, więc obraz sam niesie informację, jakie URI obsługuje. Szczegóły: docs/docker-pc-usb-runtime.md.
./scripts/build-host.sh
Wyniki:
dist/uritic-host-linux-amd64
dist/uritic-host-rpi3-armv7
dist/uritic-host-rpi3-arm64
dist/uritic-host-windows-amd64.exe
Broker z WebSocket dla przeglądarki:
mosquitto -c mqtt/mosquitto-websocket.conf
RPi3:
./scripts/run-rpi3-http-mqtt.sh
Linux PC:
./scripts/run-linux-http-mqtt.sh
Windows:
.\scripts\run-windows-http-mqtt.ps1
Panel:
http://rpi3.local:8791/
http://127.0.0.1:8791/
cp src/firmware/esp32-i2c-http-mqtt/include/secrets.example.h src/firmware/esp32-i2c-http-mqtt/include/secrets.h
# edytuj Wi-Fi/MQTT w secrets.h
./scripts/build-esp32.sh
Flash:
./scripts/flash-esp32.sh
. $HOME/esp/esp-idf/export.sh
idf.py --version
./scripts/build-esp32p4-usb.sh
ESP32-P4 example używa protocol_examples_common; ustaw sieć w idf.py menuconfig zależnie od boardu, zwykle Ethernet albo zewnętrzny moduł Wi-Fi.
curl -s http://127.0.0.1:8791/uri/call -H 'Content-Type: application/json' -d '{
"uri":"stepper://tic-t249/axis/x/command/move-relative",
"payload":{"steps":100,"speed_sps":200},
"context":{"approved":true,"dry_run":true,"environment":"mock"}
}' | jq .
Panel publikuje na:
uritic/tic-t249/call/browser
a runtime odpowiada na:
uritic/tic-t249/response/browser
Dokumentacja: docs/URI-ROUTER.md · plan: docs/REFACTORING.md · mesh: urisys/docs/MESH.md.
make resolver # profiles/targets.yaml → profiles/urisys.runtime.*.yaml
Resolvery ładowane przez urirouter (uri_router), orchestracja przez urisys:
profiles/urisys.runtime.hybrid.yaml
profiles/urisys.runtime.pc-only.yaml
profiles/urisys.runtime.esp32-only.yaml
profiles/edge.config.yaml # resolver_path względem profiles/
export TELLMESH_ROOT=~/github/tellmesh
pip install -e $TELLMESH_ROOT/urirouter -e $TELLMESH_ROOT/uricore
./scripts/run-urisys-flow.sh tic-t249-safe-relative-move
./scripts/run-urisys-flow.sh tic-t249-hybrid-pc-esp32
make integration-test
MQTT canonical: tellmesh/tic-t249 (legacy uritic/tic-t249 nadal obsługiwany przez uritic-host).
Przykłady w markpact-contracts/packs/examples/: uri-transport-binding.stepper.yaml, urisys.runtime.pololu-hybrid.yaml.
context.approved: true.dry_run: true nigdy nie wysyła komend ruchu do silnika.steps są mikro-krokami Tic.exec.Command z listą argumentów, bez shella.