# {{name}} — a tiny body ({{board}})

Scaffolded by `npx tiny-tech init --body {{slug}}` (tiny-tech {{version}}, template `usb-micropython`).
A MicroPython board that joins tiny as a **USB child**: a host (your Mac, a Pi) flashes it over USB CDC,
enrols it under the board's own name, writes `{device_id, token, name, api, networks}` into
`/flash/tiny.json` in the same run, and from then on the board heartbeats over Wi-Fi by itself.

## The one command

```bash
npx tiny-tech flash --body {{slug}} --from ./firmware [--port /dev/cu.usbmodemXXXX] [--wifi ssid:key]
```

`flash` detects the board by USB VID:PID, refuses to overwrite another project's firmware without `--force`,
copies `firmware/*.py`, verifies sha256 on the board, reads the board's name, enrols it (your session, or a
pairing code you approve on tiny.technology/devices), writes the identity and resets.

## Firmware

| file | what |
|---|---|
| `firmware/main.py` | boot: load `tiny.json`; no identity → wait for provisioning; identity → `tiny_node.run()` |
| `firmware/tiny_config.py` | `/flash/tiny.json` schema + `merge()`/`save()` — the exact API `tiny-tech flash` calls |
| `firmware/tiny_provision.py` | `ap_ssid()` = `tiny-XXXX` from the chip id — the name the fleet row gets |
| `firmware/tiny_node.py` | Wi-Fi join (roams the `networks` list) + `POST /api/devices/heartbeat` every 30 s |

Heartbeat body: `{deviceId, token, capabilities: {{capabilities}}, lanUrl?}` — the same contract every
tiny device speaks. Add sensors by extending the capability list and answering relay invokes.
