> ## Documentation Index
> Fetch the complete documentation index at: https://playbook.smedleygroup.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Telemetry: System Architecture

> The whole system on one page: the containers on the track machine, the conversion pipeline in AWS, and how the two data streams travel.

Telemetry is the only system in the estate that is not entirely cloud hosted, and that single fact shapes everything else about it. This page is the shape of the whole thing. Every box has a page of its own behind it.

## Architecture

![Telemetry architecture. One machine per hub region collects two data streams, reaching each kart only through the single ECAN or DAQ device fitted on it, never the controller or batteries directly. Charging data is stored in InfluxDB and exported by hand; DAQ runs are uploaded to S3 and converted by a Lambda. Both streams meet in the STL database. Line colour shows which stream a path belongs to.](https://mintcdn.com/smedley_group/J4Qb1kGrTQEJOjVR/images/software/developer/estate/systems/telemetry/architecture.png?fit=max\&auto=format\&n=J4Qb1kGrTQEJOjVR\&q=85\&s=06bbb63de720faa619f4c3ee65190224)

> [!NOTE]
>
> The diagram source is the draw\.io file at `images/software/developer/estate/systems/telemetry/architecture.drawio`. To change the diagram, edit that source in draw\.io, re-export it as PNG to `architecture.png` in the same folder, and commit both.

## What Is On A Kart

The left of the diagram is one kart, and it is grouped that way because the boundary matters. The receiver **never reaches the controller or the battery nodes directly**. It opens a TCP connection to the one device fitted on the kart, and everything else on the kart sits behind that device on the CAN bus.

| On the kart | Behaviour |
| - | - |
| Controller | Broadcasts its signals onto the CAN bus unprompted, at 50 Hz. Nothing asks it for anything |
| Battery nodes | Silent until asked. A node reports a value only in answer to a request frame |
| The fitted device | An **ECAN or a DAQ, never both**. Bridges the kart's CAN bus to TCP, and is the only thing the receiver talks to |

Which device is fitted changes what the receiver does, which is why the two TCP lines in the diagram are drawn differently:

* **With an ECAN**, the line is two way. The receiver's request frames travel over TCP to the ECAN, which puts them on the CAN bus, and the node answers come back the same way. The receiver is doing the polling, through the ECAN.
* **With a DAQ**, the line is one way. A DAQ replaces the ECAN entirely and polls the nodes itself, so the receiver only listens to what the DAQ sends. The same DAQ also records whole runs and posts them to the local API, which is the red path.

> [!NOTE]
>
> This is the reason the byte order setting in `ip-config.json` is a property of the fitted device rather than of the kart. Swap the device and the setting may need to change, even though nothing about the kart has. See [Fixing The Byte Order For An ECAN](/software/developer/estate/systems/telemetry/troubleshooting#fixing-the-byte-order-for-an-ecan).

## The Two Halves

The dashed boxes are the two places code runs, and the split between them is the thing to understand first.

| | The track machine | AWS |
| - | - | - |
| How many | One per hub region | One account, `eu-west-2` |
| Runs | Eleven containers as one Docker Compose stack | Two Lambdas, a topic and some queues |
| Started by | A person, every morning of an event | Nothing. It is always there |
| Updated by | A person running the setup script | The pipeline, on merge |
| Holds | Today's charging data only | Everything, permanently |

> [!WARNING]
>
> Those last two rows are the operational consequence of the split. A merge changes AWS immediately and changes a track only when someone next runs setup there, so the same version is not live everywhere at once. See [Deployment and the Pipeline](/software/developer/estate/systems/telemetry/deployment).

## The Two Streams

Line colour in the diagram is the stream, because the two barely touch until the very end.

**Charging data** is continuous. The receiver holds a TCP connection to each kart's fitted device, and the frames it reads travel over NATS to be decoded and written into InfluxDB. It is converted **on the track machine**, by an engineer working the dashboard, and nothing does it automatically.

**DAQ runs** are discrete. A unit on the kart records a whole run, posts it to the local API, and that API zips it and puts it in S3. Landing in S3 is what triggers conversion, which happens **in AWS**, and the whole path from there is automatic.

They meet in the STL database, which is where an engineer syncs from.

> [!NOTE]
>
> Note what the diagram shows about the receiver: internal signals go straight to the `telemetry_data` subject and skip the decode stage entirely. That is why a kart with nothing decodable still produces measurements. See [Internal Signals](/software/developer/estate/systems/telemetry/internal-signals).

## Where The People Are

Two of the boxes are people, and both are load bearing.

| Person | Does what nothing else does |
| - | - |
| Operator | Exports the day's charging data before the machine is stopped. Nothing reminds them, and InfluxDB is cleared on stopping |
| Engineer | Syncs the STL database down and opens it in SimTelLab |

> [!WARNING]
>
> The operator is the single most consequential manual step in the system. A day that is stopped without an export leaves that day's charging data recoverable only by restoring the backup archive.

## What The Diagram Leaves Out

Deliberately, so that it stays readable:

* **How the containers get there.** Images are built and pushed to ECR, and the `distribution/` folder is published to S3, by a CDK pipeline. See [Deployment and the Pipeline](/software/developer/estate/systems/telemetry/deployment).
* **The NATS cluster is three nodes**, drawn as its two subjects rather than its three containers.
* **Replica counts** beyond the two services that are scaled, and the internals of each container.
* **The kart fleet is many karts.** One kart is drawn, but the receiver holds a connection per fitted device, and more than one per kart where a kart exposes several.

## Where To Go Next

| Page | For |
| - | - |
| [Track Operations](/software/developer/estate/systems/telemetry/track-operations) | The machine, the container list, the event cycle and the backups |
| [The Charging Data Receiver](/software/developer/estate/systems/telemetry/receiver) | The left half of the track machine, frame by frame |
| [Charging Export](/software/developer/estate/systems/telemetry/charging-export) | The manual export, and what it does to the data |
| [Upload and Conversion](/software/developer/estate/systems/telemetry/daq-pipeline) | The DAQ path, from the kart to STL |
| [Timing and Lap Splitting](/software/developer/estate/systems/telemetry/timing-and-lap-splitting) | How TalentID turns a recording into laps |
| [Deployment and the Pipeline](/software/developer/estate/systems/telemetry/deployment) | Everything the diagram leaves out about shipping |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.