# lem-d/canairy architecture

> Architecture diagram of the GitHub repository lem-d/canairy, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-09). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/lem-d/canairy
- Repository: https://github.com/lem-d/canairy

## Overview

Canairy is a worker-safety monitoring system: wearable gas/SOS readings travel by RF to an Arduino receiver, then over USB through a Python bridge to a live React supervisor dashboard. The dashboard tracks worker status and history, prioritizes alerts, and provides worker and worksite views. The README documents the end-to-end hardware and WebSocket workflow; source-index references and excerpts support the shown software calls. Firmware internals and several bridge/dashboard details were not sampled, so those links are limited to documented relationships.

Main entry points: [`canairy-dashboard/src/App.js`](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/App.js) (Dashboard coordinator), [`canairy-dashboard/src/components/WorkerDetail.js`](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/WorkerDetail.js) (Worker detail), [`bridge/bridge.py`](https://github.com/lem-d/canairy/blob/main/bridge/bridge.py) (Bridge service), [`canairy-dashboard/src/hooks/useWorkers.js`](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/hooks/useWorkers.js) (Worker connection)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_firmware["Wearable and receiver"]
  node_wearable["Wearable sensing<br/>[wearable.ino]"]
  node_receiver["RF receiver<br/>[receiver.ino]"]
end

subgraph group_bridge["Bridge ingestion"]
  node_serial["Serial reader<br/>[serial_reader.py]"]
  node_parser["Line parser<br/>[line_parser.py]"]
  node_simulator["Worker simulator<br/>[simulator.py]"]
  node_registry["Worker names<br/>[workers.py]"]
  node_bridgeapp["Bridge service<br/>[bridge.py]"]
end

subgraph group_dashboard["Live dashboard"]
  node_hook["Worker connection<br/>[useWorkers.js]"]
  node_app["Dashboard coordinator<br/>[App.js]"]
  node_config["Dashboard settings<br/>[config.js]"]
  node_logic["Worker presentation logic<br/>[lib.js]"]
end

subgraph group_views["Safety views and data"]
  node_events["Event history<br/>[useEventLog.js]"]
  node_alerts["Alert banner<br/>[AlertBanner.js]"]
  node_cards["Worker cards<br/>[WorkerCard.js]"]
  node_detail["Worker detail<br/>[WorkerDetail.js]"]
  node_worksite["Worksite overview<br/>[Worksite.js]"]
  node_logs["Worker logs<br/>[WorkerLogs.js]"]
  node_gauge["Gas gauge<br/>[Gauge.js]"]
  node_sos["SOS indicator<br/>[SosTriangle.js]"]
  node_bars["Trend bars<br/>[Bars.js]"]
end

node_worker(("Field worker"))
node_browser(("Supervisor"))

node_worker -->|"wears"| node_wearable
node_wearable -->|"sends RF"| node_receiver
node_receiver -->|"streams USB"| node_serial
node_serial -->|"parses lines"| node_parser
node_serial -->|"reports readings"| node_bridgeapp
node_simulator -->|"uses names"| node_registry
node_simulator -->|"supplies readings"| node_bridgeapp
node_registry -->|"names workers"| node_bridgeapp
node_bridgeapp -->|"serves WebSocket"| node_browser
node_browser -->|"opens dashboard"| node_hook
node_hook -->|"receives snapshots"| node_bridgeapp
node_app -->|"loads worker data"| node_hook
node_app -->|"tracks events"| node_events
node_app -->|"renders alerts"| node_alerts
node_app -->|"renders workers"| node_cards
node_app -->|"renders selection"| node_detail
node_app -->|"renders overview"| node_worksite
node_worksite -->|"renders logs"| node_logs
node_worksite -->|"renders trend"| node_bars
node_cards -->|"renders gauge"| node_gauge
node_cards -->|"renders SOS"| node_sos
node_detail -->|"renders gauge"| node_gauge
node_detail -->|"renders SOS"| node_sos
node_detail -->|"renders history"| node_bars
node_detail -->|"displays events"| node_events
node_logs -->|"summarizes events"| node_events
node_hook -->|"reads connection settings"| node_config
node_app -->|"derives worker views"| node_logic
node_logic -->|"reads site settings"| node_config

click node_wearable "https://github.com/lem-d/canairy/blob/main/src/wearable/wearable.ino"
click node_receiver "https://github.com/lem-d/canairy/blob/main/src/receiver/receiver.ino"
click node_serial "https://github.com/lem-d/canairy/blob/main/bridge/serial_reader.py"
click node_parser "https://github.com/lem-d/canairy/blob/main/bridge/line_parser.py"
click node_simulator "https://github.com/lem-d/canairy/blob/main/bridge/simulator.py"
click node_registry "https://github.com/lem-d/canairy/blob/main/bridge/workers.py"
click node_bridgeapp "https://github.com/lem-d/canairy/blob/main/bridge/bridge.py"
click node_hook "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/hooks/useWorkers.js"
click node_app "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/App.js"
click node_events "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/hooks/useEventLog.js"
click node_alerts "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/AlertBanner.js"
click node_cards "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/WorkerCard.js"
click node_detail "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/WorkerDetail.js"
click node_worksite "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/Worksite.js"
click node_logs "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/WorkerLogs.js"
click node_gauge "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/Gauge.js"
click node_sos "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/SosTriangle.js"
click node_bars "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/Bars.js"
click node_config "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/config.js"
click node_logic "https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/lib.js"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_wearable,node_receiver toneBlue
class node_serial,node_parser,node_simulator,node_registry,node_bridgeapp toneAmber
class node_hook,node_app,node_config,node_logic toneMint
class node_events,node_alerts,node_cards,node_detail,node_worksite,node_logs,node_gauge,node_sos,node_bars,node_worker toneRose
class node_browser toneIndigo
```

## Components

### Wearable and receiver

- [Wearable sensing](https://github.com/lem-d/canairy/blob/main/src/wearable/wearable.ino): `src/wearable/wearable.ino`
- [RF receiver](https://github.com/lem-d/canairy/blob/main/src/receiver/receiver.ino): `src/receiver/receiver.ino`

### Bridge ingestion

- [Serial reader](https://github.com/lem-d/canairy/blob/main/bridge/serial_reader.py): `bridge/serial_reader.py`
- [Line parser](https://github.com/lem-d/canairy/blob/main/bridge/line_parser.py): `bridge/line_parser.py`
- [Worker simulator](https://github.com/lem-d/canairy/blob/main/bridge/simulator.py): `bridge/simulator.py`
- [Worker names](https://github.com/lem-d/canairy/blob/main/bridge/workers.py): `bridge/workers.py`
- [Bridge service](https://github.com/lem-d/canairy/blob/main/bridge/bridge.py): `bridge/bridge.py`

### Live dashboard

- [Worker connection](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/hooks/useWorkers.js): `canairy-dashboard/src/hooks/useWorkers.js`
- [Dashboard coordinator](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/App.js): `canairy-dashboard/src/App.js`
- [Dashboard settings](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/config.js): `canairy-dashboard/src/config.js`
- [Worker presentation logic](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/lib.js): `canairy-dashboard/src/lib.js`

### Safety views and data

- [Event history](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/hooks/useEventLog.js): `canairy-dashboard/src/hooks/useEventLog.js`
- [Alert banner](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/AlertBanner.js): `canairy-dashboard/src/components/AlertBanner.js`
- [Worker cards](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/WorkerCard.js): `canairy-dashboard/src/components/WorkerCard.js`
- [Worker detail](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/WorkerDetail.js): `canairy-dashboard/src/components/WorkerDetail.js`
- [Worksite overview](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/Worksite.js): `canairy-dashboard/src/components/Worksite.js`
- [Worker logs](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/WorkerLogs.js): `canairy-dashboard/src/components/WorkerLogs.js`
- [Gas gauge](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/Gauge.js): `canairy-dashboard/src/components/Gauge.js`
- [SOS indicator](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/SosTriangle.js): `canairy-dashboard/src/components/SosTriangle.js`
- [Trend bars](https://github.com/lem-d/canairy/blob/main/canairy-dashboard/src/components/Bars.js): `canairy-dashboard/src/components/Bars.js`

### Other components

- **Field worker**
- **Supervisor**

## Connections

- Field worker → Wearable sensing: wears (evidence: `README.MD`)
- Wearable sensing → RF receiver: sends RF (evidence: `README.MD`)
- RF receiver → Serial reader: streams USB (evidence: `README.MD`)
- Serial reader → Line parser: parses lines (evidence: `bridge/serial_reader.py`)
- Serial reader → Bridge service: reports readings (evidence: `bridge/bridge.py`)
- Worker simulator → Worker names: uses names (evidence: `bridge/simulator.py`)
- Worker simulator → Bridge service: supplies readings (evidence: `bridge/bridge.py`)
- Worker names → Bridge service: names workers (evidence: `bridge/bridge.py`)
- Bridge service → Supervisor: serves WebSocket (evidence: `README.MD`)
- Supervisor → Worker connection: opens dashboard (evidence: `README.MD`)
- Worker connection → Bridge service: receives snapshots (evidence: `README.MD`)
- Dashboard coordinator → Worker connection: loads worker data (evidence: `canairy-dashboard/src/App.js`)
- Dashboard coordinator → Event history: tracks events (evidence: `canairy-dashboard/src/App.js`)
- Dashboard coordinator → Alert banner: renders alerts (evidence: `canairy-dashboard/src/App.js`)
- Dashboard coordinator → Worker cards: renders workers (evidence: `canairy-dashboard/src/App.js`)
- Dashboard coordinator → Worker detail: renders selection (evidence: `canairy-dashboard/src/App.js`)
- Dashboard coordinator → Worksite overview: renders overview (evidence: `canairy-dashboard/src/App.js`)
- Worksite overview → Worker logs: renders logs (evidence: `canairy-dashboard/src/components/Worksite.js`)
- Worksite overview → Trend bars: renders trend (evidence: `canairy-dashboard/src/components/Worksite.js`)
- Worker cards → Gas gauge: renders gauge (evidence: `canairy-dashboard/src/components/WorkerCard.js`)
- Worker cards → SOS indicator: renders SOS (evidence: `canairy-dashboard/src/components/WorkerCard.js`)
- Worker detail → Gas gauge: renders gauge (evidence: `canairy-dashboard/src/components/WorkerDetail.js`)
- Worker detail → SOS indicator: renders SOS (evidence: `canairy-dashboard/src/components/WorkerDetail.js`)
- Worker detail → Trend bars: renders history (evidence: `canairy-dashboard/src/components/WorkerDetail.js`)
- Worker detail → Event history: displays events (evidence: `canairy-dashboard/src/components/WorkerDetail.js`)
- Worker logs → Event history: summarizes events (evidence: `canairy-dashboard/src/components/WorkerLogs.js`)
- Worker connection → Dashboard settings: reads connection settings (evidence: `canairy-dashboard/src/hooks/useWorkers.js`)
- Dashboard coordinator → Worker presentation logic: derives worker views (evidence: `canairy-dashboard/src/App.js`)
- Worker presentation logic → Dashboard settings: reads site settings (evidence: `canairy-dashboard/src/lib.js`)
