Files
ASF_01_sys_sw_arch/1 software design/components/ARCHITECTURE.md
2026-02-01 12:56:05 +01:00

19 KiB

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.

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.

graph TB
    subgraph AppLayer["Application Layer"]
        subgraph BusinessStack["Business Stack"]
            STM[State Manager<br/>STM]
            EventSys[Event System]
            SensorMgr[Sensor Manager]
            MCMgr[Machine Constant<br/>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<br/>I2C/SPI/UART/ADC]
        NetworkStack[Network Stack<br/>Wi-Fi/Zigbee/LoRa]
        DiagProtocol[Diagnostic Protocol<br/>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

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

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

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.

graph TB
    subgraph Tasks["RTOS Tasks"]
        SensorTask["Sensor Acquisition Task<br/>Priority: HIGH<br/>Stack: 8KB<br/>Period: 1s"]
        CommTask["Communication Task<br/>Priority: MEDIUM<br/>Stack: 12KB<br/>Event-driven"]
        PersistTask["Persistence Task<br/>Priority: MEDIUM<br/>Stack: 6KB<br/>Event-driven"]
        DiagTask["Diagnostics Task<br/>Priority: LOW<br/>Stack: 4KB<br/>Period: 10s"]
        HMITask["HMI Task<br/>Priority: LOW<br/>Stack: 4KB<br/>Event-driven"]
        OTATask["OTA Task<br/>Priority: HIGH<br/>Stack: 16KB<br/>Event-driven"]
        SystemTask["System Management Task<br/>Priority: HIGH<br/>Stack: 6KB<br/>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:

// 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:

// 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:

// 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:

// 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:

// 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