Turn this device into a telemetry source: a layout-level publishers array
streams Sensors readings over the layout's connection, so a hub device — or
your server — can watch this phone's compass, speed, or sound level live.
Definition
"publishers": [
{ "sensor": "heading", "interval": 0.25 },
{ "sensor": "device" }
]
The wire frame
Each reading is broadcast with the pipeline's keys flattened alongside the routing fields:
{ "msg_type": "sensor", "sensor": "heading", "device": "carters-iphone",
"ts_ms": 1782000000000, "value": 274.5, "cardinal": "W", "accuracy": 12.0 }
A hub layout subscribes with ordinary Sync — no server code required:
"sync": [{
"method": "meshsocket", "type": "listen", "event": "broadcast",
"filter": { "msg_type": "sensor", "sensor": "heading", "device": "carters-iphone" },
"valuePath": "value"
}]
device is the publishing layout's identity name (suffixed per device in a
room), so several phones can stream side by side and the hub tells them apart
by filter.
Consent — always
Layouts are untrusted JSON, so a publishers block never starts silently. The
first time a layout wants to broadcast, CAR-TER shows a consent sheet naming
each sensor and the exact destination; every decision is remembered per layout
and revocable in Settings → Sensor Broadcasting. While streaming, a radiating
pill in the header opens the live activity view — see what's flowing, pause a
stream, stop everything. Layouts pushed by a live-edit session (an AI editor)
get session-only consent: they ask again next session.
Notes
- Streams run while the layout is open and connected; backgrounding pauses them.
- Frames ride the layout's E2EE cipher when a key is set, like all traffic.
- The identity should keep
can_broadcast: true(role defaults usually do). intervalis clamped to a per-sensor floor so a typo can't flood the relay.- See privacy — readings go to your server, never to the developer.