example

Example of the component espp/telemetry v1.3.6
# Telemetry — USB example (→ Serial Plotter web app)

Streams synthetic float channels from an ESP32-S3 to the browser **Serial
Plotter** web app over USB, using `espp::Telemetry` (a binary telemetry emitter
carried on the `stream_frame` framing, dispatcher module 3 by default).

The hosted app — <https://esp-cpp.github.io/espp/apps/telemetry.html> —
connects on the **vendor (WebUSB)** interface, reads the channel **schema**, and
plots the live **sample** stream. It is the binary, higher-rate,
device-timestamped counterpart to the app's text/CSV Web Serial transport.

## What it does

- Declares four channels — `sine`, `cosine`, `noise`, `ramp` — as the schema.
- A producer task emits one sample (a `float` per channel) every ~10 ms (100 Hz),
  timestamped with the device clock.
- Exposes the stream over the USB **vendor (WebUSB)** interface; a `Dispatcher`
  routes the emitter's module (`Telemetry::Config::module`, 3 by default; only a
  routing key, the hosted Serial Plotter finds it through discovery by its
  protocol id) to it and serves capability discovery so the browser **Device
  Hub** lists this device and links to `telemetry.html`.
- The web app can pause/resume the stream and request a rate (`SET_STREAM`), and
  requests the schema on connect (`GET_SCHEMA`).

`espp::Telemetry` itself is transport-agnostic (the `stream_frame` framing works
over CDC / UART / a socket too); this example streams over WebUSB because that is
what the web app's binary path consumes.

Swap the synthetic generator for your real signals: build a `std::array<float, N>`
in channel order and call `telemetry.emit(...)`.

## Build & run

```sh
idf.py -p /dev/ttyACM0 flash          # target esp32s3 (set in sdkconfig.defaults)
idf.py -p /dev/ttyUSB0 monitor        # console is on UART0 (USB-UART adapter)
```

Then open the Serial Plotter web app, click **Connect (USB)**, and pick the
"espp Serial Plotter" device. The system console/logs go to **UART0**: on the
S3 / P4, USB-Serial-JTAG shares the native USB port's PHY with USB-OTG, which
TinyUSB takes over.

## Standard USB services

Like every espp USB example, this one serves the standard service set on its
framed USB link(s) next to its own protocol, so the hosted consoles and the
[Device Hub](https://esp-cpp.github.io/espp/apps/dispatcher_hub.html) (which
finds each service through discovery, by protocol id) work against it:

| Service | Module (default) | Protocol id | Console |
|---|---|---|---|
| `espp::SystemService` -- device info, reboot, reboot into the bootloader | 7 | `espp.system` | [system console](https://esp-cpp.github.io/espp/apps/system_console.html) |
| `espp::MonitorService` -- heap regions + task table, on request or streamed | 8 | `espp.monitor` | system console |
| `espp::OtaService` -- firmware update (host-driven rollback confirmation) | 0 | `espp.ota` | [OTA console](https://esp-cpp.github.io/espp/apps/ota_console.html) |
| `espp::CoreDumpService` -- last-crash report, core dump download / erase | 4 | `espp.coredump` | [coredump console](https://esp-cpp.github.io/espp/apps/coredump_console.html) |

`partitions.csv` therefore carries the OTA layout (`otadata`, `ota_0`, `ota_1`)
plus a `coredump` partition, and `sdkconfig.defaults` enables core dumps to
flash, OTA rollback and the FreeRTOS run-time statistics the task monitor
reads. Every device->host write on a transport goes through one mutex, so the
services (and any streaming) never interleave frames.

## Notes

- Native USB (vendor / WebUSB) needs an ESP32-S3 (also S2 / P4) — not the
  classic ESP32. `sdkconfig.defaults` pins `esp32s3` and enables the TinyUSB
  vendor class.
- WebUSB / Web Serial are Chromium-only and need a secure context (`https`,
  `http://localhost`, or `file://`).

To create a project from this example, run:

idf.py create-project-from-example "espp/telemetry=1.3.6:example"

or download archive (~9.33 KB)