# lukassor/foid architecture

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

- Interactive diagram: https://gitdiagram.com/lukassor/foid
- Repository: https://github.com/lukassor/foid

## Overview

Foid is an offline, German-first room-control system: a person speaks a wake word and command, the voice process recognizes and interprets it, then sends a device action over newline-delimited JSON/TCP. The simulator applies actions to room state and updates its browser view; the same protocol is intended for a real room box. Settings and typed commands provide a second control surface. The graph preserves documented wake, STT, fuzzy/optional-LLM NLU, earcon, protocol, and simulator capabilities. Some voice internals are documented but unsampled, so their links reflect README-described flow.

Main entry points: [`voice/foid_voice/app.py`](https://github.com/lukassor/foid/blob/main/voice/foid_voice/app.py) (Voice process), [`room-sim/foid_sim/server.py`](https://github.com/lukassor/foid/blob/main/room-sim/foid_sim/server.py) (Simulator hub), [`protocol/foid_protocol/tcp.py`](https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/tcp.py) (TCP transport), [`voice/foid_voice/web.py`](https://github.com/lukassor/foid/blob/main/voice/foid_voice/web.py) (Settings server)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_voice_runtime["Voice runtime"]
  node_voice_runtime["Voice process<br/>[app.py]"]
  node_wake["Wake detection<br/>[wake.py]"]
  node_audio["Audio capture<br/>[audio.py]"]
  node_vad["Speech detection<br/>[vad.py]"]
  node_stt["Speech recognition<br/>[stt.py]"]
  node_nlu["Command interpretation<br/>[nlu.py]"]
  node_llm["Local LLM fallback<br/>[llm.py]"]
  node_earcons["Audio feedback<br/>[sounds.py]"]
  node_room_link["Room connection<br/>[room_client.py]"]
end

subgraph group_protocol_model["Protocol and devices"]
  node_catalog["Device catalog<br/>[catalog.py]"]
  node_device_yaml["Device definitions"]
  node_messages["Protocol messages<br/>[messages.py]"]
  node_codec["JSON line codec<br/>[codec.py]"]
  node_tcp["TCP transport<br/>[tcp.py]"]
end

subgraph group_room_simulator["Room simulator"]
  node_sim_hub["Simulator hub<br/>[server.py]"]
  node_room_state[("Room state<br/>[room.py]")]
  node_room_browser["Room browser view<br/>[room.js]"]
end

subgraph group_user_surfaces["User surfaces"]
  node_settings_server["Settings server<br/>[web.py]"]
  node_settings_page["Settings page<br/>[settings.html]"]
end

subgraph group_configuration["Settings and feedback"]
  node_settings["Voice settings<br/>[config.py]"]
  node_i18n["English/German text<br/>[i18n.py]"]
  node_wav_assets["Earcon WAVs"]
end

node_person(("Room user"))
node_microphone(("Microphone"))
node_local_llm["Local model runtime"]
node_room_box["Room control box"]

node_person -->|"speaks"| node_microphone
node_microphone -->|"audio frames"| node_audio
node_voice_runtime -->|"captures"| node_audio
node_voice_runtime -->|"detects wake"| node_wake
node_voice_runtime -->|"segments speech"| node_vad
node_voice_runtime -->|"transcribes"| node_stt
node_voice_runtime -->|"interprets text"| node_nlu
node_voice_runtime -->|"dispatches command"| node_room_link
node_voice_runtime -->|"plays cues"| node_earcons
node_audio -->|"audio frames"| node_wake
node_audio -->|"audio frames"| node_vad
node_vad -->|"speech audio"| node_stt
node_nlu -->|"matches phrases"| node_catalog
node_nlu -.->|"fallback interpretation"| node_llm
node_llm -.->|"runs model"| node_local_llm
node_catalog -->|"loads definitions"| node_device_yaml
node_earcons -->|"loads sounds"| node_wav_assets
node_room_link -->|"sends commands"| node_tcp
node_tcp -->|"encodes lines"| node_codec
node_codec -->|"serializes messages"| node_messages
node_tcp -->|"delivers messages"| node_sim_hub
node_tcp -.->|"protocol connection"| node_room_box
node_sim_hub -->|"parses messages"| node_messages
node_sim_hub -->|"applies actions"| node_room_state
node_room_state -->|"updates device state"| node_catalog
node_sim_hub -->|"broadcasts events"| node_tcp
node_sim_hub -->|"pushes room state"| node_room_browser
node_room_browser -->|"posts commands"| node_sim_hub
node_room_browser -->|"shows room"| node_person
node_person -->|"enters commands"| node_settings_page
node_settings_page -->|"submits settings"| node_settings_server
node_settings_server -->|"updates runtime"| node_voice_runtime
node_settings_server -->|"loads and saves"| node_settings
node_settings_server -->|"text command"| node_voice_runtime
node_sim_hub -->|"serves translations"| node_i18n

click node_voice_runtime "https://github.com/lukassor/foid/blob/main/voice/foid_voice/app.py"
click node_wake "https://github.com/lukassor/foid/blob/main/voice/foid_voice/wake.py"
click node_audio "https://github.com/lukassor/foid/blob/main/voice/foid_voice/audio.py"
click node_vad "https://github.com/lukassor/foid/blob/main/voice/foid_voice/vad.py"
click node_stt "https://github.com/lukassor/foid/blob/main/voice/foid_voice/stt.py"
click node_nlu "https://github.com/lukassor/foid/blob/main/voice/foid_voice/nlu.py"
click node_llm "https://github.com/lukassor/foid/blob/main/voice/foid_voice/llm.py"
click node_earcons "https://github.com/lukassor/foid/blob/main/voice/foid_voice/sounds.py"
click node_room_link "https://github.com/lukassor/foid/blob/main/voice/foid_voice/room_client.py"
click node_catalog "https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/catalog.py"
click node_device_yaml "https://github.com/lukassor/foid/tree/main/protocol/foid_protocol/devices"
click node_messages "https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/messages.py"
click node_codec "https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/codec.py"
click node_tcp "https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/tcp.py"
click node_sim_hub "https://github.com/lukassor/foid/blob/main/room-sim/foid_sim/server.py"
click node_room_state "https://github.com/lukassor/foid/blob/main/room-sim/foid_sim/room.py"
click node_room_browser "https://github.com/lukassor/foid/blob/main/room-sim/foid_sim/static/room.js"
click node_settings_server "https://github.com/lukassor/foid/blob/main/voice/foid_voice/web.py"
click node_settings_page "https://github.com/lukassor/foid/blob/main/voice/foid_voice/templates/settings.html"
click node_settings "https://github.com/lukassor/foid/blob/main/voice/foid_voice/config.py"
click node_i18n "https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/i18n.py"
click node_wav_assets "https://github.com/lukassor/foid/tree/main/voice/foid_voice/static/sounds"

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_voice_runtime,node_wake,node_audio,node_vad,node_stt,node_nlu,node_llm,node_earcons,node_room_link,node_person toneBlue
class node_catalog,node_device_yaml,node_messages,node_codec,node_tcp toneAmber
class node_sim_hub,node_room_state,node_room_browser toneMint
class node_settings_server,node_settings_page toneRose
class node_settings,node_i18n,node_wav_assets,node_microphone,node_local_llm,node_room_box toneIndigo
```

## Components

### Voice runtime

- [Voice process](https://github.com/lukassor/foid/blob/main/voice/foid_voice/app.py): `voice/foid_voice/app.py`
- [Wake detection](https://github.com/lukassor/foid/blob/main/voice/foid_voice/wake.py): `voice/foid_voice/wake.py`
- [Audio capture](https://github.com/lukassor/foid/blob/main/voice/foid_voice/audio.py): `voice/foid_voice/audio.py`
- [Speech detection](https://github.com/lukassor/foid/blob/main/voice/foid_voice/vad.py): `voice/foid_voice/vad.py`
- [Speech recognition](https://github.com/lukassor/foid/blob/main/voice/foid_voice/stt.py): `voice/foid_voice/stt.py`
- [Command interpretation](https://github.com/lukassor/foid/blob/main/voice/foid_voice/nlu.py): `voice/foid_voice/nlu.py`
- [Local LLM fallback](https://github.com/lukassor/foid/blob/main/voice/foid_voice/llm.py): `voice/foid_voice/llm.py`
- [Audio feedback](https://github.com/lukassor/foid/blob/main/voice/foid_voice/sounds.py): `voice/foid_voice/sounds.py`
- [Room connection](https://github.com/lukassor/foid/blob/main/voice/foid_voice/room_client.py): `voice/foid_voice/room_client.py`

### Protocol and devices

- [Device catalog](https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/catalog.py): `protocol/foid_protocol/catalog.py`
- [Device definitions](https://github.com/lukassor/foid/tree/main/protocol/foid_protocol/devices): `protocol/foid_protocol/devices`
- [Protocol messages](https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/messages.py): `protocol/foid_protocol/messages.py`
- [JSON line codec](https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/codec.py): `protocol/foid_protocol/codec.py`
- [TCP transport](https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/tcp.py): `protocol/foid_protocol/tcp.py`

### Room simulator

- [Simulator hub](https://github.com/lukassor/foid/blob/main/room-sim/foid_sim/server.py): `room-sim/foid_sim/server.py`
- [Room state](https://github.com/lukassor/foid/blob/main/room-sim/foid_sim/room.py): `room-sim/foid_sim/room.py`
- [Room browser view](https://github.com/lukassor/foid/blob/main/room-sim/foid_sim/static/room.js): `room-sim/foid_sim/static/room.js`

### User surfaces

- [Settings server](https://github.com/lukassor/foid/blob/main/voice/foid_voice/web.py): `voice/foid_voice/web.py`
- [Settings page](https://github.com/lukassor/foid/blob/main/voice/foid_voice/templates/settings.html): `voice/foid_voice/templates/settings.html`

### Settings and feedback

- [Voice settings](https://github.com/lukassor/foid/blob/main/voice/foid_voice/config.py): `voice/foid_voice/config.py`
- [English/German text](https://github.com/lukassor/foid/blob/main/protocol/foid_protocol/i18n.py): `protocol/foid_protocol/i18n.py`
- [Earcon WAVs](https://github.com/lukassor/foid/tree/main/voice/foid_voice/static/sounds): `voice/foid_voice/static/sounds`

### Other components

- **Room user**
- **Microphone**
- **Local model runtime**
- **Room control box**

## Connections

- Room user → Microphone: speaks
- Microphone → Audio capture: audio frames
- Voice process → Audio capture: captures
- Voice process → Wake detection: detects wake
- Voice process → Speech detection: segments speech
- Voice process → Speech recognition: transcribes
- Voice process → Command interpretation: interprets text
- Voice process → Room connection: dispatches command
- Voice process → Audio feedback: plays cues
- Audio capture → Wake detection: audio frames
- Audio capture → Speech detection: audio frames
- Speech detection → Speech recognition: speech audio
- Command interpretation → Device catalog: matches phrases
- Command interpretation → Local LLM fallback: fallback interpretation
- Local LLM fallback → Local model runtime: runs model
- Device catalog → Device definitions: loads definitions
- Audio feedback → Earcon WAVs: loads sounds
- Room connection → TCP transport: sends commands
- TCP transport → JSON line codec: encodes lines
- JSON line codec → Protocol messages: serializes messages
- TCP transport → Simulator hub: delivers messages
- TCP transport → Room control box: protocol connection
- Simulator hub → Protocol messages: parses messages
- Simulator hub → Room state: applies actions
- Room state → Device catalog: updates device state
- Simulator hub → TCP transport: broadcasts events
- Simulator hub → Room browser view: pushes room state
- Room browser view → Simulator hub: posts commands
- Room browser view → Room user: shows room
- Room user → Settings page: enters commands
- Settings page → Settings server: submits settings
- Settings server → Voice process: updates runtime
- Settings server → Voice settings: loads and saves
- Settings server → Voice process: text command
- Simulator hub → English/German text: serves translations
