290 lines
9.0 KiB
Markdown
290 lines
9.0 KiB
Markdown
# Architecture And Flow Diagrams
|
|
|
|
This document captures the current project architecture and major runtime flows
|
|
in Mermaid format. The diagrams reflect the implementation in the repository,
|
|
not older planning notes.
|
|
|
|
## Layered Architecture
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
Main["main/app_main"]
|
|
App["app_composition\nstartup sequencing and wiring"]
|
|
CP["control_plane\npolicy, lifecycle, workers, retry/backoff"]
|
|
Domain["domain\nbusiness contracts, adapters, semantic mapping"]
|
|
Platform["platform\nhardware, transport, storage, display, audio"]
|
|
HW["ESP32-S3 hardware\nLCD, audio codec, GPIO, Wi-Fi, flash"]
|
|
|
|
Main --> App
|
|
App --> CP
|
|
CP --> Domain
|
|
Domain --> Platform
|
|
Platform --> HW
|
|
```
|
|
|
|
## Component Responsibility Map
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph AppComposition["app_composition"]
|
|
Boot["Plan A boot sequence"]
|
|
Wire["Runtime wiring"]
|
|
end
|
|
|
|
subgraph ControlPlane["control_plane"]
|
|
Connectivity["Connectivity bootstrap and Wi-Fi policy"]
|
|
Workers["Runtime worker ownership"]
|
|
Events["System event dispatch"]
|
|
MultimodalPolicy["Multimodal session policy"]
|
|
Fortune["Daily fortune policy"]
|
|
FactoryCli["Factory CLI diagnostics"]
|
|
end
|
|
|
|
subgraph Domain["domain"]
|
|
ExpressionMap["LCD expression semantic mapping"]
|
|
RuntimeAdapters["Runtime facade adapters"]
|
|
Direction["Direction and calibration model"]
|
|
FortuneDomain["Birth profile and fortune contracts"]
|
|
UserConfig["LAN user config routes"]
|
|
end
|
|
|
|
subgraph Platform["platform"]
|
|
LCD["ST7789 direct LCD backend"]
|
|
Audio["ES8311 audio pipeline"]
|
|
Network["Wi-Fi, BLE provisioning, HTTP, WebSocket"]
|
|
Storage["NVS, embedded assets, model partition"]
|
|
GPIO["GPIO, stepper, console UART"]
|
|
end
|
|
|
|
Boot --> Connectivity
|
|
Boot --> Workers
|
|
Wire --> Workers
|
|
Connectivity --> RuntimeAdapters
|
|
Workers --> Events
|
|
MultimodalPolicy --> RuntimeAdapters
|
|
Fortune --> FortuneDomain
|
|
Events --> ExpressionMap
|
|
RuntimeAdapters --> LCD
|
|
RuntimeAdapters --> Audio
|
|
RuntimeAdapters --> Network
|
|
RuntimeAdapters --> Storage
|
|
RuntimeAdapters --> GPIO
|
|
```
|
|
|
|
## Current Boot Sequence
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Main as app_main
|
|
participant App as app_composition
|
|
participant CP as control_plane
|
|
participant Domain as domain
|
|
participant Platform as platform
|
|
|
|
Main->>App: app_composition_start_default_runtime()
|
|
App->>CP: control_plane_prepare_runtime_storage()
|
|
CP->>Domain: prepare storage through runtime adapters
|
|
Domain->>Platform: NVS / storage initialization
|
|
|
|
App->>CP: control_plane_play_boot_sound(timeout)
|
|
CP->>Domain: domain_runtime_multimodal_audio_init()
|
|
Domain->>Platform: ES8311 / I2S / I2C audio init
|
|
CP->>Domain: domain_runtime_behavior_play_prompt_file()
|
|
Domain->>Platform: play prompt file
|
|
|
|
App->>CP: control_plane_init_lcd_device()
|
|
CP->>Domain: domain_runtime_init_lcd_device()
|
|
Domain->>Platform: LCD GPIO/SPI/ST7789 init
|
|
|
|
App->>CP: control_plane_start_lcd_render_worker()
|
|
CP->>CP: create cp_lcd_render task
|
|
CP->>Domain: domain_runtime_start_lcd_render_loop()
|
|
Domain->>Platform: lcd_direct_start_render_loop()
|
|
|
|
App->>CP: control_plane_init()
|
|
CP->>Domain: platform/domain runtime initialization
|
|
Domain->>Platform: stepper, storage, behavior adapters
|
|
|
|
App->>CP: control_plane_request_boot_expression()
|
|
CP->>Domain: request DOMAIN_EXPRESSION_IDLE
|
|
Domain->>Platform: queue LCD idle asset sequence
|
|
|
|
opt boot turntable calibration enabled
|
|
App->>CP: control_plane_calibrate()
|
|
CP->>Domain: direction calibration policy
|
|
Domain->>Platform: stepper + calibration switch
|
|
end
|
|
|
|
App->>CP: control_plane_bootstrap_connectivity()
|
|
CP->>Domain: Wi-Fi init / STA connect / BLE provisioning fallback
|
|
Domain->>Platform: Wi-Fi and provisioning primitives
|
|
|
|
App->>CP: control_plane_start_runtime_workers()
|
|
CP->>CP: start model, websocket wait, LCD, Wi-Fi state, events, keys, fortune
|
|
```
|
|
|
|
## Runtime Worker Topology
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
Start["control_plane_start_runtime_workers()"]
|
|
|
|
Start --> ModelQueue["ensure model command queue"]
|
|
Start --> ModelTask["cp_model_cmd"]
|
|
Start --> WsWait["WebSocket wait task"]
|
|
Start --> LcdTask["cp_lcd_render"]
|
|
Start --> WifiTask["cp_wifi_state"]
|
|
Start --> EventTask["cp_system_event"]
|
|
Start --> KeyTask["cp_key_input"]
|
|
Start --> FortuneTask["cp_fortune\nif FORTUNE_ENABLE"]
|
|
|
|
KeyTask --> EventTask
|
|
EventTask --> LcdTask
|
|
WsWait --> Multimodal["multimodal client/runtime"]
|
|
Multimodal --> ModelTask
|
|
Multimodal --> Audio["audio capture/playback"]
|
|
WifiTask --> LcdTask
|
|
FortuneTask --> FortuneApi["daily fortune API"]
|
|
```
|
|
|
|
## Connectivity Bootstrap Flow
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Start["control_plane_bootstrap_connectivity"]
|
|
InitWiFi["domain_runtime_network_wifi_init(seed credentials)"]
|
|
HasCreds{"saved Wi-Fi credentials?"}
|
|
StaConnect["connect STA with feedback"]
|
|
StaOk{"STA connected?"}
|
|
KeepCreds{"error keeps credentials?"}
|
|
ClearCreds["clear saved Wi-Fi credentials"]
|
|
ResolvePop["resolve provisioning PoP\nserial number preferred"]
|
|
HasPop{"PoP available?"}
|
|
BleProv["start BLE provisioning"]
|
|
Done["return ESP_OK"]
|
|
Error["return error"]
|
|
|
|
Start --> InitWiFi --> HasCreds
|
|
HasCreds -- yes --> StaConnect --> StaOk
|
|
StaOk -- yes --> Done
|
|
StaOk -- no --> KeepCreds
|
|
KeepCreds -- yes --> Done
|
|
KeepCreds -- no --> ClearCreds --> ResolvePop
|
|
HasCreds -- no --> ResolvePop
|
|
ResolvePop --> HasPop
|
|
HasPop -- yes --> BleProv --> Done
|
|
HasPop -- no --> Error
|
|
```
|
|
|
|
## LCD Expression Flow
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
CP["control_plane policy/event"]
|
|
DomainReq["domain_runtime_request_expression()"]
|
|
Resolve["domain_resolve_expression_platform_request()"]
|
|
Catalog["domain expression catalog\nIDLE, WIFI_DISCONNECTED,\nSERVER_ERROR, MUYU, CHOUQIAN, WUXING"]
|
|
PlatformReq["platform_lcd_request_presentation()"]
|
|
Pending["lcd_direct pending request"]
|
|
Render["cp_lcd_render loop"]
|
|
Draw["decode PNG asset frame\nfrom embedded app image"]
|
|
Panel["ST7789 panel"]
|
|
|
|
CP --> DomainReq --> Resolve --> Catalog --> PlatformReq --> Pending --> Render --> Draw --> Panel
|
|
|
|
Draw --> Delay["vTaskDelay(frame_ms)"]
|
|
Delay --> Render
|
|
```
|
|
|
|
## Key And Local Event Flow
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
GPIO["GPIO edge interrupt\nButton 1/SW1 GPIO12\nButton 2/K2 GPIO13\nrocker SW2 GPIO6"]
|
|
IsrQueue["key IRQ queue"]
|
|
KeyTask["cp_key_input\ndebounce and click state machine"]
|
|
SystemQueue["system event queue"]
|
|
EventTask["cp_system_event"]
|
|
PttState["PTT active state"]
|
|
Chouqian["SW2 short press\nDOMAIN_EXPRESSION_CHOUQIAN"]
|
|
Wuxing["SW2 double click\nDOMAIN_EXPRESSION_WUXING"]
|
|
Muyu["PTT double click\nDOMAIN_EXPRESSION_MUYU"]
|
|
|
|
GPIO --> IsrQueue --> KeyTask --> SystemQueue --> EventTask
|
|
EventTask --> PttState
|
|
EventTask --> Chouqian
|
|
EventTask --> Wuxing
|
|
EventTask --> Muyu
|
|
```
|
|
|
|
## Multimodal Runtime Flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant CP as control_plane
|
|
participant Domain as domain
|
|
participant Platform as platform
|
|
participant WS as WebSocket server
|
|
participant Audio as ES8311 audio path
|
|
participant LCD as LCD expression
|
|
|
|
CP->>Domain: prepare multimodal start
|
|
CP->>Domain: register event callback
|
|
CP->>Domain: register downstream audio callback
|
|
CP->>CP: start multimodal watchdog task
|
|
CP->>Domain: control_plane_multimodal_start()
|
|
Domain->>Platform: open WebSocket transport
|
|
Platform->>WS: connect and send Start directive
|
|
|
|
WS-->>Platform: connected / task events
|
|
Platform-->>Domain: multimodal events
|
|
Domain-->>CP: event callback
|
|
|
|
WS-->>Platform: downstream audio binary
|
|
Platform-->>Domain: downstream audio callback
|
|
Domain-->>CP: control_plane_downstream_audio_bridge()
|
|
CP->>Audio: play downstream audio
|
|
|
|
alt transport/task/output error while STA connected
|
|
CP->>LCD: request DOMAIN_EXPRESSION_SERVER_ERROR
|
|
end
|
|
|
|
alt server responding starts
|
|
CP->>Audio: stop uplink if running
|
|
end
|
|
```
|
|
|
|
## Daily Fortune Flow
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Task["cp_fortune task"]
|
|
WaitTime["wait for local time / next midnight / refresh request"]
|
|
WaitNetwork["wait for STA and multimodal readiness"]
|
|
Date["resolve local date"]
|
|
Fetch["control_plane_refresh_daily_fortune(date)"]
|
|
DomainFortune["domain fortune APIs\nbirth profile + fortune result"]
|
|
Http["HTTPS fortune API"]
|
|
Persist["persist fortune result"]
|
|
Notify["notify observers / UI configuration server"]
|
|
Retry["retry delay on failure"]
|
|
|
|
Task --> WaitTime --> WaitNetwork --> Date --> Fetch
|
|
Fetch --> DomainFortune --> Http
|
|
Http -- success --> Persist --> Notify --> WaitTime
|
|
Http -- failure --> Retry --> WaitTime
|
|
```
|
|
|
|
## Factory CLI Diagnostics Flow
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
UART["UART0 serial input"]
|
|
CLI["factory CLI parser"]
|
|
Identity["identity / auth commands"]
|
|
UARTOut["UART0 JSON/OK/ERROR output"]
|
|
|
|
UART --> CLI
|
|
CLI --> Identity --> UARTOut
|
|
```
|