# Sensor Hub Static Architecture **Document Type:** Architecture Specification **Version:** 1.0 **Date:** 2025-01-19 **Traceability:** SRS Section 3.2, Annex B ## 1. Purpose and Scope This document defines the static architecture of the Sensor Hub firmware, including component structure, interfaces, data flows, and concurrency model. This architecture enforces separation of concerns, hardware abstraction, and state-aware operation as defined in the SRS and cross-feature constraints. **Audience:** Software architects, developers, reviewers, and test engineers. ## 2. Architectural Principles ### 2.1 Layered Architecture The Sensor Hub follows a **strict layered architecture** with the following principles: 1. **Dependency Direction:** Dependencies flow downward only (Application → Drivers → OSAL → HAL) 2. **Hardware Abstraction:** Application layer SHALL NOT access hardware directly (CFC-ARCH-01) 3. **Persistence Abstraction:** All persistence access SHALL go through DP component (CFC-ARCH-01, CFC-DATA-01) 4. **State Awareness:** All features SHALL respect system state restrictions (CFC-ARCH-02) ### 2.2 Component Responsibilities - **Single Responsibility:** Each component has one well-defined purpose - **Clear Interfaces:** Public APIs are minimal and well-documented - **Event-Driven Communication:** Cross-component communication via Event System - **State-Dependent Behavior:** Components adapt behavior based on system state ## 3. Architecture Views ### 3.1 Context View The Context View shows the Sensor Hub and its external actors. ```mermaid graph TB subgraph External["External Actors"] MainHub[Main Hub] PeerHub[Peer Sensor Hub] Sensors[Environmental Sensors] SDCard[SD Card] OLED[OLED Display] Buttons[Buttons] end subgraph SensorHub["Sensor Hub System"] AppLayer[Application Layer] Drivers[Drivers Layer] OSAL[OSAL Layer] HAL[HAL/ESP-IDF] end MainHub <-->|"Encrypted Communication"| AppLayer PeerHub <-->|"Peer Communication"| AppLayer Sensors -->|"I2C/SPI/UART/Analog"| Drivers SDCard <-->|"SPI/SD Protocol"| Drivers OLED <-->|"I2C"| Drivers Buttons -->|"GPIO"| Drivers AppLayer --> Drivers Drivers --> OSAL OSAL --> HAL ``` **External Interfaces:** - **Main Hub:** Bidirectional encrypted communication (Wi-Fi/Zigbee/LoRa) - **Peer Sensor Hub:** Limited peer-to-peer communication - **Sensors:** I2C, SPI, UART, Analog interfaces - **SD Card:** SPI/SD protocol for persistent storage - **OLED Display:** I2C for local HMI - **Buttons:** GPIO inputs for user interaction ### 3.2 Component View The Component View shows the major software components and their relationships. ```mermaid graph TB subgraph AppLayer["Application Layer"] subgraph BusinessStack["Business Stack"] STM[State Manager
STM] EventSys[Event System] SensorMgr[Sensor Manager] MCMgr[Machine Constant
Manager] OTAMgr[OTA Manager] MainHubAPI[Main Hub APIs] end subgraph DPStack["DP Stack"] DataPool[Data Pool] Persistence[Persistence] end DiagTask[Diagnostics Task] ErrorHandler[Error Handler] end subgraph Drivers["Drivers Layer"] SensorDrivers[Sensor Drivers
I2C/SPI/UART/ADC] NetworkStack[Network Stack
Wi-Fi/Zigbee/LoRa] DiagProtocol[Diagnostic Protocol
Stack] SDDriver[SD Card Driver] NVMDriver[NVM Driver] OLEDDriver[OLED Driver] ButtonDriver[Button Driver] end subgraph OSAL["OSAL Layer"] TaskOS[Task Abstraction] TimerOS[Software Timer] SocketOS[Socket Abstraction] end subgraph Utils["Utilities"] Logger[Logger] TimeUtils[Time Utils] end STM --> EventSys SensorMgr --> EventSys SensorMgr --> SensorDrivers MCMgr --> Persistence OTAMgr --> NetworkStack OTAMgr --> Persistence MainHubAPI --> NetworkStack MainHubAPI --> DataPool EventSys --> DataPool DataPool --> Persistence Persistence --> SDDriver Persistence --> NVMDriver DiagTask --> Persistence DiagTask --> EventSys ErrorHandler --> STM ErrorHandler --> DiagTask SensorMgr --> Logger OTAMgr --> Logger MainHubAPI --> Logger DiagTask --> Logger SensorMgr --> TimeUtils SensorDrivers --> TaskOS NetworkStack --> SocketOS NetworkStack --> TaskOS Persistence --> TaskOS SensorDrivers --> OSAL NetworkStack --> OSAL SDDriver --> OSAL OLEDDriver --> OSAL ButtonDriver --> OSAL ``` **Component Responsibilities:** | Component | Responsibility | Non-Responsibility | |-----------|----------------|-------------------| | **State Manager (STM)** | System state machine, state transitions, teardown coordination | Feature logic, hardware access | | **Event System** | Publish/subscribe event bus, cross-component communication | Business logic, state management | | **Sensor Manager** | Sensor lifecycle, acquisition scheduling, data filtering | Hardware access, persistence, communication | | **Machine Constant Manager** | MC loading, validation, update coordination | Sensor initialization, hardware access | | **OTA Manager** | OTA negotiation, firmware reception, validation, activation | Network stack implementation, secure boot | | **Main Hub APIs** | Main Hub communication protocol, message handling | Network stack implementation, sensor data generation | | **Data Pool** | Runtime data storage, latest sensor values, system state | Persistence, communication | | **Persistence** | Persistent storage abstraction, serialization, wear management | Business logic, hardware access | | **Diagnostics Task** | Diagnostic event collection, storage, query interface | Fault detection, state management | | **Error Handler** | Fault classification, escalation, state transition triggers | Diagnostic storage, feature logic | ### 3.3 Data Flow View The Data Flow View shows how data flows through the system. #### 3.3.1 Sensor Data Acquisition Flow ```mermaid sequenceDiagram participant Sensor as Sensor Hardware participant Driver as Sensor Driver participant SMgr as Sensor Manager participant EventSys as Event System participant DP as Data Pool participant Persist as Persistence participant MainHub as Main Hub APIs Note over Sensor,MainHub: Normal Acquisition Cycle SMgr->>Driver: readSensor(sensor_id) Driver->>Sensor: I2C/SPI/UART read Sensor-->>Driver: raw_sample Driver-->>SMgr: raw_sample loop 10 samples SMgr->>Driver: readSensor(sensor_id) Driver-->>SMgr: raw_sample end SMgr->>SMgr: filter(raw_samples) SMgr->>SMgr: generateTimestamp() SMgr->>EventSys: publish(SENSOR_DATA_UPDATE, record) EventSys->>DP: update(sensor_id, record) EventSys->>Persist: async_persist(record) EventSys->>MainHub: notify(SENSOR_DATA_UPDATE) MainHub->>MainHub: queueForTransmission(record) ``` #### 3.3.2 Diagnostic Event Flow ```mermaid sequenceDiagram participant Component as Any Component participant ErrorHandler as Error Handler participant DiagTask as Diagnostics Task participant EventSys as Event System participant STM as State Manager participant Persist as Persistence Component->>ErrorHandler: reportFault(diagnostic_code, severity) ErrorHandler->>ErrorHandler: classifyFault() ErrorHandler->>ErrorHandler: checkEscalation() alt Severity == FATAL ErrorHandler->>STM: triggerStateTransition(FAULT) STM->>EventSys: publish(STATE_CHANGED, FAULT) else Severity == WARNING ErrorHandler->>STM: triggerStateTransition(WARNING) end ErrorHandler->>DiagTask: logDiagnostic(event) DiagTask->>Persist: persistDiagnostic(event) DiagTask->>EventSys: publish(DIAGNOSTIC_EVENT, event) ``` #### 3.3.3 OTA Update Flow ```mermaid sequenceDiagram participant MainHub as Main Hub participant MainHubAPI as Main Hub APIs participant OTAMgr as OTA Manager participant STM as State Manager participant Persist as Persistence participant NetworkStack as Network Stack participant Security as Security MainHub->>MainHubAPI: OTA_REQUEST(message) MainHubAPI->>OTAMgr: otaRequestReceived() OTAMgr->>OTAMgr: validateReadiness() OTAMgr->>STM: requestStateTransition(OTA_PREP) STM->>STM: validateTransition() STM->>EventSys: publish(STATE_CHANGED, OTA_PREP) OTAMgr->>MainHubAPI: otaAcknowledge(ACCEPT) MainHubAPI->>MainHub: OTA_ACK(ACCEPT) OTAMgr->>STM: requestStateTransition(TEARDOWN) STM->>Persist: flushCriticalData() Persist-->>STM: flushComplete() STM->>EventSys: publish(STATE_CHANGED, TEARDOWN) STM->>STM: transitionTo(OTA_UPDATE) loop Firmware Chunks MainHub->>NetworkStack: firmwareChunk(data) NetworkStack->>OTAMgr: firmwareChunkReceived(data) OTAMgr->>Persist: storeFirmwareChunk(data) end OTAMgr->>Security: validateFirmwareIntegrity() Security-->>OTAMgr: validationResult alt Validation Success OTAMgr->>OTAMgr: flashFirmware() OTAMgr->>STM: reboot() else Validation Failure OTAMgr->>STM: requestStateTransition(FAULT) OTAMgr->>MainHubAPI: otaStatus(FAILED) end ``` ### 3.4 Concurrency View The Concurrency View shows the task model, priorities, and resource ownership. ```mermaid graph TB subgraph Tasks["RTOS Tasks"] SensorTask["Sensor Acquisition Task
Priority: HIGH
Stack: 8KB
Period: 1s"] CommTask["Communication Task
Priority: MEDIUM
Stack: 12KB
Event-driven"] PersistTask["Persistence Task
Priority: MEDIUM
Stack: 6KB
Event-driven"] DiagTask["Diagnostics Task
Priority: LOW
Stack: 4KB
Period: 10s"] HMITask["HMI Task
Priority: LOW
Stack: 4KB
Event-driven"] OTATask["OTA Task
Priority: HIGH
Stack: 16KB
Event-driven"] SystemTask["System Management Task
Priority: HIGH
Stack: 6KB
Event-driven"] end subgraph Components["Components"] SensorMgr[Sensor Manager] MainHubAPI[Main Hub APIs] Persistence[Persistence] DiagTaskComp[Diagnostics Task] HMI[HMI] OTAMgr[OTA Manager] STM[State Manager] end SensorTask --> SensorMgr CommTask --> MainHubAPI PersistTask --> Persistence DiagTask --> DiagTaskComp HMITask --> HMI OTATask --> OTAMgr SystemTask --> STM ``` **Task Priorities and Responsibilities:** | Task | Priority | Stack Size | Responsibility | Blocking Operations | |------|----------|------------|---------------|---------------------| | **Sensor Acquisition** | HIGH | 8KB | Sensor sampling, filtering | Sensor I/O (bounded) | | **Communication** | MEDIUM | 12KB | Main Hub communication | Network I/O (bounded) | | **Persistence** | MEDIUM | 6KB | Data persistence | Storage I/O (bounded) | | **Diagnostics** | LOW | 4KB | Diagnostic collection | None (non-blocking) | | **HMI** | LOW | 4KB | Display updates, button handling | Display I/O (bounded) | | **OTA** | HIGH | 16KB | Firmware update operations | Network I/O, flash I/O | | **System Management** | HIGH | 6KB | State machine, teardown | None (coordination only) | **Resource Ownership:** | Resource | Owner | Access Method | Concurrency Control | |----------|-------|--------------|---------------------| | **Sensor Drivers** | Sensor Acquisition Task | Direct (exclusive) | Task-level ownership | | **Network Stack** | Communication Task | Direct (exclusive) | Task-level ownership | | **SD Card** | Persistence Task | Direct (exclusive) | Mutex (if shared) | | **NVM** | Persistence Task | Direct (exclusive) | Mutex (if shared) | | **Data Pool** | All Tasks | Event System | Lock-free (atomic operations) | | **Event System** | All Tasks | Publish/Subscribe | Lock-free queue | | **State Machine** | System Management Task | Direct (exclusive) | Task-level ownership | ## 4. Component Specifications ### 4.1 State Manager (STM) **Location:** `application_layer/business_stack/STM/` **Responsibilities:** - Implement system FSM as defined in System State Machine Specification - Enforce valid state transitions - Coordinate teardown sequences - Notify components of state changes **Public API:** ```c // State query system_state_t stm_getCurrentState(void); bool stm_isStateValid(system_state_t state); // State transition bool stm_requestTransition(system_state_t target_state, transition_reason_t reason); bool stm_validateTransition(system_state_t from, system_state_t to); // Teardown coordination bool stm_initiateTeardown(teardown_reason_t reason); bool stm_isTeardownComplete(void); // Component registration bool stm_registerStateListener(state_listener_t listener); ``` **State Dependencies:** - SHALL be initialized first (during INIT state) - SHALL coordinate with Error Handler for fault-triggered transitions - SHALL coordinate with OTA Manager for OTA-triggered transitions ### 4.2 Event System **Location:** `application_layer/business_stack/event_system/` **Responsibilities:** - Provide publish/subscribe event bus - Decouple components via events - Ensure non-blocking event delivery **Public API:** ```c // Event types typedef enum { EVENT_SENSOR_DATA_UPDATE, EVENT_DIAGNOSTIC_EVENT, EVENT_STATE_CHANGED, EVENT_OTA_REQUEST, // ... other event types } event_type_t; // Publish event bool event_publish(event_type_t type, void* payload, size_t payload_size); // Subscribe to events bool event_subscribe(event_type_t type, event_handler_t handler); bool event_unsubscribe(event_type_t type, event_handler_t handler); ``` **Constraints:** - SHALL be non-blocking (lock-free queue) - SHALL support multiple subscribers per event type - SHALL NOT perform blocking operations in event handlers ### 4.3 Sensor Manager **Location:** `application_layer/business_stack/sensor_manager/` **Responsibilities:** - Sensor lifecycle management (detection, initialization, sampling) - High-frequency sampling and filtering - Timestamp generation - Sensor failure detection **Public API:** ```c // Sensor lifecycle bool sensorMgr_initialize(void); bool sensorMgr_detectSensors(void); bool sensorMgr_startAcquisition(void); bool sensorMgr_stopAcquisition(void); // Sensor data access bool sensorMgr_getLatestData(uint8_t sensor_id, sensor_data_record_t* record); bool sensorMgr_getAllSensorData(sensor_data_record_t* records, size_t* count); // Sensor status bool sensorMgr_isSensorPresent(uint8_t sensor_id); bool sensorMgr_isSensorEnabled(uint8_t sensor_id); ``` **State Dependencies:** - SHALL NOT perform acquisition during OTA_UPDATE, MC_UPDATE, TEARDOWN states - SHALL pause acquisition during SERVICE state (optional) - SHALL continue acquisition during SD_DEGRADED state (without persistence) ### 4.4 Data Persistence (DP Component) **Location:** `application_layer/DP_stack/persistence/` **Responsibilities:** - Abstract storage media (SD card, NVM) - Serialize/deserialize structured data - Manage wear-aware storage - Ensure data integrity **Public API:** ```c // Data persistence bool persistence_writeSensorData(const sensor_data_record_t* record); bool persistence_writeDiagnostic(const diagnostic_event_t* event); bool persistence_writeMachineConstants(const machine_constants_t* mc); // Data retrieval bool persistence_readSensorData(sensor_data_record_t* records, size_t* count); bool persistence_readDiagnostics(diagnostic_event_t* events, size_t* count); bool persistence_readMachineConstants(machine_constants_t* mc); // Flush operations bool persistence_flushCriticalData(void); bool persistence_isFlushComplete(void); ``` **Constraints:** - SHALL be the sole interface for persistent storage access (CFC-ARCH-01) - SHALL NOT allow direct hardware access from application layer - SHALL verify persistence completion before state transitions (CFC-DATA-02) ### 4.5 OTA Manager **Location:** `application_layer/business_stack/fw_upgrader/` **Responsibilities:** - OTA negotiation with Main Hub - Firmware reception and storage - Firmware integrity validation - Controlled firmware activation **Public API:** ```c // OTA operations bool ota_handleRequest(const ota_request_t* request); bool ota_receiveFirmwareChunk(const uint8_t* chunk, size_t chunk_size); bool ota_validateFirmware(void); bool ota_activateFirmware(void); // OTA status ota_status_t ota_getStatus(void); bool ota_isReady(void); ``` **State Dependencies:** - SHALL NOT operate during WARNING, FAULT, SERVICE, SD_DEGRADED states - SHALL coordinate with STM for state transitions - SHALL coordinate with Persistence for data flush before activation ## 5. Architectural Constraints Mapping | Constraint | Architectural Mechanism | Enforcement | |------------|-------------------------|-------------| | **CFC-ARCH-01** (Hardware Abstraction) | Driver layer abstraction, OSAL layer | Compile-time (no direct HAL includes in application) | | **CFC-ARCH-02** (State-Aware Execution) | STM state queries, per-state execution rules | Runtime (state checks in components) | | **CFC-TIME-01** (Non-Blocking) | Event System, async operations | Design-time (no blocking calls in critical paths) | | **CFC-TIME-02** (Deterministic) | Static memory allocation, bounded operations | Design-time (no dynamic allocation in acquisition) | | **CFC-DATA-01** (Single Source of Truth) | DP component as sole persistence interface | Compile-time (no direct storage access) | | **CFC-DATA-02** (Data Consistency) | Persistence flush before state transitions | Runtime (STM coordination) | | **CFC-SEC-01** (Security First) | Secure boot before application start | Boot-time (hardware-enforced) | | **CFC-SEC-02** (Encrypted Channels) | TLS/DTLS in Network Stack | Runtime (mandatory encryption) | | **CFC-DBG-01** (Debug Isolation) | Debug session authentication, state restrictions | Runtime (authentication checks) | ## 6. Repository Structure Mapping | Architecture Layer | Repository Path | Components | |-------------------|-----------------|------------| | **Application Layer** | `application_layer/business_stack/` | STM, Event System, Sensor Manager, MC Manager, OTA Manager, Main Hub APIs | | **DP Stack** | `application_layer/DP_stack/` | Data Pool, Persistence | | **Diagnostics** | `application_layer/diag_task/`, `application_layer/error_handler/` | Diagnostics Task, Error Handler | | **Drivers** | `drivers/` | Network Stack, Diagnostic Protocol, SD Card, NVM, Sensors | | **ESP-IDF Wrappers** | `ESP_IDF_FW_wrappers/` | GPIO, I2C, SPI, UART, ADC, DMA, Wi-Fi | | **OSAL** | `os/` | Task, Software Timer | | **Utilities** | `utils/` | Logger, Time Utils | ## 7. Traceability - **SRS Section 3.2:** Interface Requirements - **SRS Section 3.4:** Design Constraints - **Cross-Feature Constraints:** All architectural constraints mapped - **System State Machine Specification:** State-aware component behavior ## 8. Diagrams Summary - **Context View:** External interfaces and actors - **Component View:** Major components and relationships - **Data Flow View:** Sensor data, diagnostic, and OTA flows - **Concurrency View:** Task model, priorities, resource ownership --- **Next Steps:** - Component-level specifications (detailed APIs per component) - Sequence diagrams for additional flows (MC update, diagnostic session) - Interface Control Documents (ICD) for external interfaces