# fulcanellir/flock-noir architecture

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

- Interactive diagram: https://gitdiagram.com/fulcanellir/flock-noir
- Repository: https://github.com/fulcanellir/flock-noir

## Overview

Flock Noir is an embedded optical/radio evidence detector with a dashboard, alerts, and local recording/wardriving; the README also identifies a separate Raspberry Pi target. The main workflow is selecting a scan mode, collecting optical and radio observations, correlating evidence, then presenting/logging candidates. The sampled firmware excerpts emphasize radio processing, while some sensor and UI wiring is documented only at capability level. The Pi entry point shows its component assembly; unsampled implementation details and cross-component calls are omitted where evidence is insufficient.

Main entry points: [`pi/flocknoir/main.py`](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/main.py) (Pi Runtime), [`firmware/FlockNoir/radio.cpp`](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/radio.cpp) (Radio Scanner), [`pi/flocknoir/radio.py`](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/radio.py) (Pi Radio), [`pi/flocknoir/web.py`](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/web.py) (Pi Web Dashboard)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_firmware["XIAO Firmware"]
  node_radio["Radio Scanner<br/>[radio.cpp]"]
  node_wardrive["Wardrive Survey<br/>[wardriver.cpp]"]
  node_gps["GPS Timing<br/>[gps_time.h]"]
end

subgraph group_evidence["Detection Evidence"]
  node_radio_rules["Radio Rules<br/>[radio_protocol.h]"]
  node_optical["Optical Detection<br/>[detector.cpp]"]
  node_ir_sensor["OPT101 Sensor<br/>[irsensor.cpp]"]
  node_fusion["Evidence Fusion<br/>[fusion.h]"]
end

subgraph group_outputs["User Outputs"]
  node_dashboard["Mode Dashboard<br/>[web_ui.h]"]
  node_recorder["Video Recorder<br/>[recorder.cpp]"]
  node_buzzer["Sound Alerts<br/>[buzzer.cpp]"]
  node_storage[("SD Evidence Files<br/>[recorder.cpp]")]
end

subgraph group_pi["Raspberry Pi"]
  node_pi_main["Pi Runtime<br/>[main.py]"]
  node_pi_camera["Pi Camera<br/>[camera.py]"]
  node_pi_ir["Pi IR Sensor<br/>[irsensor.py]"]
  node_pi_radio["Pi Radio<br/>[radio.py]"]
  node_pi_fusion["Pi Native Parsers<br/>[core.cpp]"]
  node_pi_logger["Pi Evidence Logger<br/>[logger.py]"]
  node_pi_web["Pi Web Dashboard<br/>[web.py]"]
  node_pi_wardrive["Pi Wardrive<br/>[wardriver.py]"]
  node_pi_buzzer["Pi Sound Alerts<br/>[buzzer.py]"]
  node_settings[("Saved Settings<br/>[settings.py]")]
end

node_operator(("Operator"))

node_operator -->|"selects mode"| node_dashboard
node_dashboard -.->|"configures scan"| node_radio
node_radio -->|"matches packets"| node_radio_rules
node_radio -->|"checks survey state"| node_wardrive
node_radio -->|"requests alerts"| node_buzzer
node_radio -->|"uses evidence model"| node_fusion
node_optical -.->|"contributes evidence"| node_fusion
node_ir_sensor -.->|"contributes evidence"| node_fusion
node_recorder -->|"writes recordings"| node_storage
node_operator -->|"uses dashboard"| node_pi_web
node_pi_main -->|"creates camera"| node_pi_camera
node_pi_main -->|"creates sensor"| node_pi_ir
node_pi_main -->|"creates scanner"| node_pi_radio
node_pi_main -->|"creates logger"| node_pi_logger
node_pi_main -->|"creates surveyor"| node_pi_wardrive
node_pi_main -->|"creates alerts"| node_pi_buzzer
node_pi_main -->|"starts web app"| node_pi_web
node_pi_radio -->|"decodes evidence"| node_pi_fusion
node_pi_buzzer -->|"loads and saves"| node_settings
node_pi_web -->|"configures scanner"| node_pi_radio

click node_dashboard "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/web_ui.h"
click node_radio "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/radio.cpp"
click node_radio_rules "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/radio_protocol.h"
click node_optical "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/detector.cpp"
click node_ir_sensor "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/irsensor.cpp"
click node_fusion "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/fusion.h"
click node_recorder "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/recorder.cpp"
click node_wardrive "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/wardriver.cpp"
click node_buzzer "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/buzzer.cpp"
click node_gps "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/gps_time.h"
click node_storage "https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/recorder.cpp"
click node_pi_main "https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/main.py"
click node_pi_camera "https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/camera.py"
click node_pi_ir "https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/irsensor.py"
click node_pi_radio "https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/radio.py"
click node_pi_fusion "https://github.com/fulcanellir/flock-noir/blob/main/pi/native/core.cpp"
click node_pi_logger "https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/logger.py"
click node_pi_web "https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/web.py"
click node_pi_wardrive "https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/wardriver.py"
click node_pi_buzzer "https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/buzzer.py"
click node_settings "https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/settings.py"

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_radio,node_wardrive,node_gps toneBlue
class node_radio_rules,node_optical,node_ir_sensor,node_fusion toneAmber
class node_dashboard,node_recorder,node_buzzer,node_storage toneMint
class node_pi_main,node_pi_camera,node_pi_ir,node_pi_radio,node_pi_fusion,node_pi_logger,node_pi_web,node_pi_wardrive,node_pi_buzzer,node_settings toneRose
class node_operator toneIndigo
```

## Components

### XIAO Firmware

- [Radio Scanner](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/radio.cpp): `firmware/FlockNoir/radio.cpp`
- [Wardrive Survey](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/wardriver.cpp): `firmware/FlockNoir/wardriver.cpp`
- [GPS Timing](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/gps_time.h): `firmware/FlockNoir/gps_time.h`

### Detection Evidence

- [Radio Rules](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/radio_protocol.h): `firmware/FlockNoir/radio_protocol.h`
- [Optical Detection](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/detector.cpp): `firmware/FlockNoir/detector.cpp`
- [OPT101 Sensor](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/irsensor.cpp): `firmware/FlockNoir/irsensor.cpp`
- [Evidence Fusion](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/fusion.h): `firmware/FlockNoir/fusion.h`

### User Outputs

- [Mode Dashboard](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/web_ui.h): `firmware/FlockNoir/web_ui.h`
- [Video Recorder](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/recorder.cpp): `firmware/FlockNoir/recorder.cpp`
- [Sound Alerts](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/buzzer.cpp): `firmware/FlockNoir/buzzer.cpp`
- [SD Evidence Files](https://github.com/fulcanellir/flock-noir/blob/main/firmware/FlockNoir/recorder.cpp): `firmware/FlockNoir/recorder.cpp`

### Raspberry Pi

- [Pi Runtime](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/main.py): `pi/flocknoir/main.py`
- [Pi Camera](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/camera.py): `pi/flocknoir/camera.py`
- [Pi IR Sensor](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/irsensor.py): `pi/flocknoir/irsensor.py`
- [Pi Radio](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/radio.py): `pi/flocknoir/radio.py`
- [Pi Native Parsers](https://github.com/fulcanellir/flock-noir/blob/main/pi/native/core.cpp): `pi/native/core.cpp`
- [Pi Evidence Logger](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/logger.py): `pi/flocknoir/logger.py`
- [Pi Web Dashboard](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/web.py): `pi/flocknoir/web.py`
- [Pi Wardrive](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/wardriver.py): `pi/flocknoir/wardriver.py`
- [Pi Sound Alerts](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/buzzer.py): `pi/flocknoir/buzzer.py`
- [Saved Settings](https://github.com/fulcanellir/flock-noir/blob/main/pi/flocknoir/settings.py): `pi/flocknoir/settings.py`

### Other components

- **Operator**

## Connections

- Operator → Mode Dashboard: selects mode
- Mode Dashboard → Radio Scanner: configures scan
- Radio Scanner → Radio Rules: matches packets (evidence: `firmware/FlockNoir/radio.cpp`)
- Radio Scanner → Wardrive Survey: checks survey state (evidence: `firmware/FlockNoir/radio.cpp`)
- Radio Scanner → Sound Alerts: requests alerts (evidence: `firmware/FlockNoir/radio.cpp`)
- Radio Scanner → Evidence Fusion: uses evidence model
- Optical Detection → Evidence Fusion: contributes evidence
- OPT101 Sensor → Evidence Fusion: contributes evidence
- Video Recorder → SD Evidence Files: writes recordings (evidence: `firmware/FlockNoir/recorder.cpp`)
- Operator → Pi Web Dashboard: uses dashboard
- Pi Runtime → Pi Camera: creates camera (evidence: `pi/flocknoir/main.py`)
- Pi Runtime → Pi IR Sensor: creates sensor (evidence: `pi/flocknoir/main.py`)
- Pi Runtime → Pi Radio: creates scanner (evidence: `pi/flocknoir/main.py`)
- Pi Runtime → Pi Evidence Logger: creates logger (evidence: `pi/flocknoir/main.py`)
- Pi Runtime → Pi Wardrive: creates surveyor (evidence: `pi/flocknoir/main.py`)
- Pi Runtime → Pi Sound Alerts: creates alerts (evidence: `pi/flocknoir/main.py`)
- Pi Runtime → Pi Web Dashboard: starts web app (evidence: `pi/flocknoir/main.py`)
- Pi Radio → Pi Native Parsers: decodes evidence (evidence: `pi/flocknoir/radio.py`)
- Pi Sound Alerts → Saved Settings: loads and saves (evidence: `pi/flocknoir/buzzer.py`)
- Pi Web Dashboard → Pi Radio: configures scanner (evidence: `pi/flocknoir/web.py`)
