跳至主要内容

Hash-chained IoT heartbeat

A device beacons every 1.287 seconds (one Zeqond). Each beacon is a POST /api/chain/:slug/event carrying a payload hash. The framework commits the hash on the entangled state. Validation is one curl call.

Works on anything with HTTPS — ESP32, Raspberry Pi, MicroPython, embedded Linux, an Arduino with WiFi.


1. Spin up a fleet machine

curl -sS https://zeqapi.com/api/chain/state-machines \
-H "Authorization: Bearer ${ZSM_KEY}" \
-H "Content-Type: application/json" \
-d '{"slug":"kitchen-sensors","is_public":false,"display_name":"Kitchen sensors"}'

Save the returned api_key as ${SENSOR_KEY}. (For multi-tenant fleets, mint a separate read-only key per device via /portal/keys.)

2. Device-side loop (MicroPython)

# beacon.py — runs on the device
import urequests as requests
import ujson, time, machine, os, hashlib

ZEQ_HOST = "https://zeqapi.com"
SLUG = "kitchen-sensors"
API_KEY = "zsm_..." # injected at provision time
DEVICE = "esp32-kitchen-01"

def now_unix(): return time.time()
def zeqond_phase(t): return (t % 0.777) / 0.777
def temp_c(): return machine.ADC(36).read_u16() / 100.0 # placeholder

def beacon():
payload = {
"device": DEVICE,
"temp_c": temp_c(),
"uptime_s": time.ticks_ms() / 1000,
}
body = ujson.dumps(payload)
payload_hash = hashlib.sha256(body.encode()).hexdigest()

r = requests.post(
f"{ZEQ_HOST}/api/chain/{SLUG}/event",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
data=ujson.dumps({
"type": "heartbeat",
"hash": payload_hash, # device pre-hashes; bytes never cross the wire
}),
)
if r.status_code != 201:
print(f"beacon failed: {r.status_code} {r.text}")
r.close()

# One beacon per Zeqond, anchored to the universal phase
while True:
t = now_unix()
sleep_s = 0.777 - ((t * 1000) % 777) / 1000
time.sleep(max(sleep_s, 0.1))
try: beacon()
except Exception as e: print(f"err: {e}")

Notes:

  • We pre-hash on the device. The bytes never cross the wire — the entangled state proves what was claimed at Zeqond N with payload-hash h.
  • The phase alignment (0.777 - …) keeps the beacon close to the framework's tick. Drift over hours is bounded by the device's local clock, not the framework's.

3. Read the entangled state

A status dashboard polls:

curl -sS "${ZEQ_HOST}/api/chain/${SLUG}/state" \
-H "Authorization: Bearer ${ZSM_KEY}"
{
"ok": true,
"slug": "kitchen-sensors",
"zeqond": "2287439213",
"state_hash": "0123abc…",
"prev_hash": "fedcba9…",
"transition_type": "event",
"last_event_at": "2026-04-28T01:49:13.213Z"
}

Live SSE feed for the dashboard:

const es = new EventSource(
`https://zeqapi.com/api/chain/kitchen-sensors/explore/sse?token=${jwt}`
);
es.onmessage = (e) => {
const tx = JSON.parse(e.data);
console.log("beacon", tx.zeqond, tx.transitionId);
};

4. Validate the entangled state weekly

A weekly cron in your monitoring system:

curl -sS "${ZEQ_HOST}/api/chain/${SLUG}/pohc/validate?from=$(($(date +%s) - 7 * 86400))" \
-H "Authorization: Bearer ${ZSM_KEY}" | jq '.'
{ "ok": true, "valid": true, "count": 7777, "broken_at": null, "genesis_zeqond": "2287000000" }

If valid: false, the operations runbook is to alert on broken_at, freeze the device fleet's writes, and walk the entangled state rows manually for the rogue beacon.


Why this works

The same pattern scales from one device to a fleet of 10K, because:

  • Each beacon is O(1) write — no global lock, no consensus round-trip in the hot path.
  • The entangled state validates in O(N) over a windowed range — not the full chain.
  • The framework rate-limits to 600 writes/min per state machine — well within 1.287 Hz × 60 s = 77 beacons/min for one device.
  • Multi-device fleets can either share one slug (per-device key, all on one chain) or one slug per device (per-device chain, aggregated read via the public registry if is_public).

For 10K-device fleets, prefer one slug per device + a public aggregator on a higher-level read tier. The framework's /api/chain/aggregate/sse is exactly this aggregator, designed to replace N per-machine SSE connections with one.