From c6311103495dba585d9a3712ec71b7f36755e615 Mon Sep 17 00:00:00 2001 From: mahmamdouh Date: Sun, 25 Jan 2026 23:48:46 +0100 Subject: [PATCH] software design --- system_arch_final/.cursor | 96 + .../Cross-Feature Constraints.md | 120 ++ system_arch_final/Features.md | 359 ++++ .../Migration_and_Updates_Log.md | 224 +++ .../System Assumptions & Limitations.md | 83 + .../System_Architecture_Documentation.md | 302 ++++ .../[COM] Communication Features.md | 349 ++++ .../[DAQ] Sensor Data Acquisition Features.md | 320 ++++ ... Persistence & Data Management Features.md | 173 ++ ...iagnostics & Health Monitoring Features.md | 167 ++ ...QC] Data Quality & Calibration Features.md | 180 ++ .../[HW] Hardware Abstraction Features.md | 150 ++ .../[OTA] Firmware Update (OTA) Features.md | 236 +++ .../[PWR] Power & Fault Handling Features.md | 138 ++ .../[SEC] Security & Safety Features.md | 281 +++ .../[SYS] System Management Features.md | 314 ++++ system_arch_final/asf-arch_1.drawio | 203 +++ system_arch_final/asf-arch_1.drawio.png | Bin 0 -> 184066 bytes system_arch_final/selected sensors.html | 697 ++++++++ system_arch_final/selected sensors.txt | 453 +++++ .../software/Global_Software_Architecture.md | 866 +++++++++ system_arch_final/software/SRS.md | 515 ++++++ system_arch_final/software/SW design.md | 336 ++++ .../Software_Requirements_Traceability.md | 195 ++ .../System_Documentation_Validation_Report.md | 385 ++++ .../software/Traceability_Matrix.md | 395 +++++ .../software/components/ARCHITECTURE.md | 548 ++++++ .../components/ESP_IDF_FW_wrappers/README.md | 346 ++++ .../ESP_IDF_FW_wrappers/adc/CMakeLists.txt | 5 + .../ESP_IDF_FW_wrappers/adc/README.md | 276 +++ .../ESP_IDF_FW_wrappers/adc/com/adc.cpp | 363 ++++ .../ESP_IDF_FW_wrappers/adc/com/adc.hpp | 261 +++ .../ESP_IDF_FW_wrappers/adc/logging_data.csv | 28 + .../adc/test/adc_init_test.py | 34 + .../adc/test/adc_init_test.test_scenario.xml | 14 + .../ESP_IDF_FW_wrappers/adc/test/test_adc.cpp | 69 + .../ESP_IDF_FW_wrappers/bt/CMakeLists.txt | 5 + .../ESP_IDF_FW_wrappers/bt/README.md | 502 ++++++ .../ESP_IDF_FW_wrappers/bt/com/bt.cpp | 621 +++++++ .../ESP_IDF_FW_wrappers/bt/com/bt.hpp | 457 +++++ .../ESP_IDF_FW_wrappers/bt/logging_data.csv | 55 + .../bt/test/bt_init_test.py | 34 + .../ESP_IDF_FW_wrappers/bt/test/test_bt.cpp | 39 + .../ESP_IDF_FW_wrappers/dma/CMakeLists.txt | 5 + .../ESP_IDF_FW_wrappers/dma/README.md | 396 +++++ .../ESP_IDF_FW_wrappers/dma/com/dma.cpp | 512 ++++++ .../ESP_IDF_FW_wrappers/dma/com/dma.hpp | 386 ++++ .../ESP_IDF_FW_wrappers/dma/logging_data.csv | 46 + .../dma/test/dma_init_test.py | 34 + .../dma/test/dma_init_test.test_scenario.xml | 14 + .../ESP_IDF_FW_wrappers/dma/test/test_dma.cpp | 31 + .../ESP_IDF_FW_wrappers/gpio/CMakeLists.txt | 5 + .../ESP_IDF_FW_wrappers/gpio/README.md | 154 ++ .../ESP_IDF_FW_wrappers/gpio/com/gpio.cpp | 271 +++ .../ESP_IDF_FW_wrappers/gpio/com/gpio.hpp | 173 ++ .../ESP_IDF_FW_wrappers/gpio/logging_data.csv | 21 + .../gpio/test/gpio_init_test.py | 34 + .../test/gpio_init_test.test_scenario.xml | 14 + .../gpio/test/test_gpio.cpp | 65 + .../ESP_IDF_FW_wrappers/i2c/CMakeLists.txt | 6 + .../ESP_IDF_FW_wrappers/i2c/README.md | 216 +++ .../ESP_IDF_FW_wrappers/i2c/com/i2c.cpp | 273 +++ .../ESP_IDF_FW_wrappers/i2c/com/i2c.hpp | 183 ++ .../ESP_IDF_FW_wrappers/i2c/logging_data.csv | 24 + .../i2c/test/i2c_init_test.py | 34 + .../i2c/test/i2c_init_test.test_scenario.xml | 14 + .../ESP_IDF_FW_wrappers/i2c/test/test_i2c.cpp | 47 + .../ESP_IDF_FW_wrappers/spi/CMakeLists.txt | 5 + .../ESP_IDF_FW_wrappers/spi/README.md | 279 +++ .../ESP_IDF_FW_wrappers/spi/com/spi.cpp | 282 +++ .../ESP_IDF_FW_wrappers/spi/com/spi.hpp | 212 +++ .../ESP_IDF_FW_wrappers/spi/logging_data.csv | 21 + .../spi/test/spi_init_test.py | 34 + .../spi/test/spi_init_test.test_scenario.xml | 14 + .../ESP_IDF_FW_wrappers/spi/test/test_spi.cpp | 31 + .../ESP_IDF_FW_wrappers/uart/CMakeLists.txt | 5 + .../ESP_IDF_FW_wrappers/uart/README.md | 222 +++ .../ESP_IDF_FW_wrappers/uart/com/uart.cpp | 293 +++ .../ESP_IDF_FW_wrappers/uart/com/uart.hpp | 220 +++ .../ESP_IDF_FW_wrappers/uart/logging_data.csv | 27 + .../uart/test/test_uart.cpp | 31 + .../uart/test/uart_init_test.py | 34 + .../test/uart_init_test.test_scenario.xml | 14 + .../ESP_IDF_FW_wrappers/wifi/CMakeLists.txt | 5 + .../ESP_IDF_FW_wrappers/wifi/README.md | 323 ++++ .../ESP_IDF_FW_wrappers/wifi/com/wifi.cpp | 501 ++++++ .../ESP_IDF_FW_wrappers/wifi/com/wifi.hpp | 306 ++++ .../ESP_IDF_FW_wrappers/wifi/logging_data.csv | 38 + .../wifi/test/test_wifi.cpp | 42 + .../wifi/test/wifi_init_test.py | 34 + .../test/wifi_init_test.test_scenario.xml | 14 + .../DP_stack/data_pool/CMakeLists.txt | 5 + .../DP_stack/data_pool/COMPONENT_SPEC.md | 667 +++++++ .../DP_stack/data_pool/com/data_pool.cpp | 47 + .../DP_stack/data_pool/com/data_pool.hpp | 33 + .../DP_stack/data_pool/logging_data.csv | 2 + .../data_pool/test/data_pool_init_test.py | 34 + .../data_pool_init_test.test_scenario.xml | 14 + .../data_pool/test/test_data_pool.cpp | 40 + .../DP_stack/persistence/CMakeLists.txt | 5 + .../DP_stack/persistence/COMPONENT_SPEC.md | 257 +++ .../DP_stack/persistence/com/persistence.cpp | 47 + .../DP_stack/persistence/com/persistence.hpp | 33 + .../DP_stack/persistence/logging_data.csv | 2 + .../persistence/test/persistence_init_test.py | 34 + .../persistence_init_test.test_scenario.xml | 14 + .../persistence/test/test_persistence.cpp | 40 + .../business_stack/STM/CMakeLists.txt | 5 + .../business_stack/STM/COMPONENT_SPEC.md | 291 +++ .../business_stack/STM/com/stm.cpp | 47 + .../business_stack/STM/com/stm.hpp | 33 + .../business_stack/STM/logging_data.csv | 2 + .../business_stack/STM/test/stm_init_test.py | 34 + .../STM/test/stm_init_test.test_scenario.xml | 14 + .../business_stack/STM/test/test_stm.cpp | 40 + .../actuator_manager/CMakeLists.txt | 5 + .../actuator_manager/com/actuator_manager.cpp | 46 + .../actuator_manager/com/actuator_manager.hpp | 33 + .../actuator_manager/logging_data.csv | 2 + .../robot_keywords.cpython-313.pyc | Bin 0 -> 2637 bytes .../test/actuator_manager_init_test.py | 34 + ...tuator_manager_init_test.test_scenario.xml | 12 + .../test/actuator_manager_init_test2.py | 56 + .../test/test_actuator_manager.cpp | 40 + .../event_system/CMakeLists.txt | 5 + .../event_system/COMPONENT_SPEC.md | 200 +++ .../event_system/com/event_system.cpp | 46 + .../event_system/com/event_system.hpp | 33 + .../event_system/logging_data.csv | 2 + .../test/event_system_init_test.py | 34 + .../event_system_init_test.test_scenario.xml | 14 + .../event_system/test/test_event_system.cpp | 40 + .../business_stack/fw_upgrader/CMakeLists.txt | 5 + .../fw_upgrader/com/fw_upgrader.cpp | 47 + .../fw_upgrader/com/fw_upgrader.hpp | 33 + .../fw_upgrader/logging_data.csv | 2 + .../fw_upgrader/test/fw_upgrader_init_test.py | 44 + .../fw_upgrader_init_test.test_scenario.xml | 14 + .../fw_upgrader/test/test_fw_upgrader.cpp | 40 + .../machine_constant_manager/CMakeLists.txt | 5 + .../com/machine_constant_manager.cpp | 47 + .../com/machine_constant_manager.hpp | 33 + .../machine_constant_manager/logging_data.csv | 2 + .../machine_constant_manager_init_test.py | 34 + ...nstant_manager_init_test.test_scenario.xml | 14 + .../test/test_machine_constant_manager.cpp | 40 + .../main_hub_apis/CMakeLists.txt | 5 + .../main_hub_apis/com/main_hub_apis.cpp | 47 + .../main_hub_apis/com/main_hub_apis.hpp | 33 + .../main_hub_apis/logging_data.csv | 2 + .../test/main_hub_apis_init_test.py | 34 + .../main_hub_apis_init_test.test_scenario.xml | 14 + .../main_hub_apis/test/test_main_hub_apis.cpp | 40 + .../sensor_manager/CMakeLists.txt | 5 + .../sensor_manager/COMPONENT_SPEC.md | 652 +++++++ .../sensor_manager/com/sensor_manager.cpp | 47 + .../sensor_manager/com/sensor_manager.hpp | 33 + .../sensor_manager/logging_data.csv | 2 + .../test/sensor_manager_init_test.py | 34 + ...sensor_manager_init_test.test_scenario.xml | 14 + .../test/test_sensor_manager.cpp | 40 + .../diag_task/CMakeLists.txt | 5 + .../diag_task/com/diag_task.cpp | 47 + .../diag_task/com/diag_task.hpp | 33 + .../diag_task/logging_data.csv | 2 + .../diag_task/test/diag_task_init_test.py | 34 + .../diag_task_init_test.test_scenario.xml | 14 + .../diag_task/test/test_diag_task.cpp | 40 + .../error_handler/CMakeLists.txt | 5 + .../error_handler/com/error_handler.cpp | 47 + .../error_handler/com/error_handler.hpp | 33 + .../error_handler/logging_data.csv | 2 + .../test/error_handler_init_test.py | 34 + .../error_handler_init_test.test_scenario.xml | 14 + .../error_handler/test/test_error_handler.cpp | 40 + system_arch_final/software/components/arch.md | 413 +++++ .../components/drivers/SDcard/CMakeLists.txt | 5 + .../drivers/SDcard/SD-1.3.0/LICENSE.txt | 674 +++++++ .../drivers/SDcard/SD-1.3.0/README.adoc | 13 + .../drivers/SDcard/SD-1.3.0/docs/api.md | 894 ++++++++++ .../drivers/SDcard/SD-1.3.0/docs/readme.md | 23 + .../SD-1.3.0/examples/CardInfo/CardInfo.ino | 118 ++ .../examples/Datalogger/Datalogger.ino | 79 + .../SD-1.3.0/examples/DumpFile/DumpFile.ino | 65 + .../SDcard/SD-1.3.0/examples/Files/Files.ino | 76 + .../NonBlockingWrite/NonBlockingWrite.ino | 118 ++ .../SD-1.3.0/examples/ReadWrite/ReadWrite.ino | 80 + .../SD-1.3.0/examples/listfiles/listfiles.ino | 86 + .../drivers/SDcard/SD-1.3.0/keywords.txt | 31 + .../SDcard/SD-1.3.0/library.properties | 9 + .../drivers/SDcard/SD-1.3.0/src/File.cpp | 168 ++ .../drivers/SDcard/SD-1.3.0/src/README.txt | 13 + .../drivers/SDcard/SD-1.3.0/src/SD.cpp | 639 +++++++ .../drivers/SDcard/SD-1.3.0/src/SD.h | 138 ++ .../SDcard/SD-1.3.0/src/utility/FatStructs.h | 418 +++++ .../SDcard/SD-1.3.0/src/utility/Sd2Card.cpp | 777 ++++++++ .../SDcard/SD-1.3.0/src/utility/Sd2Card.h | 273 +++ .../SDcard/SD-1.3.0/src/utility/Sd2PinMap.h | 528 ++++++ .../SDcard/SD-1.3.0/src/utility/SdFat.h | 641 +++++++ .../SDcard/SD-1.3.0/src/utility/SdFatUtil.h | 77 + .../SD-1.3.0/src/utility/SdFatmainpage.h | 202 +++ .../SDcard/SD-1.3.0/src/utility/SdFile.cpp | 1527 ++++++++++++++++ .../SDcard/SD-1.3.0/src/utility/SdInfo.h | 232 +++ .../SDcard/SD-1.3.0/src/utility/SdVolume.cpp | 351 ++++ .../components/drivers/SDcard/com/sdcard.cpp | 1563 +++++++++++++++++ .../components/drivers/SDcard/com/sdcard.hpp | 161 ++ .../drivers/SDcard/logging_data.csv | 2 + .../drivers/SDcard/test/sdcard_init_test.py | 34 + .../test/sdcard_init_test.test_scenario.xml | 14 + .../drivers/SDcard/test/test_sdcard.cpp | 31 + .../diag_protocol_stack/CMakeLists.txt | 5 + .../com/diag_protocol_stack.cpp | 47 + .../com/diag_protocol_stack.hpp | 33 + .../diag_protocol_stack/logging_data.csv | 2 + .../test/diag_protocol_stack_init_test.py | 34 + ...protocol_stack_init_test.test_scenario.xml | 14 + .../test/test_diag_protocol_stack.cpp | 40 + .../drivers/network_stack/CMakeLists.txt | 5 + .../network_stack/com/network_stack.cpp | 47 + .../network_stack/com/network_stack.hpp | 33 + .../drivers/network_stack/logging_data.csv | 2 + .../test/network_stack_init_test.py | 34 + .../network_stack_init_test.test_scenario.xml | 14 + .../network_stack/test/test_network_stack.cpp | 40 + .../components/drivers/nvm/CMakeLists.txt | 5 + .../components/drivers/nvm/com/nvm.cpp | 87 + .../components/drivers/nvm/com/nvm.hpp | 49 + .../components/drivers/nvm/logging_data.csv | 2 + .../drivers/nvm/test/nvm_init_test.py | 34 + .../nvm/test/nvm_init_test.test_scenario.xml | 14 + .../components/drivers/nvm/test/test_nvm.cpp | 47 + .../drivers/sensors/ammonia/CMakeLists.txt | 5 + .../drivers/sensors/ammonia/com/ammonia.cpp | 47 + .../drivers/sensors/ammonia/com/ammonia.hpp | 33 + .../drivers/sensors/ammonia/logging_data.csv | 2 + .../sensors/ammonia/test/ammonia_init_test.py | 34 + .../test/ammonia_init_test.test_scenario.xml | 14 + .../sensors/ammonia/test/test_ammonia.cpp | 40 + .../drivers/sensors/co2/CMakeLists.txt | 5 + .../drivers/sensors/co2/com/co2.cpp | 47 + .../drivers/sensors/co2/com/co2.hpp | 33 + .../drivers/sensors/co2/logging_data.csv | 2 + .../drivers/sensors/co2/test/co2_init_test.py | 34 + .../co2/test/co2_init_test.test_scenario.xml | 14 + .../drivers/sensors/co2/test/test_co2.cpp | 40 + .../drivers/sensors/humidity/CMakeLists.txt | 5 + .../drivers/sensors/humidity/com/humidity.cpp | 47 + .../drivers/sensors/humidity/com/humidity.hpp | 33 + .../drivers/sensors/humidity/logging_data.csv | 2 + .../humidity/test/humidity_init_test.py | 34 + .../test/humidity_init_test.test_scenario.xml | 14 + .../sensors/humidity/test/test_humidity.cpp | 40 + .../drivers/sensors/light/CMakeLists.txt | 5 + .../drivers/sensors/light/com/light.cpp | 47 + .../drivers/sensors/light/com/light.hpp | 33 + .../drivers/sensors/light/logging_data.csv | 2 + .../sensors/light/test/light_init_test.py | 34 + .../test/light_init_test.test_scenario.xml | 14 + .../drivers/sensors/light/test/test_light.cpp | 40 + .../drivers/sensors/temprature/CMakeLists.txt | 5 + .../sensors/temprature/com/temprature.cpp | 47 + .../sensors/temprature/com/temprature.hpp | 33 + .../sensors/temprature/logging_data.csv | 2 + .../temprature/test/temprature_init_test.py | 34 + .../temprature_init_test.test_scenario.xml | 14 + .../temprature/test/test_temprature.cpp | 40 + .../drivers/sensors/voc/CMakeLists.txt | 5 + .../drivers/sensors/voc/com/voc.cpp | 47 + .../drivers/sensors/voc/com/voc.hpp | 33 + .../drivers/sensors/voc/logging_data.csv | 2 + .../drivers/sensors/voc/test/test_voc.cpp | 40 + .../drivers/sensors/voc/test/voc_init_test.py | 34 + .../voc/test/voc_init_test.test_scenario.xml | 14 + .../components/os/swtimer/CMakeLists.txt | 4 + .../components/os/swtimer/com/swtimer.cpp | 81 + .../components/os/swtimer/com/swtimer.hpp | 95 + .../os/swtimer/test/test_swtimer.cpp | 108 ++ .../components/os/task/CMakeLists.txt | 4 + .../software/components/os/task/com/task.cpp | 111 ++ .../software/components/os/task/com/task.hpp | 134 ++ .../components/os/task/test/test_task.cpp | 114 ++ .../components/perf_tests/CMakeLists.txt | 23 + .../ESP32_Performance_Tests_Documentation.md | 708 ++++++++ .../software/components/perf_tests/Kconfig | 26 + .../components/perf_tests/test/perf_tests.cpp | 574 ++++++ .../__pycache__/scan_serial.cpython-313.pyc | Bin 0 -> 5757 bytes .../components/system_tests/scan_serial.py | 109 ++ .../components/system_tests/smoke_test_hil.py | 45 + .../system_tests/smoke_test_simulator.py | 45 + .../components/utils/logger/ARCHITECTURE.md | 601 +++++++ .../components/utils/logger/CMakeLists.txt | 5 + .../components/utils/logger/DIAGRAMS.md | 689 ++++++++ .../components/utils/logger/README.md | 431 +++++ .../components/utils/logger/USAGE_GUIDE.md | 630 +++++++ .../components/utils/logger/com/logger.cpp | 366 ++++ .../components/utils/logger/com/logger.hpp | 226 +++ .../logger/example/gpio_wrapper_example.cpp | 355 ++++ .../utils/logger/test/CMakeLists.txt | 5 + .../utils/logger/test/test_logger.cpp | 292 +++ .../utils/time_utils/CMakeLists.txt | 5 + .../utils/time_utils/com/time_utils.cpp | 44 + .../utils/time_utils/com/time_utils.hpp | 25 + .../features/F-DAQ_Sensor_Data_Acquisition.md | 445 +++++ .../features/F-SYS_System_Management.md | 640 +++++++ system_arch_final/software/features/README.md | 89 + 305 files changed, 40333 insertions(+) create mode 100644 system_arch_final/.cursor create mode 100644 system_arch_final/Cross-Feature Constraints.md create mode 100644 system_arch_final/Features.md create mode 100644 system_arch_final/Migration_and_Updates_Log.md create mode 100644 system_arch_final/System Assumptions & Limitations.md create mode 100644 system_arch_final/System_Architecture_Documentation.md create mode 100644 system_arch_final/[COM] Communication Features.md create mode 100644 system_arch_final/[DAQ] Sensor Data Acquisition Features.md create mode 100644 system_arch_final/[DATA] Persistence & Data Management Features.md create mode 100644 system_arch_final/[DIAG] Diagnostics & Health Monitoring Features.md create mode 100644 system_arch_final/[DQC] Data Quality & Calibration Features.md create mode 100644 system_arch_final/[HW] Hardware Abstraction Features.md create mode 100644 system_arch_final/[OTA] Firmware Update (OTA) Features.md create mode 100644 system_arch_final/[PWR] Power & Fault Handling Features.md create mode 100644 system_arch_final/[SEC] Security & Safety Features.md create mode 100644 system_arch_final/[SYS] System Management Features.md create mode 100644 system_arch_final/asf-arch_1.drawio create mode 100644 system_arch_final/asf-arch_1.drawio.png create mode 100644 system_arch_final/selected sensors.html create mode 100644 system_arch_final/selected sensors.txt create mode 100644 system_arch_final/software/Global_Software_Architecture.md create mode 100644 system_arch_final/software/SRS.md create mode 100644 system_arch_final/software/SW design.md create mode 100644 system_arch_final/software/Software_Requirements_Traceability.md create mode 100644 system_arch_final/software/System_Documentation_Validation_Report.md create mode 100644 system_arch_final/software/Traceability_Matrix.md create mode 100644 system_arch_final/software/components/ARCHITECTURE.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/README.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/adc/CMakeLists.txt create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/adc/README.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/adc/com/adc.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/adc/com/adc.hpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/adc/logging_data.csv create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.py create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/adc/test/adc_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/adc/test/test_adc.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/bt/CMakeLists.txt create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/bt/README.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/bt/com/bt.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/bt/com/bt.hpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/bt/logging_data.csv create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/bt/test/bt_init_test.py create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/bt/test/test_bt.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/dma/CMakeLists.txt create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/dma/README.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/dma/com/dma.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/dma/com/dma.hpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/dma/logging_data.csv create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.py create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/dma/test/dma_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/dma/test/test_dma.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/gpio/CMakeLists.txt create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/gpio/README.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/gpio/com/gpio.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/gpio/com/gpio.hpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/gpio/logging_data.csv create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.py create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/gpio/test/gpio_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/gpio/test/test_gpio.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/i2c/CMakeLists.txt create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/i2c/README.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/i2c/com/i2c.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/i2c/com/i2c.hpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/i2c/logging_data.csv create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.py create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/i2c/test/i2c_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/i2c/test/test_i2c.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/spi/CMakeLists.txt create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/spi/README.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/spi/com/spi.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/spi/com/spi.hpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/spi/logging_data.csv create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.py create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/spi/test/spi_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/spi/test/test_spi.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/uart/CMakeLists.txt create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/uart/README.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/uart/com/uart.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/uart/com/uart.hpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/uart/logging_data.csv create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/uart/test/test_uart.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.py create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/uart/test/uart_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/wifi/CMakeLists.txt create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/wifi/README.md create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/wifi/com/wifi.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/wifi/com/wifi.hpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/wifi/logging_data.csv create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/wifi/test/test_wifi.cpp create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.py create mode 100644 system_arch_final/software/components/ESP_IDF_FW_wrappers/wifi/test/wifi_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/DP_stack/data_pool/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/DP_stack/data_pool/COMPONENT_SPEC.md create mode 100644 system_arch_final/software/components/application_layer/DP_stack/data_pool/com/data_pool.cpp create mode 100644 system_arch_final/software/components/application_layer/DP_stack/data_pool/com/data_pool.hpp create mode 100644 system_arch_final/software/components/application_layer/DP_stack/data_pool/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.py create mode 100644 system_arch_final/software/components/application_layer/DP_stack/data_pool/test/data_pool_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/DP_stack/data_pool/test/test_data_pool.cpp create mode 100644 system_arch_final/software/components/application_layer/DP_stack/persistence/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/DP_stack/persistence/COMPONENT_SPEC.md create mode 100644 system_arch_final/software/components/application_layer/DP_stack/persistence/com/persistence.cpp create mode 100644 system_arch_final/software/components/application_layer/DP_stack/persistence/com/persistence.hpp create mode 100644 system_arch_final/software/components/application_layer/DP_stack/persistence/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/DP_stack/persistence/test/persistence_init_test.py create mode 100644 system_arch_final/software/components/application_layer/DP_stack/persistence/test/persistence_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/DP_stack/persistence/test/test_persistence.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/STM/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/business_stack/STM/COMPONENT_SPEC.md create mode 100644 system_arch_final/software/components/application_layer/business_stack/STM/com/stm.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/STM/com/stm.hpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/STM/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/business_stack/STM/test/stm_init_test.py create mode 100644 system_arch_final/software/components/application_layer/business_stack/STM/test/stm_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/business_stack/STM/test/test_stm.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/actuator_manager/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/business_stack/actuator_manager/com/actuator_manager.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/actuator_manager/com/actuator_manager.hpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/actuator_manager/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/business_stack/actuator_manager/test/__pycache__/robot_keywords.cpython-313.pyc create mode 100644 system_arch_final/software/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.py create mode 100644 system_arch_final/software/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/business_stack/actuator_manager/test/actuator_manager_init_test2.py create mode 100644 system_arch_final/software/components/application_layer/business_stack/actuator_manager/test/test_actuator_manager.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/event_system/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/business_stack/event_system/COMPONENT_SPEC.md create mode 100644 system_arch_final/software/components/application_layer/business_stack/event_system/com/event_system.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/event_system/com/event_system.hpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/event_system/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/business_stack/event_system/test/event_system_init_test.py create mode 100644 system_arch_final/software/components/application_layer/business_stack/event_system/test/event_system_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/business_stack/event_system/test/test_event_system.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/fw_upgrader/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/fw_upgrader/com/fw_upgrader.hpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/fw_upgrader/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.py create mode 100644 system_arch_final/software/components/application_layer/business_stack/fw_upgrader/test/fw_upgrader_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/business_stack/fw_upgrader/test/test_fw_upgrader.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/machine_constant_manager/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/machine_constant_manager/com/machine_constant_manager.hpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/machine_constant_manager/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.py create mode 100644 system_arch_final/software/components/application_layer/business_stack/machine_constant_manager/test/machine_constant_manager_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/business_stack/machine_constant_manager/test/test_machine_constant_manager.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/main_hub_apis/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/main_hub_apis/com/main_hub_apis.hpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/main_hub_apis/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.py create mode 100644 system_arch_final/software/components/application_layer/business_stack/main_hub_apis/test/main_hub_apis_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/business_stack/main_hub_apis/test/test_main_hub_apis.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/sensor_manager/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/business_stack/sensor_manager/COMPONENT_SPEC.md create mode 100644 system_arch_final/software/components/application_layer/business_stack/sensor_manager/com/sensor_manager.cpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/sensor_manager/com/sensor_manager.hpp create mode 100644 system_arch_final/software/components/application_layer/business_stack/sensor_manager/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.py create mode 100644 system_arch_final/software/components/application_layer/business_stack/sensor_manager/test/sensor_manager_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/business_stack/sensor_manager/test/test_sensor_manager.cpp create mode 100644 system_arch_final/software/components/application_layer/diag_task/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/diag_task/com/diag_task.cpp create mode 100644 system_arch_final/software/components/application_layer/diag_task/com/diag_task.hpp create mode 100644 system_arch_final/software/components/application_layer/diag_task/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/diag_task/test/diag_task_init_test.py create mode 100644 system_arch_final/software/components/application_layer/diag_task/test/diag_task_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/diag_task/test/test_diag_task.cpp create mode 100644 system_arch_final/software/components/application_layer/error_handler/CMakeLists.txt create mode 100644 system_arch_final/software/components/application_layer/error_handler/com/error_handler.cpp create mode 100644 system_arch_final/software/components/application_layer/error_handler/com/error_handler.hpp create mode 100644 system_arch_final/software/components/application_layer/error_handler/logging_data.csv create mode 100644 system_arch_final/software/components/application_layer/error_handler/test/error_handler_init_test.py create mode 100644 system_arch_final/software/components/application_layer/error_handler/test/error_handler_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/application_layer/error_handler/test/test_error_handler.cpp create mode 100644 system_arch_final/software/components/arch.md create mode 100644 system_arch_final/software/components/drivers/SDcard/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/LICENSE.txt create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/README.adoc create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/docs/api.md create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/docs/readme.md create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/examples/CardInfo/CardInfo.ino create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/examples/Datalogger/Datalogger.ino create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/examples/DumpFile/DumpFile.ino create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/examples/Files/Files.ino create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/examples/NonBlockingWrite/NonBlockingWrite.ino create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/examples/ReadWrite/ReadWrite.ino create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/examples/listfiles/listfiles.ino create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/keywords.txt create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/library.properties create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/File.cpp create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/README.txt create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/SD.cpp create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/SD.h create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/FatStructs.h create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.cpp create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2Card.h create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/Sd2PinMap.h create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/SdFat.h create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatUtil.h create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/SdFatmainpage.h create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/SdFile.cpp create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/SdInfo.h create mode 100644 system_arch_final/software/components/drivers/SDcard/SD-1.3.0/src/utility/SdVolume.cpp create mode 100644 system_arch_final/software/components/drivers/SDcard/com/sdcard.cpp create mode 100644 system_arch_final/software/components/drivers/SDcard/com/sdcard.hpp create mode 100644 system_arch_final/software/components/drivers/SDcard/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/SDcard/test/sdcard_init_test.py create mode 100644 system_arch_final/software/components/drivers/SDcard/test/sdcard_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/drivers/SDcard/test/test_sdcard.cpp create mode 100644 system_arch_final/software/components/drivers/diag_protocol_stack/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/diag_protocol_stack/com/diag_protocol_stack.cpp create mode 100644 system_arch_final/software/components/drivers/diag_protocol_stack/com/diag_protocol_stack.hpp create mode 100644 system_arch_final/software/components/drivers/diag_protocol_stack/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.py create mode 100644 system_arch_final/software/components/drivers/diag_protocol_stack/test/diag_protocol_stack_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/drivers/diag_protocol_stack/test/test_diag_protocol_stack.cpp create mode 100644 system_arch_final/software/components/drivers/network_stack/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/network_stack/com/network_stack.cpp create mode 100644 system_arch_final/software/components/drivers/network_stack/com/network_stack.hpp create mode 100644 system_arch_final/software/components/drivers/network_stack/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/network_stack/test/network_stack_init_test.py create mode 100644 system_arch_final/software/components/drivers/network_stack/test/network_stack_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/drivers/network_stack/test/test_network_stack.cpp create mode 100644 system_arch_final/software/components/drivers/nvm/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/nvm/com/nvm.cpp create mode 100644 system_arch_final/software/components/drivers/nvm/com/nvm.hpp create mode 100644 system_arch_final/software/components/drivers/nvm/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/nvm/test/nvm_init_test.py create mode 100644 system_arch_final/software/components/drivers/nvm/test/nvm_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/drivers/nvm/test/test_nvm.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/ammonia/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/sensors/ammonia/com/ammonia.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/ammonia/com/ammonia.hpp create mode 100644 system_arch_final/software/components/drivers/sensors/ammonia/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/sensors/ammonia/test/ammonia_init_test.py create mode 100644 system_arch_final/software/components/drivers/sensors/ammonia/test/ammonia_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/drivers/sensors/ammonia/test/test_ammonia.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/co2/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/sensors/co2/com/co2.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/co2/com/co2.hpp create mode 100644 system_arch_final/software/components/drivers/sensors/co2/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/sensors/co2/test/co2_init_test.py create mode 100644 system_arch_final/software/components/drivers/sensors/co2/test/co2_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/drivers/sensors/co2/test/test_co2.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/humidity/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/sensors/humidity/com/humidity.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/humidity/com/humidity.hpp create mode 100644 system_arch_final/software/components/drivers/sensors/humidity/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/sensors/humidity/test/humidity_init_test.py create mode 100644 system_arch_final/software/components/drivers/sensors/humidity/test/humidity_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/drivers/sensors/humidity/test/test_humidity.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/light/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/sensors/light/com/light.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/light/com/light.hpp create mode 100644 system_arch_final/software/components/drivers/sensors/light/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/sensors/light/test/light_init_test.py create mode 100644 system_arch_final/software/components/drivers/sensors/light/test/light_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/drivers/sensors/light/test/test_light.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/temprature/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/sensors/temprature/com/temprature.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/temprature/com/temprature.hpp create mode 100644 system_arch_final/software/components/drivers/sensors/temprature/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/sensors/temprature/test/temprature_init_test.py create mode 100644 system_arch_final/software/components/drivers/sensors/temprature/test/temprature_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/drivers/sensors/temprature/test/test_temprature.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/voc/CMakeLists.txt create mode 100644 system_arch_final/software/components/drivers/sensors/voc/com/voc.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/voc/com/voc.hpp create mode 100644 system_arch_final/software/components/drivers/sensors/voc/logging_data.csv create mode 100644 system_arch_final/software/components/drivers/sensors/voc/test/test_voc.cpp create mode 100644 system_arch_final/software/components/drivers/sensors/voc/test/voc_init_test.py create mode 100644 system_arch_final/software/components/drivers/sensors/voc/test/voc_init_test.test_scenario.xml create mode 100644 system_arch_final/software/components/os/swtimer/CMakeLists.txt create mode 100644 system_arch_final/software/components/os/swtimer/com/swtimer.cpp create mode 100644 system_arch_final/software/components/os/swtimer/com/swtimer.hpp create mode 100644 system_arch_final/software/components/os/swtimer/test/test_swtimer.cpp create mode 100644 system_arch_final/software/components/os/task/CMakeLists.txt create mode 100644 system_arch_final/software/components/os/task/com/task.cpp create mode 100644 system_arch_final/software/components/os/task/com/task.hpp create mode 100644 system_arch_final/software/components/os/task/test/test_task.cpp create mode 100644 system_arch_final/software/components/perf_tests/CMakeLists.txt create mode 100644 system_arch_final/software/components/perf_tests/ESP32_Performance_Tests_Documentation.md create mode 100644 system_arch_final/software/components/perf_tests/Kconfig create mode 100644 system_arch_final/software/components/perf_tests/test/perf_tests.cpp create mode 100644 system_arch_final/software/components/system_tests/__pycache__/scan_serial.cpython-313.pyc create mode 100644 system_arch_final/software/components/system_tests/scan_serial.py create mode 100644 system_arch_final/software/components/system_tests/smoke_test_hil.py create mode 100644 system_arch_final/software/components/system_tests/smoke_test_simulator.py create mode 100644 system_arch_final/software/components/utils/logger/ARCHITECTURE.md create mode 100644 system_arch_final/software/components/utils/logger/CMakeLists.txt create mode 100644 system_arch_final/software/components/utils/logger/DIAGRAMS.md create mode 100644 system_arch_final/software/components/utils/logger/README.md create mode 100644 system_arch_final/software/components/utils/logger/USAGE_GUIDE.md create mode 100644 system_arch_final/software/components/utils/logger/com/logger.cpp create mode 100644 system_arch_final/software/components/utils/logger/com/logger.hpp create mode 100644 system_arch_final/software/components/utils/logger/example/gpio_wrapper_example.cpp create mode 100644 system_arch_final/software/components/utils/logger/test/CMakeLists.txt create mode 100644 system_arch_final/software/components/utils/logger/test/test_logger.cpp create mode 100644 system_arch_final/software/components/utils/time_utils/CMakeLists.txt create mode 100644 system_arch_final/software/components/utils/time_utils/com/time_utils.cpp create mode 100644 system_arch_final/software/components/utils/time_utils/com/time_utils.hpp create mode 100644 system_arch_final/software/features/F-DAQ_Sensor_Data_Acquisition.md create mode 100644 system_arch_final/software/features/F-SYS_System_Management.md create mode 100644 system_arch_final/software/features/README.md diff --git a/system_arch_final/.cursor b/system_arch_final/.cursor new file mode 100644 index 0000000..29e9991 --- /dev/null +++ b/system_arch_final/.cursor @@ -0,0 +1,96 @@ +# ASF Sensor Hub - Cursor Configuration + +## Project Context + +**Project Name:** ASF Sensor Hub (Sub-Hub) +**Target Platform:** ESP32-S3 microcontroller +**Framework:** ESP-IDF v5.4 +**RTOS:** FreeRTOS (included in ESP-IDF) +**Language:** C/C++ +**Domain:** Industrial / Agricultural Automation (Smart Poultry Farm) + +## Global Conditions + +### Hardware Platform +- **MCU:** ESP32-S3 +- **CPU:** Dual-core Xtensa LX7, 240 MHz +- **Memory:** 512KB SRAM, 8MB Flash +- **Security:** Secure Boot V2, Flash Encryption (AES-256), eFuse +- **Connectivity:** Wi-Fi 802.11n (2.4 GHz), ESP-NOW, Bluetooth (optional) + +### Software Framework +- **Framework:** ESP-IDF v5.4 +- **RTOS:** FreeRTOS +- **Language:** C/C++ (C++17 standard) +- **Build System:** CMake +- **Toolchain:** ESP-IDF toolchain + +### Communication Stack +- **Physical/Link:** Wi-Fi 802.11n (2.4 GHz) +- **Application Protocol:** MQTT over TLS 1.2 +- **Peer-to-Peer:** ESP-NOW +- **Payload Encoding:** CBOR (Binary, versioned) +- **Security:** Mutual TLS (mTLS) with X.509 certificates + +### Security Requirements +- **Secure Boot:** Secure Boot V2 (mandatory for production) +- **Flash Encryption:** AES-256 (hardware-accelerated) +- **Communication:** TLS 1.2 with mutual authentication (mTLS) +- **Key Storage:** eFuse or encrypted flash +- **Anti-Rollback:** eFuse-based version protection + +### Storage +- **Primary Storage:** SD Card (FAT32, SDMMC 4-bit) +- **Configuration Storage:** NVS (Encrypted, 64KB) +- **Firmware Storage:** Flash partitions (A/B partitioning: ota_0, ota_1) + +### System Architecture +- **Architecture Style:** Layered, Event-Driven, Component-Based +- **State Management:** Finite State Machine (11 states) +- **Communication:** Event-driven publish/subscribe +- **Persistence:** DP (Data Persistence) component abstraction + +### Development Constraints +- **No Direct Hardware Access:** Application layer must use abstraction layers +- **State-Aware Execution:** All features must respect system state +- **Non-Blocking Operations:** Critical paths must be non-blocking +- **Deterministic Behavior:** Time-critical tasks must have bounded execution time +- **Memory Management:** Minimal dynamic allocation in critical paths + +### Standards Compliance +- **Requirements:** ISO/IEC/IEEE 29148 (SRS) +- **Industrial Standards:** IEC 61499 (conceptual), ISA-95 (conceptual) +- **Security:** Industry-standard secure boot and encryption + +### Key Documents +- **Features:** `Features.md` and `[XXX] Feature Files.md` +- **State Machine:** `System_State_Machine_Specification.md` +- **Failure Handling:** `Failure_Handling_Model.md` +- **SRS:** `System Design/SRS/SRS.md` +- **Architecture:** `software design/components/ARCHITECTURE.md` +- **Component Specs:** `software design/components/.../COMPONENT_SPEC.md` + +### Important Notes +- This is an **industrial embedded system**, not consumer IoT +- **Reliability > Convenience** +- **Security is mandatory** +- **OTA must be fail-safe** +- **Power loss is expected** (brownout detection required) +- **SD card failure must be assumed** (fallback mode required) + +### Development Guidelines +- Follow **Cross-Feature Constraints** (`Cross-Feature Constraints.md`) +- Respect **System State Machine** (`System_State_Machine_Specification.md`) +- Implement **Failure Handling Model** (`Failure_Handling_Model.md`) +- Use **Component Specifications** for API definitions +- Maintain **Traceability** to System Requirements (SR-*) and Software Requirements (SWR-*) + +### Testing Requirements +- **Unit Tests:** Required for all components +- **Integration Tests:** Required for feature interactions +- **HIL/System Tests:** Required for system-level validation +- **V&V Matrix:** `System Design/SRS/VV_Matrix.md` defines verification methods + +--- + +**Use this context when generating code, documentation, or making architectural decisions.** diff --git a/system_arch_final/Cross-Feature Constraints.md b/system_arch_final/Cross-Feature Constraints.md new file mode 100644 index 0000000..298aad2 --- /dev/null +++ b/system_arch_final/Cross-Feature Constraints.md @@ -0,0 +1,120 @@ +## 1\. Purpose + +This document defines **cross-feature constraints** that apply across multiple system features and components. These constraints ensure consistent behavior, prevent architectural violations, and reduce integration risk. + +Cross-feature constraints are **mandatory rules** that all future software design and implementation must comply with. + +## 2\. Architectural Constraints + +### CFC-ARCH-01: Layered Architecture Enforcement + +* Application logic shall not access hardware directly. + +* All hardware access shall be performed via Drivers and OSAL layers. + +* Persistence access shall only be performed through the DP component. + + +**Impacted Features:** +DAQ, DQC, DATA, DIAG, SYS, OTA, SEC + +### CFC-ARCH-02: State-Aware Feature Execution + +* All features shall be aware of the current system state. + +* Features shall not execute actions that are invalid for the current state. + + +**Examples:** + +* DAQ shall not start sampling during OTA\_UPDATE. + +* Communication shall be limited during TEARDOWN. + + +**Impacted Features:** +SYS, DAQ, COM, OTA, DATA + +## 3\. Concurrency & Timing Constraints + +### CFC-TIME-01: Non-Blocking Operation + +* Sensor acquisition, communication, and UI updates shall be non-blocking. + +* Blocking operations shall be isolated in controlled system services (e.g., persistence task). + + +**Impacted Features:** +DAQ, COM, SYS + +### CFC-TIME-02: Deterministic Task Behavior + +* Time-critical tasks (sensor acquisition, watchdog servicing) shall have deterministic execution time. + +* Dynamic memory allocation during runtime shall be minimized or prohibited in critical paths. + + +**Impacted Features:** +DAQ, SYS, DIAG + +## 4\. Data & Persistence Constraints + +### CFC-DATA-01: Single Source of Truth + +* Runtime and persistent data shall be owned and managed by the DP component. + +* No feature shall maintain private persistent copies of shared system data. + + +**Impacted Features:** +DATA, DAQ, DIAG, SYS, OTA + +### CFC-DATA-02: Data Consistency During Transitions + +* No data write operations shall occur during teardown unless explicitly authorized by the System Manager. + +* Persistence completion shall be confirmed before state transitions. + + +**Impacted Features:** +SYS, DATA, OTA + +## 5\. Security Constraints + +### CFC-SEC-01: Security First Initialization + +* Secure boot and flash protection shall be enabled before any application-level logic executes. + + +**Impacted Features:** +SEC, SYS + +### CFC-SEC-02: Encrypted Channels Only + +* OTA, diagnostics, and data transmission shall only occur over encrypted and authenticated channels. + + +**Impacted Features:** +COM, OTA, DIAG, SEC + +## 6\. HMI & Debug Constraints + +### CFC-HMI-01: Read-Only Local UI + +* The OLED HMI shall not allow configuration changes that affect system safety or security. + +* Configuration updates shall only be accepted via authenticated communication channels. + + +**Impacted Features:** +SYS, SEC + +### CFC-DBG-01: Debug Isolation + +* Debug and engineering sessions shall not interfere with normal system operation. + +* Debug commands shall respect system state restrictions. + + +**Impacted Features:** +SYS, DIAG, SEC \ No newline at end of file diff --git a/system_arch_final/Features.md b/system_arch_final/Features.md new file mode 100644 index 0000000..83878f5 --- /dev/null +++ b/system_arch_final/Features.md @@ -0,0 +1,359 @@ +# **ASF Sensor Hub – Feature Definition Document** + +*(Global, Feature-Based, Architecture-Neutral)* + +This document defines the **system features** of the ASF Sensor Hub subsystem, organized by functional categories. +It is intended to be used as: + +* A **feature baseline** in ALM +* Input to **system requirements derivation** +* Reference for **architecture and software design** +* Traceability anchor to IEC 61508 / IEC 61499 style decomposition later + +> ⚠️ **Important Scope Note** +> This document covers **ONLY the Sensor Hub (Sub-Hub)** based on **ESP32-S3**. +> Main Hub, Cloud, Farm Control Logic are **explicitly out of scope**. + +--- + +## **1. System Context Overview** + +The ASF Sensor Hub is a **distributed sensing node** deployed inside a poultry house. +Its primary responsibilities are: + +* Acquisition of multiple environmental sensors +* Local preprocessing and validation of sensor data +* Persistent storage of data and configuration +* Secure communication with a Main Hub +* Support for diagnostics, maintenance, and OTA updates +* Safe operation under fault conditions + +The Sensor Hub operates as an **autonomous embedded system** with defined lifecycle states. + +--- + +## **2. Feature Categorization Overview** + +The system features are grouped into the following categories: + +1. **Sensor Data Acquisition Features** +2. **Data Quality & Calibration Features** +3. **Communication Features** +4. **Diagnostics & Health Monitoring Features** +5. **Persistence & Data Management Features** +6. **Firmware Update (OTA) Features** +7. **Security & Safety Features** +8. **System Management Features** + +Each feature is described at a **functional level** (WHAT the system does, not HOW). + +--- + +## **3. Sensor Data Acquisition Features** + +### **F-DAQ-01: Multi-Sensor Data Acquisition** + +The system provides the capability to acquire data from multiple environmental sensors connected to the Sensor Hub hardware. + +Supported sensor types include: + +* Temperature +* Humidity +* Carbon Dioxide (CO₂) +* Ammonia (NH₃) +* Volatile Organic Compounds (VOC) +* Particulate Matter (PM) +* Light Intensity + +--- + +### **F-DAQ-02: High-Frequency Sampling and Local Filtering** + +The system provides local preprocessing of sensor data by: + +* Sampling each sensor multiple times per acquisition cycle +* Applying a fast local filtering mechanism +* Producing a single validated value per sensor per cycle + +Filtering algorithms are **pluggable and configurable**. + +--- + +### **F-DAQ-03: Timestamped Sensor Data Generation** + +The system provides timestamped sensor data using a synchronized local time source. + +Each sensor record includes: + +* Sensor identifier +* Measured value +* Timestamp +* Data validity status + +--- + +## **4. Data Quality & Calibration Features** + +### **F-DQC-01: Automatic Sensor Detection** + +The system provides automatic detection of sensor presence based on dedicated hardware detection signals. + +Key characteristics: + +* Each sensor slot is type-specific +* Sensor presence is detected during initialization and runtime +* Only detected sensors are initialized and sampled + +--- + +### **F-DQC-02: Sensor Type Enforcement** + +The system enforces sensor-slot compatibility to prevent incorrect sensor usage. + +Each physical slot: + +* Accepts only one sensor type +* Is mapped to a predefined sensor class in software + +--- + +### **F-DQC-03: Sensor Failure Detection** + +The system provides detection of sensor failures, including: + +* Communication errors +* Out-of-range values +* Non-responsive sensors + +Detected failures are classified and reported. + +--- + +### **F-DQC-04: Machine Constants & Calibration Management** + +The system provides a Machine Constants (MC) mechanism responsible for: + +* Defining installed sensor types +* Holding sensor calibration parameters +* Defining communication parameters +* Defining system identity parameters + +MC data is persistent and reloadable. + +--- + +## **5. Communication Features** + +### **F-COM-01: Main Hub Communication** + +The system provides bidirectional communication with a Main Hub to: + +* Send sensor data +* Send diagnostics information +* Receive configuration updates +* Receive firmware updates + +--- + +### **F-COM-02: On-Demand Data Broadcasting** + +The system provides on-demand transmission of the most recent sensor dataset upon request from the Main Hub. + +--- + +### **F-COM-03: Peer Sensor Hub Communication** + +The system provides limited peer-to-peer communication between Sensor Hubs for: + +* Connectivity checks +* Time synchronization support +* Basic status exchange + +This feature is **on-demand and optional**. + +--- + +## **6. Diagnostics & Health Monitoring Features** + +### **F-DIAG-01: Diagnostic Code Management** + +The system provides structured diagnostics with: + +* Diagnostic codes +* Severity levels +* Root cause hierarchy +* Timestamping + +--- + +### **F-DIAG-02: Diagnostic Data Storage** + +The system provides persistent storage of diagnostic events for post-analysis. + +--- + +### **F-DIAG-03: Diagnostic Session** + +The system provides a diagnostic session allowing engineers to: + +* Retrieve diagnostic data +* Inspect system health +* Clear diagnostic records + +--- + +## **7. Persistence & Data Management Features** + +### **F-DATA-01: Persistent Sensor Data Storage** + +The system provides persistent storage of sensor data in non-volatile memory (SD Card). + +--- + +### **F-DATA-02: Data Persistence Abstraction (DP Component)** + +The system provides a Data Persistence (DP) component responsible for: + +* Abstracting storage media (SD / NVM) +* Managing write/read operations +* Ensuring data integrity + +--- + +### **F-DATA-03: Safe Data Handling During State Transitions** + +The system ensures that all critical data is safely stored before: + +* Firmware update +* Configuration update +* System teardown +* Reset or restart + +--- + +## **8. Firmware Update (OTA) Features** + +### **F-OTA-01: OTA Update Negotiation** + +The system provides an OTA handshake mechanism with the Main Hub to: + +* Acknowledge update availability +* Signal readiness for update + +--- + +### **F-OTA-02: Firmware Reception and Storage** + +The system provides secure reception of firmware images and temporary storage on SD Card. + +--- + +### **F-OTA-03: Firmware Integrity Validation** + +The system validates firmware integrity using checksum or CRC before activation. + +--- + +### **F-OTA-04: Safe Firmware Activation** + +The system provides controlled firmware flashing and rollback-safe activation. + +--- + +## **9. Security & Safety Features** + +### **F-SEC-01: Secure Boot** + +The system provides secure boot functionality to ensure only authenticated firmware is executed. + +--- + +### **F-SEC-02: Secure Flash Storage** + +The system provides encrypted flash storage for sensitive assets. + +--- + +### **F-SEC-03: Encrypted Communication** + +The system provides encrypted communication channels for all external data exchange. + +--- + +## **10. System Management Features** + +### **F-SYS-01: System State Management** + +The system provides explicit lifecycle states including: + +* Initialization +* Normal Operation +* Degraded Operation +* Update Mode +* Fault Mode +* Teardown Mode + +--- + +### **F-SYS-02: Controlled Teardown Mechanism** + +The system provides a controlled teardown mechanism that: + +* Stops sensor acquisition +* Flushes all critical data +* Ensures persistent storage consistency +* Prepares the system for update or shutdown + +--- + +### **F-SYS-03: Status Indication** + +The system provides visual status indicators: + +* Green: Normal operation +* Yellow: Warning state +* Red: Fatal error state + +--- + +### **F-SYS-04: Debug & Engineering Sessions** + +The system provides engineering access sessions allowing: + +* Log inspection +* MC file inspection and update +* Command execution +* Controlled debugging + +--- + +## **11. Feature Relationship Overview (High-Level)** + +``` +Sensor Acquisition + ↓ +Data Quality & Calibration + ↓ +Data Persistence + ↓ +Communication + ↓ +Diagnostics & System Management + ↓ +OTA / Security / Safety +``` + +* **Machine Constants** affect: + + * Sensor initialization + * Calibration + * Communication +* **Diagnostics** span all features +* **Teardown** is a cross-cutting mechanism triggered by: + + * OTA + * MC update + * Fatal faults + +--- + diff --git a/system_arch_final/Migration_and_Updates_Log.md b/system_arch_final/Migration_and_Updates_Log.md new file mode 100644 index 0000000..5eb93af --- /dev/null +++ b/system_arch_final/Migration_and_Updates_Log.md @@ -0,0 +1,224 @@ +# Migration and Updates Log + +**Date:** 2025-01-19 +**Version:** 2.0 +**Purpose:** Document what was moved, what was updated, and what actions are still needed + +## 1. What Was Moved + +All feature documentation files were copied from `System Design/Features/` to `System Design/system_arch_final/`: + +### 1.1 Feature Files (Copied) + +- ✅ `Features.md` – Main feature catalog +- ✅ `[DAQ] Sensor Data Acquisition Features.md` +- ✅ `[DQC] Data Quality & Calibration Features.md` +- ✅ `[COM] Communication Features.md` +- ✅ `[DIAG] Diagnostics & Health Monitoring Features.md` +- ✅ `[DATA] Persistence & Data Management Features.md` +- ✅ `[OTA] Firmware Update (OTA) Features.md` +- ✅ `[SEC] Security & Safety Features.md` +- ✅ `[SYS] System Management Features.md` +- ✅ `Cross-Feature Constraints.md` +- ✅ `System Assumptions & Limitations.md` + +### 1.2 Supporting Documents (Referenced, Not Copied) + +These documents remain in their original locations and are referenced from the system architecture documentation: + +- `System Design/System_State_Machine_Specification.md` +- `System Design/Failure_Handling_Model.md` +- `System Design/SRS/SRS.md` and annexes +- `software design/components/ARCHITECTURE.md` +- `software design/components/application_layer/business_stack/*/COMPONENT_SPEC.md` + +## 2. What Was Updated + +### 2.1 Features.md + +**Updates:** +- Added version 2.0 header with date and platform information +- Added technology stack summary section +- Added new features: + - **F-DAQ-04:** Sensor State Management (updated with state flow) + - **F-DQC-05:** Redundant Sensor Support (NEW) + - **F-COM-04:** Long-Range Fallback Communication (NEW) + - **F-DIAG-04:** Layered Watchdog System (NEW) + - **F-DATA-04:** Power-Loss Data Protection (NEW) + - **F-OTA-05:** A/B Partitioning with Rollback (NEW) + - **F-SEC-04:** Security Violation Handling (NEW) + - **F-SYS-05:** GPIO & Hardware Discipline (NEW) + - **F-PWR-01, F-PWR-02:** Power & Fault Handling Features (NEW) + - **F-HW-01, F-HW-02:** Hardware Abstraction Features (NEW) +- Updated technology specifications for all features +- Added traceability section + +### 2.2 [COM] Communication Features.md + +**Updates:** +- Added version 2.0 header +- Added technology stack section with detailed specifications: + - Wi-Fi 802.11n (2.4 GHz) configuration + - MQTT protocol configuration + - TLS 1.2 / mTLS configuration + - ESP-NOW configuration + - CBOR encoding configuration +- Added F-COM-04: Long-Range Fallback Communication (NEW) +- Added new system requirements (SR-COM-011 through SR-COM-017) +- Added technology specifications section +- Updated traceability mapping + +### 2.3 [SEC] Security & Safety Features.md + +**Updates:** +- Added version 2.0 header +- Added technology stack section: + - Secure Boot V2 specifications + - Flash Encryption (AES-256) specifications + - mTLS and X.509 certificate specifications +- Added F-SEC-04: Security Violation Handling (NEW) +- Added new system requirements (SR-SEC-013 through SR-SEC-015) +- Added implementation notes with technology details +- Added industrial standards compliance section + +### 2.4 [OTA] Firmware Update (OTA) Features.md + +**Updates:** +- Added version 2.0 header +- Added partition layout table (8MB flash) +- Added F-OTA-05: A/B Partitioning with Rollback (NEW) +- Added OTA policy table with detailed rules +- Added new system requirements (SR-OTA-014 through SR-OTA-016) +- Added technology specifications (SHA-256, A/B partitioning) +- Added gap closure section + +### 2.5 New Feature Files Created + +- ✅ `[PWR] Power & Fault Handling Features.md` – NEW +- ✅ `[HW] Hardware Abstraction Features.md` – NEW + +### 2.6 New Documentation Files Created + +- ✅ `System_Architecture_Documentation.md` – Comprehensive system documentation +- ✅ `Migration_and_Updates_Log.md` – This document + +## 3. What Still Needs to Be Specified + +### 3.1 Feature Files Requiring Updates + +The following feature files were copied but may need updates based on gap analysis: + +- ⚠️ `[DAQ] Sensor Data Acquisition Features.md` + - **Action:** Add sensor state management details (F-DAQ-04) + - **Action:** Add filtering algorithm specifications (Median filter N=5, Rate-of-change limiter) + - **Action:** Add timing requirements (maximum 100ms per sensor acquisition cycle) + +- ⚠️ `[DQC] Data Quality & Calibration Features.md` + - **Action:** Add redundant sensor support details (F-DQC-05) + - **Action:** Add sensor fusion algorithm specifications + +- ⚠️ `[DIAG] Diagnostics & Health Monitoring Features.md` + - **Action:** Add layered watchdog system details (F-DIAG-04) + - **Action:** Add diagnostic code format details (0xSCCC) + - **Action:** Add subsystem code allocation table + +- ⚠️ `[DATA] Persistence & Data Management Features.md` + - **Action:** Add power-loss data protection details (F-DATA-04) + - **Action:** Add wear-aware management specifications + - **Action:** Add storage separation details (NVS vs SD Card) + +- ⚠️ `[SYS] System Management Features.md` + - **Action:** Add GPIO & Hardware Discipline details (F-SYS-05) + - **Action:** Add canonical GPIO map reference + - **Action:** Update state list to include all 11 states + +### 3.2 Missing Specifications + +- ⚠️ **GPIO Map Document** + - **Action:** Create canonical GPIO map document + - **Location:** `System Design/system_arch_final/GPIO_Map.md` + - **Content:** Complete GPIO pin assignments, strapping pin warnings, ADC1/ADC2 separation, I2C pull-up requirements + +- ⚠️ **Sensor Abstraction Layer (SAL) Interface Specification** + - **Action:** Create detailed SAL interface specification + - **Location:** `System Design/system_arch_final/SAL_Interface_Specification.md` + - **Content:** Complete API definition, sensor state machine, calibration procedures + +- ⚠️ **Communication Protocol Specification** + - **Action:** Create detailed MQTT topic structure and CBOR schema specification + - **Location:** `System Design/system_arch_final/Communication_Protocol_Specification.md` + - **Content:** Topic hierarchy, message formats, CBOR schemas, versioning strategy + +- ⚠️ **Storage Layout Specification** + - **Action:** Create detailed storage layout specification + - **Location:** `System Design/system_arch_final/Storage_Layout_Specification.md` + - **Content:** SD card file structure, NVS namespace layout, partition table details + +### 3.3 Integration with SRS + +- ⚠️ **SRS Updates** + - **Action:** Review SRS for new features (PWR, HW) and ensure all SWRs are derived + - **Location:** `System Design/SRS/SRS.md` + - **Status:** SRS may need updates for new features + +- ⚠️ **Traceability Updates** + - **Action:** Update traceability matrix for new features + - **Location:** `System Design/SRS/Annex_A_Traceability.md` + - **Status:** New features need traceability links + +### 3.4 Component Design + +- ⚠️ **Component Specifications** + - **Action:** Create component specifications for new components (Power Manager, Hardware Abstraction Layer) + - **Location:** `software design/components/application_layer/.../COMPONENT_SPEC.md` + - **Status:** New components need specifications + +## 4. Recommended Actions + +### 4.1 Immediate Actions (Before Implementation) + +1. **Update Remaining Feature Files** + - Update DAQ, DQC, DIAG, DATA, SYS feature files with new details + - Add technology specifications where missing + +2. **Create Missing Specifications** + - GPIO Map document + - SAL Interface Specification + - Communication Protocol Specification + - Storage Layout Specification + +3. **Update SRS** + - Derive SWRs for new features (PWR, HW) + - Update traceability matrix + +### 4.2 Short-Term Actions (During Component Design) + +1. **Component Specifications** + - Create specifications for Power Manager component + - Create specifications for Hardware Abstraction Layer component + - Update existing component specs if needed + +2. **API Definitions** + - Finalize SAL API + - Finalize DP component API + - Finalize Event System API + +### 4.3 Long-Term Actions (During Implementation) + +1. **Test Specifications** + - Create test cases for new features + - Update V&V matrix + +2. **Documentation** + - Update user documentation + - Create developer guides + +## 5. Document Status + +**Status:** Complete for initial migration +**Next Review:** After feature file updates +**Owner:** System Architecture Team + +--- + +**This log should be updated whenever changes are made to the system architecture documentation.** diff --git a/system_arch_final/System Assumptions & Limitations.md b/system_arch_final/System Assumptions & Limitations.md new file mode 100644 index 0000000..421c992 --- /dev/null +++ b/system_arch_final/System Assumptions & Limitations.md @@ -0,0 +1,83 @@ +## 1\. System Assumptions + +### SA-01: Deployment Environment + +* The Sensor Hub operates in an indoor poultry farm environment. + +* Environmental conditions may include high humidity, dust, and ammonia presence. + + +### SA-02: Power Availability + +* The Sensor Hub is assumed to have continuous power. + +* Short power interruptions may occur; system shall recover gracefully. + + +### SA-03: Network Connectivity + +* Wireless connectivity to the Main Hub may be intermittent. + +* The Sensor Hub shall operate autonomously when disconnected. + + +### SA-04: Trusted Provisioning + +* Devices are assumed to be provisioned securely during manufacturing or installation. + +* Cryptographic keys are assumed to be injected via a secure process. + + +### SA-05: Time Synchronization + +* System time is assumed to be synchronized periodically by the Main Hub. + +* Temporary time drift is acceptable. + + +## 2\. System Limitations + +### SL-01: Local Processing Limits + +* The Sensor Hub performs lightweight preprocessing only. + +* Complex analytics and AI models are out of scope. + + +### SL-02: User Interface Constraints + +* The OLED display is intended for monitoring and diagnostics only. + +* It is not a full configuration or management interface. + + +### SL-03: Physical Security + +* The Sensor Hub does not include physical tamper detection. + +* Physical access is assumed to be restricted. + + +### SL-04: Storage Constraints + +* SD card storage capacity is finite. + +* Data retention policies may result in data overwrite. + + +### SL-05: Safety Classification + +* The system is not classified as a safety-critical life-support system. + +* Failures may impact farm performance but not human safety directly. + + +## 3\. External Dependencies + +* ESP32-S3 hardware platform + +* ESP-IDF framework + +* Supported sensors and communication modules + +* Main Hub availability for OTA and configuration updates \ No newline at end of file diff --git a/system_arch_final/System_Architecture_Documentation.md b/system_arch_final/System_Architecture_Documentation.md new file mode 100644 index 0000000..fc09b5c --- /dev/null +++ b/system_arch_final/System_Architecture_Documentation.md @@ -0,0 +1,302 @@ +# ASF Sensor Hub – System Architecture Documentation + +**Version:** 2.0 +**Date:** 2025-01-19 +**Platform:** ESP32-S3, ESP-IDF v5.4 +**Status:** Final for Implementation Phase + +## 1. Document Purpose + +This document provides comprehensive system architecture documentation for the ASF Sensor Hub (Sub-Hub). It consolidates all architectural decisions, technology choices, feature definitions, and system specifications required for the implementation phase. + +## 2. Document Structure + +This documentation package includes: + +1. **Features.md** – Complete feature catalog with technology specifications +2. **Feature Files** – Detailed feature specifications: + - `[DAQ] Sensor Data Acquisition Features.md` + - `[DQC] Data Quality & Calibration Features.md` + - `[COM] Communication Features.md` + - `[DIAG] Diagnostics & Health Monitoring Features.md` + - `[DATA] Persistence & Data Management Features.md` + - `[OTA] Firmware Update (OTA) Features.md` + - `[SEC] Security & Safety Features.md` + - `[SYS] System Management Features.md` + - `[PWR] Power & Fault Handling Features.md` [NEW] + - `[HW] Hardware Abstraction Features.md` [NEW] +3. **Cross-Feature Constraints.md** – Architectural constraints +4. **System Assumptions & Limitations.md** – System context and boundaries +5. **System State Machine Specification** – Complete FSM definition +6. **Failure Handling Model** – Fault taxonomy and recovery rules + +## 3. System Overview + +### 3.1 Platform + +- **Hardware:** ESP32-S3 microcontroller +- **Framework:** ESP-IDF v5.4 +- **RTOS:** FreeRTOS (included in ESP-IDF) +- **Language:** C/C++ + +### 3.2 Technology Stack + +| Layer | Technology | Justification | +|-------|------------|---------------| +| **Hardware** | ESP32-S3 | Dual-core, 512KB SRAM, 8MB flash, security features | +| **Framework** | ESP-IDF v5.4 | Native support, mature drivers | +| **Physical/Link** | Wi-Fi 802.11n (2.4 GHz) | Native support, good range, sufficient throughput | +| **Peer-to-Peer** | ESP-NOW | Deterministic, low-latency, no AP dependency | +| **Application Protocol** | MQTT over TLS 1.2 | Store-and-forward, keepalive, industrial standard | +| **Payload Encoding** | CBOR | Binary, efficient, versioned | +| **Security** | Secure Boot V2, Flash Encryption, mTLS | Hardware root of trust, IP protection | +| **Storage** | FAT32 (SD Card), NVS (Encrypted) | Wear-aware, reliable | +| **OTA** | A/B Partitioning, SHA-256 | Safe updates, automatic rollback | + +### 3.3 System States + +The system operates as a finite state machine with 11 states: + +1. **INIT** – Hardware and software initialization +2. **BOOT_FAILURE** – Secure boot verification failed +3. **RUNNING** – Normal sensor acquisition and communication +4. **WARNING** – Non-fatal fault detected, degraded operation +5. **FAULT** – Fatal error, core functionality disabled +6. **OTA_PREP** – OTA preparation phase +7. **OTA_UPDATE** – Firmware update in progress +8. **MC_UPDATE** – Machine constants update in progress +9. **TEARDOWN** – Controlled shutdown sequence +10. **SERVICE** – Engineering or diagnostic interaction +11. **SD_DEGRADED** – SD card failure detected, fallback mode + +**Reference:** `System_State_Machine_Specification.md` + +## 4. Feature Groups + +### 4.1 Sensor Data Acquisition (DAQ) + +- **F-DAQ-01:** Multi-Sensor Data Acquisition +- **F-DAQ-02:** High-Frequency Sampling and Local Filtering +- **F-DAQ-03:** Timestamped Sensor Data Generation +- **F-DAQ-04:** Sensor State Management [UPDATED] + +**Technology:** Sensor Abstraction Layer (SAL), Median filter N=5, Rate-of-change limiter + +### 4.2 Data Quality & Calibration (DQC) + +- **F-DQC-01:** Automatic Sensor Detection +- **F-DQC-02:** Sensor Type Enforcement +- **F-DQC-03:** Sensor Failure Detection +- **F-DQC-04:** Machine Constants & Calibration Management +- **F-DQC-05:** Redundant Sensor Support [NEW] + +### 4.3 Communication (COM) + +- **F-COM-01:** Main Hub Communication (MQTT over TLS 1.2) +- **F-COM-02:** On-Demand Data Broadcasting +- **F-COM-03:** Peer Sensor Hub Communication (ESP-NOW) +- **F-COM-04:** Long-Range Fallback Communication [NEW] + +**Technology:** Wi-Fi 802.11n, MQTT, TLS 1.2/mTLS, CBOR encoding, ESP-NOW + +### 4.4 Diagnostics & Health Monitoring (DIAG) + +- **F-DIAG-01:** Diagnostic Code Management +- **F-DIAG-02:** Diagnostic Data Storage +- **F-DIAG-03:** Diagnostic Session +- **F-DIAG-04:** Layered Watchdog System [NEW] + +**Technology:** Diagnostic code format `0xSCCC`, Bounded circular log, Task/Interrupt/RTC watchdogs + +### 4.5 Persistence & Data Management (DATA) + +- **F-DATA-01:** Persistent Sensor Data Storage +- **F-DATA-02:** Data Persistence Abstraction (DP Component) +- **F-DATA-03:** Safe Data Handling During State Transitions +- **F-DATA-04:** Power-Loss Data Protection [NEW] + +**Technology:** FAT32 (SD Card), NVS (Encrypted), Wear-aware batch writing + +### 4.6 Firmware Update (OTA) + +- **F-OTA-01:** OTA Update Negotiation +- **F-OTA-02:** Firmware Reception and Storage +- **F-OTA-03:** Firmware Integrity Validation (SHA-256) +- **F-OTA-04:** Safe Firmware Activation +- **F-OTA-05:** A/B Partitioning with Rollback [NEW] + +**Technology:** A/B partitioning (ota_0/ota_1), SHA-256 hash verification, Automatic rollback + +### 4.7 Security & Safety (SEC) + +- **F-SEC-01:** Secure Boot (Secure Boot V2) +- **F-SEC-02:** Secure Flash Storage (Flash Encryption, AES-256) +- **F-SEC-03:** Encrypted Communication (mTLS, X.509 certificates) +- **F-SEC-04:** Security Violation Handling [NEW] + +**Technology:** Secure Boot V2, Flash Encryption (AES-256), mTLS, X.509 certificates + +### 4.8 System Management (SYS) + +- **F-SYS-01:** System State Management +- **F-SYS-02:** Controlled Teardown Mechanism +- **F-SYS-03:** Status Indication (OLED-Based HMI) +- **F-SYS-04:** Debug & Engineering Sessions +- **F-SYS-05:** GPIO & Hardware Discipline [NEW] + +**Technology:** OLED I2C display, Three-button navigation, State machine enforcement + +### 4.9 Power & Fault Handling (PWR) [NEW] + +- **F-PWR-01:** Brownout Detection and Handling +- **F-PWR-02:** Power-Loss Recovery + +**Technology:** Hardware brownout detector (BOD), Supercapacitor (optional), RTC battery (optional) + +### 4.10 Hardware Abstraction (HW) [NEW] + +- **F-HW-01:** Sensor Abstraction Layer (SAL) +- **F-HW-02:** Hardware Interface Abstraction + +**Technology:** SAL interface, ESP-IDF driver wrappers, GPIO discipline + +## 5. Architectural Principles + +### 5.1 Layered Architecture + +``` +Application Layer + ↓ +Business Stack (STM, Event System, Managers) + ↓ +DP Stack (Data Pool, Persistence) + ↓ +Drivers (Network, Sensors, Storage) + ↓ +ESP-IDF Wrappers (GPIO, I2C, SPI, UART, ADC) + ↓ +ESP-IDF Framework + ↓ +Hardware (ESP32-S3) +``` + +**Constraint:** Application layer SHALL NOT access hardware directly (CFC-ARCH-01) + +### 5.2 State-Aware Execution + +All features must be aware of the current system state and respect state-based operation restrictions. + +**Reference:** `System_State_Machine_Specification.md` + +### 5.3 Event-Driven Communication + +Internal communication uses an event-driven publish/subscribe model. + +**Reference:** `software design/components/application_layer/business_stack/event_system/COMPONENT_SPEC.md` + +### 5.4 Data Persistence Abstraction + +All persistent data access goes through the DP (Data Persistence) component. + +**Reference:** `software design/components/application_layer/DP_stack/persistence/COMPONENT_SPEC.md` + +## 6. Key Specifications + +### 6.1 System State Machine + +**Document:** `System_State_Machine_Specification.md` + +- 11 states with defined transitions +- Per-state feature execution rules +- State transition timing requirements + +### 6.2 Failure Handling Model + +**Document:** `Failure_Handling_Model.md` + +- Fault taxonomy (INFO, WARNING, ERROR, FATAL) +- 7 fault categories with detection rules +- Escalation and recovery behaviors +- Integration with state machine + +### 6.3 Cross-Feature Constraints + +**Document:** `Cross-Feature Constraints.md` + +- Architectural constraints (CFC-ARCH-*) +- Timing constraints (CFC-TIME-*) +- Data constraints (CFC-DATA-*) +- Security constraints (CFC-SEC-*) +- HMI/Debug constraints (CFC-HMI-*, CFC-DBG-*) + +## 7. Implementation Readiness + +### 7.1 Completed Artifacts + +- ✅ Feature definitions with technology specifications +- ✅ System State Machine Specification +- ✅ Failure Handling Model +- ✅ Software Requirements Specification (SRS) +- ✅ Static Architecture Views +- ✅ Component Specifications (STM, Event System, Persistence) +- ✅ Verification & Validation Matrix + +### 7.2 Next Steps + +1. **Component Design Phase:** + - Detailed component APIs + - Threading models + - Error handling strategies + - State machine implementation + +2. **Implementation Phase:** + - Code implementation following SRS + - Unit tests + - Integration tests + - HIL/System tests + +## 8. Traceability + +All features trace to: +- System Requirements (SR-*) +- Software Requirements (SWR-*) +- System State Machine Specification +- Failure Handling Model +- Cross-Feature Constraints +- Component Specifications + +**Reference:** `System Design/SRS/Annex_A_Traceability.md` + +## 9. References + +### 9.1 Internal Documents + +- `Features.md` – Feature catalog +- `[XXX] Feature Files.md` – Detailed feature specifications +- `Cross-Feature Constraints.md` – Architectural constraints +- `System Assumptions & Limitations.md` – System context +- `System_State_Machine_Specification.md` – FSM definition +- `Failure_Handling_Model.md` – Fault taxonomy + +### 9.2 External Documents + +- `System Design/SRS/SRS.md` – Software Requirements Specification +- `System Design/SRS/Annex_A_Traceability.md` – Traceability matrix +- `System Design/SRS/Annex_B_Interfaces.md` – External interfaces +- `System Design/SRS/Annex_C_Budgets.md` – Timing and resource budgets +- `System Design/SRS/VV_Matrix.md` – Verification & Validation matrix +- `software design/components/ARCHITECTURE.md` – Static architecture views +- `software design/components/application_layer/business_stack/STM/COMPONENT_SPEC.md` – State Manager spec +- `software design/components/application_layer/business_stack/event_system/COMPONENT_SPEC.md` – Event System spec +- `software design/components/application_layer/DP_stack/persistence/COMPONENT_SPEC.md` – Persistence spec + +## 10. Document Status + +**Status:** Final for Implementation Phase +**Version:** 2.0 +**Date:** 2025-01-19 +**Next Review:** After Component Design Phase + +--- + +**This document serves as the authoritative system architecture reference for the ASF Sensor Hub implementation phase.** diff --git a/system_arch_final/[COM] Communication Features.md b/system_arch_final/[COM] Communication Features.md new file mode 100644 index 0000000..0616b2c --- /dev/null +++ b/system_arch_final/[COM] Communication Features.md @@ -0,0 +1,349 @@ +# Feature Engineering Specification + +## Communication Features + +**Feature Group ID:** FG-COM +**Version:** 2.0 +**Date:** 2025-01-19 +**Scope:** Sensor Hub (Sub-Hub only) +**Target Platform:** ESP32-S3–based Sensor Hub, ESP-IDF v5.4 +**Applies To:** Indoor poultry farm sensor hubs +**Dependencies:** + +* Sensor Data Acquisition (FG-DAQ) +* Data Quality & Calibration (FG-DQC) +* Diagnostics & Health Monitoring (FG-DIAG) +* Security & Safety Features (FG-SEC) + +## 1. Purpose and Objectives + +The **Communication Features** define how the Sensor Hub exchanges data and control information with external entities. These features ensure that sensor data, diagnostics, configuration updates, and control requests are transferred in a **reliable, secure, and deterministic manner**. + +The communication layer is designed to: + +* Support hierarchical farm architecture (Sensor Hub → Main Hub) +* Enable on-demand and event-driven data transfer +* Allow limited peer-to-peer communication between Sensor Hubs +* Maintain robustness under intermittent connectivity + +**Technology Stack:** +- **Primary Uplink:** Wi-Fi 802.11n (2.4 GHz) +- **Application Protocol:** MQTT over TLS 1.2 +- **Peer-to-Peer:** ESP-NOW +- **Payload Encoding:** CBOR (Binary, versioned) +- **Long-Range Fallback:** LoRa (External Module, optional) + +## 2. Feature Overview and Relationships + +| Feature ID | Feature Name | Primary Objective | Related Features | +|------------|--------------|-------------------|------------------| +| F-COM-01 | Main Hub Communication | Primary uplink/downlink with Main Hub | OTA, Diagnostics, MC Management | +| F-COM-02 | On-Demand Data Broadcasting | Provide latest data upon request | DAQ, DP Stack | +| F-COM-03 | Peer Sensor Hub Communication | Limited hub-to-hub coordination | System Management | +| F-COM-04 | Long-Range Fallback Communication | Farm-scale connectivity resilience | System Management | + +## 3. Functional Feature Descriptions + +### 3.1 F-COM-01: Main Hub Communication + +**Description** +The Sensor Hub shall establish and maintain a bidirectional communication channel with the Main Hub using **MQTT over TLS 1.2**. + +**Protocol Stack:** +``` +Application Layer (MQTT) + ↓ +Transport Security Layer (TLS 1.2 / mTLS) + ↓ +Network Layer (Wi-Fi 802.11n 2.4 GHz) + ↓ +Physical Layer +``` + +**MQTT Configuration:** +- **Broker:** Main Hub / Edge Gateway +- **QoS:** QoS 1 (At least once delivery) +- **Retain:** Used for configuration topics only +- **Payload:** CBOR (Binary, versioned for efficiency and compatibility) +- **Keepalive:** 60 seconds (default) +- **Maximum Message Size:** 8KB + +**Topic Structure:** +``` +/farm/{site_id}/{house_id}/{node_id}/data/{sensor_id} +/farm/{site_id}/{house_id}/{node_id}/status/heartbeat +/farm/{site_id}/{house_id}/{node_id}/status/system +/farm/{site_id}/{house_id}/{node_id}/cmd/{command_type} +/farm/{site_id}/{house_id}/{node_id}/diag/{severity} +/farm/{site_id}/{house_id}/{node_id}/ota/{action} +``` + +**Heartbeat Mechanism:** +- **Interval:** 10 seconds +- **Timeout:** 3 missed heartbeats (30 seconds) triggers "offline" status +- **Payload includes:** + - Uptime (seconds) + - Firmware version (string) + - Free heap memory (bytes) + - RSSI (signal strength, dBm) + - Error bitmap (32-bit) + - System state + +**Key Capabilities** + +* Bidirectional communication +* Command and response handling +* Diagnostics and status reporting +* Integration with OTA and MC updates +* Store-and-forward messaging (handles intermittent connectivity) +* Automatic reconnection with exponential backoff + +**Wi-Fi Configuration:** +- **Standard:** 802.11n (2.4 GHz) +- **Minimum RSSI:** -85 dBm (connection threshold) +- **Channel Selection:** Automatic (avoid interference) +- **Power Management:** Active mode (no PSM for real-time requirements) + +### 3.2 F-COM-02: On-Demand Data Broadcasting + +**Description** +The Sensor Hub shall support on-demand transmission of the most recent sensor data upon request from the Main Hub. This allows the Main Hub to query real-time conditions without waiting for periodic reporting cycles. + +**Response Time:** Maximum 100ms from request to response transmission. + +Data broadcasts include timestamped sensor values and associated validity status. + +**Key Capabilities** + +* Request/response data exchange +* Latest-value data delivery +* Timestamp and validity inclusion +* Low-latency response (≤100ms) + +### 3.3 F-COM-03: Peer Sensor Hub Communication + +**Description** +Sensor Hubs shall be capable of limited peer-to-peer communication using **ESP-NOW** for coordination purposes such as connectivity checks, time synchronization assistance, or basic status exchange. + +**ESP-NOW Configuration:** +- **Protocol:** ESP-NOW (deterministic, low-latency) +- **Range:** ~200m line-of-sight, ~50m through walls +- **Maximum Peers:** 20 +- **Security:** Application-layer encryption (AES-128 minimum) required +- **Acknowledgment:** Application-layer acknowledgment and retry mechanism + +**Message Types:** +- `PEER_PING`: Connectivity check +- `PEER_PONG`: Connectivity response +- `PEER_TIME_SYNC`: Time synchronization request +- `PEER_TIME_RESP`: Time synchronization response + +**Key Capabilities** + +* Hub-to-hub message exchange +* Minimal command set +* No dependency on centralized infrastructure +* Isolation from control logic +* Encrypted communication (application-layer) + +**Constraints:** +- Peer communication SHALL NOT interfere with Main Hub communication +- Peer communication SHALL be limited to coordination functions only +- Maximum peer count: 20 (ESP-NOW limitation) + +### 3.4 F-COM-04: Long-Range Fallback Communication [NEW] + +**Description** +The system supports optional long-range fallback communication using **LoRa (External Module)** for farm-scale distances where Wi-Fi may not reach. + +**Note:** This feature is **optional** and requires cost-benefit analysis. Alternative: Cellular (LTE-M/NB-IoT) if farm has cellular coverage. + +**LoRa Configuration (if implemented):** +- **Module:** External LoRa module (e.g., SX1276, SX1262) +- **Protocol:** LoRaWAN or raw LoRa +- **Use Cases:** Emergency alerts, data backup (not for OTA updates) +- **Data Rate:** Low (may not support OTA updates) + +**Alternative Consideration:** +- **Cellular (LTE-M/NB-IoT):** Higher data rate, better for OTA updates, more expensive but more reliable in some regions + +## 4. System Requirements (Formal SHALL Statements) + +### 4.1 Main Hub Communication + +**SR-COM-001** +The system shall support bidirectional communication between the Sensor Hub and the Main Hub using MQTT over TLS 1.2. + +**SR-COM-002** +The system shall transmit sensor data, diagnostics, and system status information to the Main Hub via MQTT. + +**SR-COM-003** +The system shall receive commands, configuration updates, and firmware update requests from the Main Hub via MQTT. + +**SR-COM-004** +The system shall monitor and report the communication link status with the Main Hub. + +**SR-COM-011** [NEW] +The system shall implement a heartbeat mechanism with 10-second interval and 30-second timeout. + +**SR-COM-012** [NEW] +The system shall use CBOR encoding for all MQTT payloads. + +**SR-COM-013** [NEW] +The system shall support automatic reconnection with exponential backoff on connection loss. + +### 4.2 On-Demand Data Broadcasting + +**SR-COM-005** +The system shall support on-demand requests from the Main Hub for sensor data. + +**SR-COM-006** +The system shall respond to on-demand data requests with the most recent timestamped sensor data within 100ms. + +**SR-COM-007** +The system shall include data validity and sensor status information in on-demand responses. + +### 4.3 Peer Sensor Hub Communication + +**SR-COM-008** +The system shall support limited peer-to-peer communication between Sensor Hubs using ESP-NOW. + +**SR-COM-009** +The system shall allow peer communication for basic coordination functions such as connectivity checks or time synchronization. + +**SR-COM-010** +The system shall ensure that peer Sensor Hub communication does not interfere with Main Hub communication or control operations. + +**SR-COM-014** [NEW] +The system shall encrypt all ESP-NOW peer communication using application-layer encryption (AES-128 minimum). + +**SR-COM-015** [NEW] +The system shall implement acknowledgment and retry mechanism for ESP-NOW peer communication. + +### 4.4 Long-Range Fallback Communication [NEW] + +**SR-COM-016** [NEW] +The system may support long-range fallback communication using LoRa or cellular (LTE-M/NB-IoT) for farm-scale distances. + +**SR-COM-017** [NEW] +If implemented, long-range fallback communication shall be used only for emergency alerts and data backup, not for OTA updates. + +## 5. Technology Specifications + +### 5.1 Wi-Fi 802.11n (2.4 GHz) + +**Rationale:** +- Native ESP32-S3 support +- Existing farm infrastructure compatibility +- Mature ESP-IDF drivers +- High data rate for OTA firmware updates (150 Mbps theoretical, ~20-30 Mbps practical) +- Good range and penetration for farm structures + +**Configuration:** +- **Standard:** 802.11n +- **Frequency:** 2.4 GHz +- **Minimum RSSI:** -85 dBm +- **Channel Selection:** Automatic +- **Power Management:** Active mode + +### 5.2 MQTT Protocol + +**Rationale:** +- Store-and-forward messaging (handles intermittent connectivity gracefully) +- Built-in keepalive mechanism (monitors connection health automatically) +- QoS levels for delivery guarantees +- Massive industrial adoption (SCADA, IIoT) +- Native ESP-IDF support (esp_mqtt component) + +**Configuration:** +- **QoS Level:** 1 (At least once delivery) +- **Retain Flag:** Used for configuration topics only +- **Keepalive:** 60 seconds +- **Maximum Message Size:** 8KB +- **Broker Compatibility:** Mosquitto 2.x, HiveMQ, or compatible + +### 5.3 TLS 1.2 / mTLS + +**Rationale:** +- Strong security (mutual authentication) +- Industry standard +- ESP-IDF native support (mbedTLS) +- Prevents man-in-the-middle attacks + +**Configuration:** +- **TLS Version:** 1.2 (minimum) +- **Authentication:** Mutual TLS (mTLS) +- **Certificate:** Device-unique X.509 certificate +- **Private Key:** Stored in eFuse or encrypted flash +- **Maximum Certificate Size:** <2KB (ESP32-S3 optimization) + +### 5.4 ESP-NOW + +**Rationale:** +- Deterministic, low-latency communication +- No AP dependency +- Native ESP32-S3 support +- Low power consumption + +**Configuration:** +- **Maximum Peers:** 20 +- **Security:** Application-layer encryption (AES-128 minimum) +- **Acknowledgment:** Application-layer implementation required + +### 5.5 CBOR Encoding + +**Rationale:** +- Binary format (efficient, ~30-50% smaller than JSON) +- Versioned payloads (backward compatibility) +- Standardized (RFC 8949) +- Good library support (TinyCBOR, QCBOR) + +**Configuration:** +- **Schema Versioning:** Required +- **Maximum Payload Size:** 8KB per message type +- **Schema Validation:** On Main Hub side + +## 6. Traceability Mapping + +### 6.1 Feature → System Requirement Mapping + +```mermaid +graph TD + F-COM-01 -->|Main Hub Communication| SR-COM-001 + F-COM-01 -->|Transmit Data| SR-COM-002 + F-COM-01 -->|Receive Commands| SR-COM-003 + F-COM-01 -->|Monitor Link Status| SR-COM-004 + F-COM-01 -->|Heartbeat| SR-COM-011 + F-COM-01 -->|CBOR Encoding| SR-COM-012 + F-COM-01 -->|Auto Reconnect| SR-COM-013 + + F-COM-02 -->|On-Demand Requests| SR-COM-005 + F-COM-02 -->|Respond with Data| SR-COM-006 + F-COM-02 -->|Include Validity Info| SR-COM-007 + + F-COM-03 -->|Peer Communication| SR-COM-008 + F-COM-03 -->|Peer Coordination| SR-COM-009 + F-COM-03 -->|Isolate Peer Traffic| SR-COM-010 + F-COM-03 -->|ESP-NOW Encryption| SR-COM-014 + F-COM-03 -->|ESP-NOW Acknowledgment| SR-COM-015 + + F-COM-04 -->|Long-Range Fallback| SR-COM-016 + F-COM-04 -->|Fallback Use Cases| SR-COM-017 +``` + +## 7. Engineering Notes and Constraints + +* **MQTT Broker Compatibility:** Specify broker version (e.g., Mosquitto 2.x, HiveMQ) +* **Message Size Limits:** Maximum 8KB per message +* **Topic Naming:** Follow hierarchical structure `/farm/{site}/{house}/{node}/...` +* **Security:** All communication encrypted via TLS 1.2 / mTLS (defined under Security Features) +* **ESP-NOW Security:** Application-layer encryption required (AES-128 minimum) +* **Communication failures** shall trigger diagnostics events but shall not block sensor acquisition +* **LoRa Fallback:** Optional feature requiring cost-benefit analysis + +## 8. Dependencies + +* **Security Features:** TLS/mTLS implementation +* **System Management:** State-aware communication restrictions +* **Diagnostics:** Communication failure reporting +* **Data Acquisition:** Sensor data for transmission diff --git a/system_arch_final/[DAQ] Sensor Data Acquisition Features.md b/system_arch_final/[DAQ] Sensor Data Acquisition Features.md new file mode 100644 index 0000000..59d155b --- /dev/null +++ b/system_arch_final/[DAQ] Sensor Data Acquisition Features.md @@ -0,0 +1,320 @@ +# **ASF Sensor Hub** + +## **Feature Engineering Specification** + +## **Sensor Data Acquisition Features** + +## **1\. Feature Overview** + +### **Feature Name** + +Sensor Data Acquisition Features + +### **Feature ID** + +FEAT-DAQ + +### **Subsystem** + +ASF Sensor Hub (Sub-Hub) + +### **Target Platform** + +ESP32-S3–based embedded system + +### **Scope** + +This feature defines the capabilities of the Sensor Hub related to: + +* Environmental sensor data acquisition + +* Local preprocessing and filtering + +* Timestamping and preparation of sensor data for persistence and communication + + +This feature **does NOT include**: + +* Main Hub processing + +* Cloud analytics + +* Control logic + +* OTA, diagnostics, or persistence mechanisms (referenced only as dependencies) + + +## **2\. Purpose and Engineering Rationale** + +Modern poultry farm automation systems require **high-resolution, reliable, and time-correlated environmental data** to enable: + +* Accurate environmental control + +* Early fault detection + +* Advanced analytics and machine learning + + +The Sensor Data Acquisition feature ensures: + +* Deterministic sensor sampling + +* Noise-resilient measurements + +* Temporal traceability of data + +* Decoupling of acquisition from communication and control + + +This aligns with **distributed intelligence principles** used in leading international poultry automation systems. + +## **3\. Feature Decomposition** + +The Sensor Data Acquisition feature is decomposed into the following sub-features: + +

Sub-Feature ID

Name

F-DAQ-01

Multi-Sensor Data Acquisition

F-DAQ-02

High-Frequency Sampling and Local Filtering

F-DAQ-03

Timestamped Sensor Data Generation

+ +## **4\. Functional Description** + +### **4.1 F-DAQ-01: Multi-Sensor Data Acquisition** + +#### **Description** + +The Sensor Hub acquires environmental data from multiple heterogeneous sensors connected to dedicated hardware interfaces. + +#### **Supported Sensor Types** + +* Temperature + +* Relative Humidity + +* Carbon Dioxide (CO₂) + +* Ammonia (NH₃) + +* Volatile Organic Compounds (VOC) + +* Particulate Matter (PM) + +* Light Intensity + + +Each sensor: + +* Is mapped to a predefined hardware slot + +* Has a dedicated driver abstraction + +* Can be independently enabled or disabled + + +#### **Key Characteristics** + +* Concurrent sensor handling + +* Modular sensor driver architecture + +* Runtime awareness of sensor presence + + +### **4.2 F-DAQ-02: High-Frequency Sampling and Local Filtering** + +#### **Description** + +For each enabled sensor, the system performs multiple raw readings per acquisition cycle and applies a local filtering mechanism to produce a single representative value. + +#### **Sampling Behavior** + +* Each sensor is sampled **N times per cycle** (default: 10) + +* Sampling occurs within a bounded time window + +* Sampling frequency is configurable via Machine Constants + + +#### **Filtering Behavior** + +* Filtering is executed locally on the Sensor Hub + +* Filtering algorithms are abstracted and replaceable + +* Examples (non-exhaustive): + + * Moving average + + * Median filter + + * Outlier rejection + + +#### **Objective** + +* Reduce sensor noise + +* Improve data stability + +* Avoid propagating raw sensor jitter upstream + + +### **4.3 F-DAQ-03: Timestamped Sensor Data Generation** + +#### **Description** + +Each processed sensor value is associated with a timestamp generated by the Sensor Hub. + +#### **Timestamp Characteristics** + +* Generated after filtering completion + +* Represents the effective measurement time + +* Based on system time (RTC or synchronized clock) + + +#### **Sensor Data Record** + +Each record includes: + +* Sensor ID + +* Sensor type + +* Filtered value + +* Unit of measurement + +* Timestamp + +* Data validity status + + +## **5\. Operational Flow** + +### **Normal Acquisition Cycle** + +1. Detect enabled sensors + +2. Initialize sensor drivers (if not already active) + +3. Perform high-frequency sampling per sensor + +4. Apply local filtering + +5. Generate timestamp + +6. Create sensor data record + +7. Forward data to: + + * Data Persistence component + + * Communication component (on request) + + +## **6\. Constraints and Assumptions** + +### **Constraints** + +* Sensor acquisition must not block system-critical tasks + +* Sampling and filtering must complete within a bounded cycle time + +* Memory usage must be deterministic + + +### **Assumptions** + +* Sensor presence detection is handled by a separate feature + +* Time synchronization is provided by another system component + +* Storage and communication are decoupled from acquisition + + +## **7\. Architecture Diagram (PlantUML)** + +### **7.1 Sensor Hub Component Diagram** + +```mermaid +graph TD + subgraph "Sensor Hub" + SD["Sensor Drivers"] --> SE["Sampling Engine"] + SE --> FE["Filtering Engine"] + FE --> TS["Timestamp Service"] + TS --> DB["Sensor Data Buffer"] + end + SD -->|"raw samples"| SE + SE -->|"sampled data"| FE + FE -->|"filtered value"| TS + TS -->|"timestamped record"| DB +``` + +### **7.2 Acquisition Cycle Sequence Diagram** + +```mermaid +sequenceDiagram + participant S as Sensor Driver + participant SE as Sampling Engine + participant FE as Filtering Engine + participant TS as Timestamp Service + S ->> SE: read() + loop N samples + SE ->> S: sample() + end + SE ->> FE: raw sample set + FE ->> TS: filtered value + TS ->> FE: timestamp +``` + +## **8\. Formal System SHALL Requirements** + +### **8.1 Requirement Style** + +* Each requirement uses **“The system shall …”** + +* Each requirement has a unique ID + +* Requirements are atomic and testable + + +### **8.2 Requirements List** + +#### **Multi-Sensor Acquisition** + +* **REQ-DAQ-001** + The system shall support acquisition of data from multiple environmental sensor types simultaneously. + +* **REQ-DAQ-002** + The system shall provide a dedicated software driver abstraction for each supported sensor type. + +* **REQ-DAQ-003** + The system shall acquire sensor data only from sensors detected as present and enabled. + + +#### **High-Frequency Sampling & Filtering** + +* **REQ-DAQ-004** + The system shall sample each enabled sensor multiple times within a single acquisition cycle. + +* **REQ-DAQ-005** + The system shall apply a local filtering mechanism to raw sensor samples to produce a single representative value. + +* **REQ-DAQ-006** + The system shall allow configuration of sampling count and filtering parameters via system configuration data. + + +#### **Timestamped Data Generation** + +* **REQ-DAQ-007** + The system shall associate each processed sensor value with a timestamp. + +* **REQ-DAQ-008** + The system shall generate timestamps after completion of filtering. + +* **REQ-DAQ-009** + The system shall include sensor identifier, sensor type, value, unit, timestamp, and validity status in each sensor data record. + + +## **9\. Feature-to-Requirement Traceability** + +

Feature ID

Requirement IDs

F-DAQ-01

REQ-DAQ-001, REQ-DAQ-002, REQ-DAQ-003

F-DAQ-02

REQ-DAQ-004, REQ-DAQ-005, REQ-DAQ-006

F-DAQ-03

REQ-DAQ-007, REQ-DAQ-008, REQ-DAQ-009

\ No newline at end of file diff --git a/system_arch_final/[DATA] Persistence & Data Management Features.md b/system_arch_final/[DATA] Persistence & Data Management Features.md new file mode 100644 index 0000000..a748f80 --- /dev/null +++ b/system_arch_final/[DATA] Persistence & Data Management Features.md @@ -0,0 +1,173 @@ + + + +# Feature Engineering Specification + +## Persistence & Data Management Features + +**Feature Group ID:** FG-DATA +**Scope:** Sensor Hub (Sub-Hub only) +**Target Platform:** ESP32-S3–based Sensor Hub +**Applies To:** Indoor poultry farm sensor hubs +**Dependencies:** + +* Sensor Data Acquisition (FG-DAQ) + +* Data Quality & Calibration (FG-DQC) + +* Diagnostics & Health Monitoring (FG-DIAG) + +* System State Management / Teardown Mechanism + + +## 1\. Purpose and Objectives + +The **Persistence & Data Management Features** define how the Sensor Hub stores, protects, and manages critical runtime and historical data. These features ensure that: + +* Sensor data and system state are not lost during resets or failures + +* Data storage is abstracted from application logic + +* Critical data is safely handled during firmware updates, configuration changes, or fatal faults + + +The persistence layer is a **foundational system service**, supporting diagnostics, calibration, OTA, and recovery operations. + +## 2\. Feature Overview and Relationships + +

Feature ID

Feature Name

Primary Objective

Related Features

F-DATA-01

Persistent Sensor Data Storage

Store timestamped sensor data

DAQ, COM

F-DATA-02

Data Persistence Abstraction (DP)

Abstract storage access

Application Layer

F-DATA-03

Safe Data Handling During State Transitions

Protect data during teardown

OTA, System Mgmt

+ +## 3\. Functional Feature Descriptions + +### 3.1 F-DATA-01: Persistent Sensor Data Storage + +**Description** +The system shall persist timestamped sensor data to non-volatile storage to support historical analysis, diagnostics correlation, and recovery scenarios. + +Persistence may include: + +* Filtered sensor values + +* Timestamps + +* Sensor validity and status metadata + + +The persistence policy (frequency, retention window, overwrite behavior) is configurable and optimized for storage longevity and performance. + +**Key Capabilities** + +* Non-volatile storage (SD card / NVM) + +* Timestamped records + +* Configurable retention policy + +* Integration with DAQ and COM + + +### 3.2 F-DATA-02: Data Persistence Abstraction (DP Component) + +**Description** +The system shall provide a **Data Persistence (DP) component** that abstracts storage access for all upper layers. Application and feature modules interact with the DP component rather than directly accessing storage hardware. + +The DP component manages: + +* Data model definitions + +* Serialization and deserialization + +* Storage backend selection + +* Consistency and integrity guarantees + + +**Key Capabilities** + +* Unified persistence API + +* Storage backend abstraction + +* Centralized data ownership + +* Reduced coupling between layers + + +### 3.3 F-DATA-03: Safe Data Handling During State Transitions + +**Description** +The system shall ensure safe and deterministic handling of data during critical state transitions, including: + +* Firmware updates (OTA) + +* Machine Constants updates + +* System resets + +* Fatal error handling + + +Before entering such transitions, the system executes a controlled data finalization process to flush buffers, persist critical state, and verify data integrity. + +**Key Capabilities** + +* Controlled data flush + +* Atomic write operations + +* Data integrity checks + +* Coordination with teardown mechanism + + +## 4\. System Requirements (Formal SHALL Statements) + +### 4.1 Persistent Sensor Data Storage + +**SR-DATA-001** +The system shall persist timestamped sensor data in non-volatile storage. + +**SR-DATA-002** +The system shall store sensor data together with sensor identifiers, timestamps, and validity status. + +**SR-DATA-003** +The system shall support configurable data retention and overwrite policies. + +### 4.2 Data Persistence Abstraction (DP Component) + +**SR-DATA-004** +The system shall provide a Data Persistence (DP) component as the sole interface for persistent data access. + +**SR-DATA-005** +The system shall prevent application and feature modules from directly accessing storage hardware. + +**SR-DATA-006** +The DP component shall support serialization and deserialization of structured system data. + +### 4.3 Safe Data Handling During State Transitions + +**SR-DATA-007** +The system shall ensure that all critical runtime data is flushed to non-volatile storage before entering a controlled teardown or reset. + +**SR-DATA-008** +The system shall protect data integrity during firmware updates and configuration changes. + +**SR-DATA-009** +The system shall verify successful data persistence before completing a state transition. + +## 5\. Feature ↔ System Requirement Mapping + +

Feature ID

System Requirements

F-DATA-01

SR-DATA-001, SR-DATA-002, SR-DATA-003

F-DATA-02

SR-DATA-004, SR-DATA-005, SR-DATA-006

F-DATA-03

SR-DATA-007, SR-DATA-008, SR-DATA-009

+ +## 6\. Engineering Notes + +* The DP component aligns with your **DP Stack** already defined in the architecture. + +* Atomic write strategies (e.g., temp file + rename) are recommended. + +* Diagnostic events should be generated on persistence failures. + +* Storage wear-leveling considerations apply for SD/NVM. + + +## \ No newline at end of file diff --git a/system_arch_final/[DIAG] Diagnostics & Health Monitoring Features.md b/system_arch_final/[DIAG] Diagnostics & Health Monitoring Features.md new file mode 100644 index 0000000..0107792 --- /dev/null +++ b/system_arch_final/[DIAG] Diagnostics & Health Monitoring Features.md @@ -0,0 +1,167 @@ + + + +# Feature Engineering Specification + +## Diagnostics & Health Monitoring Features + +**Feature Group ID:** FG-DIAG +**Scope:** Sensor Hub (Sub-Hub only) +**Target Platform:** ESP32-S3–based Sensor Hub +**Applies To:** Indoor poultry farm sensor hubs +**Dependencies:** + +* Sensor Data Acquisition (FG-DAQ) + +* Data Quality & Calibration (FG-DQC) + +* Communication Features (FG-COM) + +* Persistence / DP Stack + + +## 1\. Purpose and Objectives + +The **Diagnostics & Health Monitoring Features** provide a structured and persistent mechanism to detect, classify, record, and expose system faults, warnings, and health states. + +These features ensure that: + +* Failures are detectable and explainable + +* Root causes are traceable + +* Diagnostic data survives resets and power loss + +* Engineers can access diagnostic information locally or remotely + + +The diagnostics subsystem is **non-intrusive**, meaning it shall not block core sensing or communication functions unless the system enters a fatal state. + +## 2\. Feature Overview and Relationships + +

Feature ID

Feature Name

Primary Objective

Related Features

F-DIAG-01

Diagnostic Code Management

Standardize fault and warning identification

DQC, COM

F-DIAG-02

Diagnostic Data Storage

Persist diagnostic events

DP Stack

F-DIAG-03

Diagnostic Session

Engineer access to diagnostics

COM, System Mgmt

+ +## 3\. Functional Feature Descriptions + +### 3.1 F-DIAG-01: Diagnostic Code Management + +**Description** +The system shall implement a structured diagnostic code framework to represent system health conditions, warnings, errors, and fatal faults. + +Each diagnostic event is associated with: + +* A unique diagnostic code + +* Severity level (info, warning, error, fatal) + +* A hierarchical root-cause classification + +* Timestamp and source component + + +This framework enables consistent fault handling across all system components. + +**Key Capabilities** + +* Unique diagnostic code registry + +* Severity classification + +* Root-cause hierarchy + +* Event-based reporting + + +### 3.2 F-DIAG-02: Diagnostic Data Storage + +**Description** +The system shall persist diagnostic events in non-volatile storage to allow post-failure analysis and long-term health monitoring. + +Stored diagnostics remain available across system resets and power cycles until explicitly cleared by an authorized diagnostic session or command. + +**Key Capabilities** + +* Persistent storage of diagnostic events + +* Timestamped records + +* Bounded storage with overwrite policy + +* Integration with DP / Persistence layer + + +### 3.3 F-DIAG-03: Diagnostic Session + +**Description** +The system shall provide a diagnostic session that allows authorized engineers or tools to access diagnostic data, inspect system health, and perform maintenance operations. + +The diagnostic session may be accessed locally or remotely via the communication interface and supports read and limited control operations. + +**Key Capabilities** + +* Session-based access + +* Read diagnostics and health data + +* Clear diagnostic records + +* Controlled command execution + + +## 4\. System Requirements (Formal SHALL Statements) + +### 4.1 Diagnostic Code Management + +**SR-DIAG-001** +The system shall implement a diagnostic code framework for reporting system health, warnings, errors, and fatal faults. + +**SR-DIAG-002** +The system shall assign a unique diagnostic code to each detected fault or abnormal condition. + +**SR-DIAG-003** +The system shall classify diagnostic codes by severity level. + +**SR-DIAG-004** +The system shall associate each diagnostic event with a timestamp and source component. + +### 4.2 Diagnostic Data Storage + +**SR-DIAG-005** +The system shall persist diagnostic events in non-volatile storage. + +**SR-DIAG-006** +The system shall retain diagnostic data across system resets and power cycles. + +**SR-DIAG-007** +The system shall implement a bounded diagnostic storage mechanism with a defined overwrite or rollover policy. + +### 4.3 Diagnostic Session + +**SR-DIAG-008** +The system shall provide a diagnostic session interface for accessing diagnostic data. + +**SR-DIAG-009** +The system shall allow authorized diagnostic sessions to retrieve stored diagnostic events. + +**SR-DIAG-010** +The system shall allow authorized diagnostic sessions to clear diagnostic records. + +**SR-DIAG-011** +The system shall ensure that diagnostic sessions do not interfere with normal sensor acquisition or communication operations. + +## 5\. Feature ↔ System Requirement Mapping + +

Feature ID

System Requirements

F-DIAG-01

SR-DIAG-001, SR-DIAG-002, SR-DIAG-003, SR-DIAG-004

F-DIAG-02

SR-DIAG-005, SR-DIAG-006, SR-DIAG-007

F-DIAG-03

SR-DIAG-008, SR-DIAG-009, SR-DIAG-010, SR-DIAG-011

+ +## 6\. Engineering Notes + +* Diagnostic codes should be versioned to support firmware evolution. + +* Diagnostic severity may be linked to LED indicators (green/yellow/red). + +* Fatal diagnostics may trigger the teardown mechanism defined elsewhere. + +* Security and access control for diagnostic sessions are handled under **Security & Safety Features**. + + +## \ No newline at end of file diff --git a/system_arch_final/[DQC] Data Quality & Calibration Features.md b/system_arch_final/[DQC] Data Quality & Calibration Features.md new file mode 100644 index 0000000..3d429a0 --- /dev/null +++ b/system_arch_final/[DQC] Data Quality & Calibration Features.md @@ -0,0 +1,180 @@ + + + +# Feature Engineering Specification + +## Data Quality & Calibration Features + +**Feature Group ID:** FG-DQC +**Scope:** Sensor Hub (Sub-Hub only) +**Target Platform:** ESP32-S3–based Sensor Hub +**Applies To:** Indoor poultry farm sensor hubs +**Dependencies:** Sensor Data Acquisition Features (FG-DAQ), Diagnostics Features (FG-DIAG), Persistence / DP Stack + +## 1\. Purpose and Objectives + +The **Data Quality & Calibration Features** ensure that all sensor data generated by the Sensor Hub is **valid, trustworthy, correctly classified, and calibrated** throughout the system lifecycle. These features provide mechanisms for: + +* Automatic identification of connected sensors + +* Enforcing correct sensor–slot compatibility + +* Early detection and isolation of faulty sensors + +* Centralized management of machine constants and calibration parameters + + +The goal is to maintain **high data integrity**, reduce commissioning errors, support **remote reconfiguration**, and ensure safe operation during updates or failures. + +
+ + + + +## 2\. Feature Overview and Relationships + +

Feature ID

Feature Name

Primary Objective

Related Features

F-DQC-01

Automatic Sensor Detection

Detect connected sensors dynamically

F-DAQ-01, F-DIAG-01

F-DQC-02

Sensor Type Enforcement

Prevent incorrect sensor-slot usage

F-DQC-01

F-DQC-03

Sensor Failure Detection

Identify and isolate faulty sensors

F-DIAG-02

F-DQC-04

Machine Constants & Calibration Management

Manage static configuration and calibration

OTA, Persistence, Teardown

+ +## 3\. Functional Feature Descriptions + +### 3.1 F-DQC-01: Automatic Sensor Detection + +**Description** +The Sensor Hub shall automatically detect which sensors are physically connected at runtime. Each sensor slot provides a dedicated detection mechanism (e.g., GPIO presence pin or ID signal) that allows the system to determine whether a sensor is installed. + +Detected sensors are dynamically initialized and incorporated into the data acquisition workflow without requiring firmware changes. + +**Key Capabilities** + +* Hardware-based presence detection + +* Runtime sensor enumeration + +* Dynamic initialization during boot or reconfiguration + +* Integration with diagnostics and data acquisition + + +### 3.2 F-DQC-02: Sensor Type Enforcement + +**Description** +Each physical sensor slot on the Sensor Hub is dedicated to a specific sensor type. The system enforces sensor-slot compatibility to prevent incorrect sensor insertion (e.g., humidity sensor in temperature slot). + +This enforcement is achieved via electrical identification, pin mapping, or firmware configuration defined in Machine Constants. + +**Key Capabilities** + +* Fixed sensor-to-slot mapping + +* Sensor identity verification + +* Rejection of invalid sensor configurations + +* Diagnostic reporting of configuration violations + + +### 3.3 F-DQC-03: Sensor Failure Detection + +**Description** +The Sensor Hub continuously monitors sensor behavior to detect failures such as disconnection, out-of-range values, non-responsive sensors, or abnormal signal patterns. + +Detected sensor failures are classified, logged, timestamped, and reported to the Main Hub. Failed sensors are excluded from control and analytics workflows to prevent propagation of invalid data. + +**Key Capabilities** + +* Runtime health monitoring + +* Failure classification + +* Fault isolation + +* Diagnostic event generation + + +### 3.4 F-DQC-04: Machine Constants & Calibration Management + +**Description** +The system maintains a **Machine Constants (MC)** dataset that defines static and semi-static configuration parameters for the Sensor Hub, including: + +* Installed sensor types and slots + +* Communication identifiers and addressing + +* Calibration coefficients and offsets + +* Sensor-specific limits and scaling + + +Machine Constants are persisted in non-volatile storage (SD card) and loaded during system initialization. Updates may be received from the Main Hub and applied via a controlled teardown and reinitialization process. + +**Key Capabilities** + +* Persistent configuration storage + +* Runtime loading and validation + +* Remote update support + +* Controlled reinitialization sequence + + +## 4\. System Requirements (Formal SHALL Statements) + +### 4.1 Automatic Sensor Detection + +**SR-DQC-001** +The system shall detect the presence of each sensor using a dedicated hardware detection mechanism. + +**SR-DQC-002** +The system shall perform sensor presence detection during system startup and after any reinitialization event. + +**SR-DQC-003** +The system shall initialize only those sensors that are detected as present. + +### 4.2 Sensor Type Enforcement + +**SR-DQC-004** +The system shall assign each sensor slot to a predefined sensor type. + +**SR-DQC-005** +The system shall verify that the detected sensor matches the expected sensor type for the slot. + +**SR-DQC-006** +The system shall reject and report any sensor-slot mismatch as a diagnostic event. + +### 4.3 Sensor Failure Detection + +**SR-DQC-007** +The system shall continuously monitor sensor responsiveness and signal validity during operation. + +**SR-DQC-008** +The system shall detect sensor failures including disconnection, non-responsiveness, and invalid measurement ranges. + +**SR-DQC-009** +The system shall mark a failed sensor as defective and exclude it from data reporting. + +**SR-DQC-010** +The system shall report detected sensor failures to the Main Hub with timestamps and failure classification. + +### 4.4 Machine Constants & Calibration Management + +**SR-DQC-011** +The system shall maintain a Machine Constants dataset defining sensor configuration, calibration parameters, and communication identifiers. + +**SR-DQC-012** +The system shall persist the Machine Constants dataset in non-volatile storage. + +**SR-DQC-013** +The system shall load and apply Machine Constants during system initialization. + +**SR-DQC-014** +The system shall support remote updates of the Machine Constants dataset initiated by the Main Hub. + +**SR-DQC-015** +The system shall apply updated Machine Constants only after executing a controlled teardown and reinitialization sequence. + +## 5\. Traceability Summary + +

Feature ID

System Requirements

F-DQC-01

SR-DQC-001 → SR-DQC-003

F-DQC-02

SR-DQC-004 → SR-DQC-006

F-DQC-03

SR-DQC-007 → SR-DQC-010

F-DQC-04

SR-DQC-011 → SR-DQC-015

+ +## \ No newline at end of file diff --git a/system_arch_final/[HW] Hardware Abstraction Features.md b/system_arch_final/[HW] Hardware Abstraction Features.md new file mode 100644 index 0000000..bafbf19 --- /dev/null +++ b/system_arch_final/[HW] Hardware Abstraction Features.md @@ -0,0 +1,150 @@ +# Hardware Abstraction Features + +**Feature Group ID:** FG-HW +**Version:** 1.0 +**Date:** 2025-01-19 +**Scope:** Sensor Hub (Sub-Hub only) +**Target Platform:** ESP32-S3–based Sensor Hub, ESP-IDF v5.4 + +## 1 Feature Overview + +The **Hardware Abstraction Features** provide a clean separation between application logic and hardware interfaces. These features ensure hardware independence, maintainability, and testability of the system. + +**Architecture Principle:** Application layer SHALL NOT access hardware directly (CFC-ARCH-01). + +## 2 Scope and Assumptions + +**In Scope** + +* Sensor Abstraction Layer (SAL) +* Hardware interface abstraction (I2C, SPI, UART, ADC, GPIO) +* Storage interface abstraction (SD Card, NVM) +* Display interface abstraction (OLED I2C) + +**Out of Scope** + +* Hardware driver implementation details (ESP-IDF drivers) +* Hardware-specific optimizations (deferred to implementation) + +## 3 Sub-Feature Breakdown + +### 3.1 F-HW-01: Sensor Abstraction Layer (SAL) + +#### Description + +The system provides a Sensor Abstraction Layer (SAL) to ensure hardware independence and maintainability. + +**Interface Functions:** +- `sensor_read()`: Retrieve the latest value +- `sensor_calibrate()`: Perform sensor-specific calibration +- `sensor_validate()`: Check if the reading is within physical bounds +- `sensor_health_check()`: Verify the operational status of the hardware +- `sensor_getMetadata()`: Get sensor capabilities (range, accuracy, etc.) +- `sensor_reset()`: Recovery from fault states + +**Sensor State Management:** +- **INIT:** Sensor initialization +- **WARMUP:** Sensor warming up (not yet stable) +- **STABLE:** Sensor operational and stable +- **DEGRADED:** Sensor operational but degraded +- **FAILED:** Sensor failed, not operational + +#### Responsibilities + +* Abstract sensor hardware interfaces +* Provide uniform sensor API +* Manage sensor state +* Handle sensor-specific calibration +* Validate sensor readings + +#### Constraints + +* All sensor access must go through SAL +* Application layer must not access sensor hardware directly +* Sensor state must be tracked and reported + +### 3.2 F-HW-02: Hardware Interface Abstraction + +#### Description + +The system abstracts all hardware interfaces through driver layers. + +**Abstraction Layers:** +- **I2C Interface:** Abstracted via ESP-IDF I2C driver wrapper +- **SPI Interface:** Abstracted via ESP-IDF SPI driver wrapper +- **UART Interface:** Abstracted via ESP-IDF UART driver wrapper +- **ADC Interface:** Abstracted via ESP-IDF ADC driver wrapper +- **GPIO Interface:** Abstracted via ESP-IDF GPIO driver wrapper +- **Storage Interfaces:** SD Card (SDMMC), NVM (NVS) +- **Display Interface:** OLED I2C + +**GPIO Discipline:** +- **No Strapping Pins:** Avoid using strapping pins (GPIO 0, 3, 45, 46) for general-purpose I/O +- **I2C Pull-up Audit:** Ensure all shared I2C buses have appropriate physical pull-up resistors (2.2kΩ - 4.7kΩ for 3.3V) +- **No ADC2 with Wi-Fi:** ADC2 unit cannot be used when Wi-Fi is active. All analog sensors must be connected to ADC1 pins +- **Canonical GPIO Map:** Single authoritative GPIO map document must be maintained + +#### Responsibilities + +* Abstract hardware interfaces +* Provide uniform API for hardware access +* Enforce GPIO discipline +* Manage hardware resource conflicts + +#### Constraints + +* Application layer must not access hardware directly +* GPIO usage must follow canonical GPIO map +* Hardware conflicts must be detected and reported + +## 4 System Requirements (Formal SHALL Statements) + +### Sensor Abstraction Layer Requirements + +* **SR-HW-001**: The system shall provide a Sensor Abstraction Layer (SAL) for all sensor access. +* **SR-HW-002**: The system shall prevent application layer from directly accessing sensor hardware. +* **SR-HW-003**: The system shall track sensor state (INIT, WARMUP, STABLE, DEGRADED, FAILED). +* **SR-HW-004**: The system shall provide sensor validation and health check functions. + +### Hardware Interface Abstraction Requirements + +* **SR-HW-005**: The system shall abstract all hardware interfaces (I2C, SPI, UART, ADC, GPIO) through driver layers. +* **SR-HW-006**: The system shall enforce GPIO discipline (no strapping pins, proper pull-ups, ADC1/ADC2 separation). +* **SR-HW-007**: The system shall maintain a canonical GPIO map document. +* **SR-HW-008**: The system shall detect and report hardware resource conflicts. + +## 5 Traceability Matrix (Feature → System Requirements) + +| Feature ID | Related System Requirements | +|------------|----------------------------| +| F-HW-01 | SR-HW-001, SR-HW-002, SR-HW-003, SR-HW-004 | +| F-HW-02 | SR-HW-005, SR-HW-006, SR-HW-007, SR-HW-008 | + +## 6 Design & Implementation Notes (Non-Normative) + +* **SAL Implementation:** Each sensor type implements SAL interface +* **Driver Wrappers:** ESP-IDF drivers wrapped in application-specific abstraction layer +* **GPIO Map:** Must be maintained as single source of truth +* **Hardware Conflicts:** Runtime detection and reporting via diagnostics + +## 7 Dependencies + +* **ESP-IDF Drivers:** I2C, SPI, UART, ADC, GPIO, SDMMC, NVS +* **System Management Features:** Hardware initialization and teardown +* **Diagnostics Features:** Hardware fault reporting + +## 8 GPIO Map Guidelines + +**Strapping Pins (DO NOT USE):** +- GPIO 0: Boot mode selection +- GPIO 3: JTAG +- GPIO 45: Strapping pin +- GPIO 46: Strapping pin + +**ADC Constraints:** +- **ADC1:** Available when Wi-Fi is active +- **ADC2:** NOT available when Wi-Fi is active (use ADC1 for all analog sensors) + +**I2C Pull-up Requirements:** +- **Physical Pull-ups:** 2.2kΩ - 4.7kΩ for 3.3V +- **Software Pull-ups:** Not recommended for production (use physical pull-ups) diff --git a/system_arch_final/[OTA] Firmware Update (OTA) Features.md b/system_arch_final/[OTA] Firmware Update (OTA) Features.md new file mode 100644 index 0000000..26f2daf --- /dev/null +++ b/system_arch_final/[OTA] Firmware Update (OTA) Features.md @@ -0,0 +1,236 @@ +# Firmware Update (OTA) Features + +**Feature Group ID:** FG-OTA +**Version:** 2.0 +**Date:** 2025-01-19 +**Scope:** Sensor Hub (Sub-Hub only) +**Target Platform:** ESP32-S3–based Sensor Hub, ESP-IDF v5.4 + +## 1 Feature Overview + +The **Firmware Update (OTA) Features** enable the Sensor Hub (Sub-Hub) to safely receive, validate, and activate new firmware images provided by the Main Hub. +These features ensure **controlled firmware lifecycle management**, **data integrity**, **system availability**, and **fault containment** during firmware update operations. + +The OTA process is designed to: + +* Prevent unauthorized or corrupted firmware installation +* Preserve critical system data and calibration information +* Ensure recoverability in case of update failure +* Minimize operational disruption + +**Technology:** A/B Partitioning with automatic rollback, SHA-256 integrity verification + +This feature set applies **only to the Sensor Hub (ESP32-S3 based)** and does not include cloud-side or Main Hub OTA logic. + +## 2 Scope and Assumptions + +### In Scope + +* OTA negotiation and readiness handshake with Main Hub +* Firmware image reception over secure communication (MQTT or HTTPS) +* Temporary firmware storage on SD card +* Firmware integrity verification (SHA-256 hash) +* Controlled firmware activation and reboot +* A/B partitioning with automatic rollback + +### Out of Scope + +* Firmware generation and signing +* Cloud-side firmware distribution +* Rollback policy definition (defined in this document) + +## 3 Partition Layout + +For a device with **8MB of flash**, the following partition layout is recommended: + +| Partition | Size | Purpose | +|-----------|------|---------| +| **bootloader** | ~32KB | Initial boot code | +| **partition_table** | ~4KB | Defines the flash layout | +| **factory** | Optional | Minimal rescue firmware | +| **ota_0** | 3.5 MB | Primary application slot | +| **ota_1** | 3.5 MB | Secondary application slot for updates | +| **nvs** | 64 KB | Encrypted Non-Volatile Storage for config | +| **phy_init** | ~4KB | Physical layer initialization data | +| **coredump** | 64 KB | Storage for crash logs and debugging | + +**Total Used:** ~7.1MB (fits in 8MB flash) + +## 4 Sub-Features + +### 4.1 F-OTA-01: OTA Update Negotiation + +**Description** +This sub-feature governs the initial negotiation phase between the Sensor Hub and the Main Hub prior to any firmware transfer. +The Sensor Hub validates its current operational state and explicitly signals readiness before accepting an OTA update. + +**Readiness Validation:** +- System state check (must be RUNNING, not WARNING/FAULT/SERVICE/SD_DEGRADED) +- Storage availability check (SD card space, NVS space) +- Power stability check +- Communication link stability check + +**Responsibilities** + +* Receive OTA availability notification +* Validate system readiness (power, storage, state) +* Acknowledge or reject OTA request +* Transition system into OTA_PREP state + +### 4.2 F-OTA-02: Firmware Reception and Storage + +**Description** +This sub-feature handles the controlled reception of the firmware image from the Main Hub and its storage in non-volatile memory (SD card) without overwriting the currently running firmware. + +**Download Method:** +- **Protocol:** HTTPS or MQTT +- **Chunk Size:** 4096 bytes (optimized for flash page size) +- **Storage:** SD Card (temporary) before flashing to OTA partition + +**Responsibilities** + +* Receive firmware in chunks (4096 bytes per chunk) +* Store firmware image on SD card (temporary) +* Monitor transfer completeness +* Prevent execution during download +* Track download progress + +### 4.3 F-OTA-03: Firmware Integrity Validation + +**Description** +This sub-feature validates the integrity and correctness of the received firmware image prior to activation, ensuring that corrupted or incomplete firmware is never flashed. + +**Validation Method:** +- **Integrity Check:** SHA-256 hash verification +- **Size Validation:** Firmware size matches metadata +- **Metadata Validation:** Partition table, version number + +**Responsibilities** + +* Perform integrity checks (SHA-256 hash) +* Validate firmware size and metadata +* Reject invalid firmware images +* Report validation status to Main Hub + +### 4.4 F-OTA-04: Safe Firmware Activation + +**Description** +This sub-feature manages the safe transition from the current firmware to the new firmware, ensuring all critical data is preserved and the system is left in a known safe state. + +**Activation Sequence:** +1. Execute controlled teardown +2. Persist critical runtime data and calibration data +3. Flash validated firmware image to inactive OTA partition +4. Update partition table to boot from new partition +5. Reboot system into new firmware +6. Validate: System must boot and send health report +7. Confirmation: Application must confirm stability within 60-120 seconds +8. Failure: Automatic rollback to previous known-good version + +**Responsibilities** + +* Trigger teardown procedure +* Persist runtime and calibration data +* Flash validated firmware image +* Reboot system into updated firmware + +### 4.5 F-OTA-05: A/B Partitioning with Rollback [NEW] + +**Description** +The system implements A/B partitioning to support safe firmware updates with automatic rollback capability. + +**Rollback Triggers:** +- Boot failure after firmware activation +- No health report within confirmation window (60-120 seconds) +- Application crash during confirmation period +- Manual rollback command from Main Hub + +**Rollback Process:** +1. Detect failure condition +2. Mark new firmware as invalid +3. Update partition table to boot from previous partition +4. Reboot into previous known-good firmware +5. Report rollback to Main Hub + +## 5 OTA Policy + +A formal policy ensures that updates are downloaded correctly and that the system can roll back if the new firmware is unstable. + +| Step | Rule | +|------|------| +| **Download** | Conducted via HTTPS or MQTT in chunks | +| **Chunk Size** | 4096 bytes (optimized for flash page size) | +| **Integrity** | Verified using a full image SHA-256 hash | +| **Validation** | System must boot and send a health report | +| **Confirmation** | The application must confirm stability within 60-120 seconds | +| **Failure** | Automatic rollback to the previous known-good version | + +**OTA Duration:** Maximum 10 minutes (end-to-end) + +## 6 System Requirements (Formal SHALL Statements) + +### OTA Negotiation Requirements + +* **SR-OTA-001**: The system shall support OTA update negotiation initiated by the Main Hub. +* **SR-OTA-002**: The system shall verify internal readiness before accepting an OTA update request. +* **SR-OTA-003**: The system shall explicitly acknowledge or reject OTA requests. + +### Firmware Reception & Storage Requirements + +* **SR-OTA-004**: The system shall receive firmware images over the established communication channel (HTTPS or MQTT). +* **SR-OTA-005**: The system shall store received firmware images in non-volatile storage (SD card) prior to validation. +* **SR-OTA-006**: The system shall prevent overwriting the active firmware during firmware reception. + +### Firmware Integrity Requirements + +* **SR-OTA-007**: The system shall validate the integrity of the received firmware image before activation using SHA-256 hash. +* **SR-OTA-008**: The system shall reject firmware images that fail integrity validation. +* **SR-OTA-009**: The system shall report firmware validation results to the Main Hub. + +### Safe Activation Requirements + +* **SR-OTA-010**: The system shall execute a controlled teardown before firmware activation. +* **SR-OTA-011**: The system shall persist critical runtime data and calibration data prior to firmware flashing. +* **SR-OTA-012**: The system shall activate new firmware only after successful integrity validation. +* **SR-OTA-013**: The system shall reboot into the new firmware after successful activation. + +### Rollback Requirements [NEW] + +* **SR-OTA-014**: The system shall implement A/B partitioning for safe firmware updates. +* **SR-OTA-015**: The system shall automatically rollback to previous firmware if new firmware fails validation or health check. +* **SR-OTA-016**: The system shall report rollback events to the Main Hub. + +## 7 Feature-to-Requirement Traceability + +| Feature ID | Related System Requirements | +|------------|----------------------------| +| F-OTA-01 | SR-OTA-001, SR-OTA-002, SR-OTA-003 | +| F-OTA-02 | SR-OTA-004, SR-OTA-005, SR-OTA-006 | +| F-OTA-03 | SR-OTA-007, SR-OTA-008, SR-OTA-009 | +| F-OTA-04 | SR-OTA-010, SR-OTA-011, SR-OTA-012, SR-OTA-013 | +| F-OTA-05 | SR-OTA-014, SR-OTA-015, SR-OTA-016 | + +## 8 Architectural Considerations (Informative) + +* OTA logic shall be implemented as a **dedicated OTA Manager component** +* Firmware storage shall be accessed via the **DP (Data Persistence) component** +* OTA state transitions shall interact with: + * Diagnostics subsystem + * Machine Constants management + * Teardown mechanism +* OTA execution shall not block critical system diagnostics reporting +* OTA operations SHALL NOT be allowed during WARNING, FAULT, SERVICE, or SD_DEGRADED states + +## 9 Related Features + +* **Persistence & Data Management Features (F-DATA-03)** +* **Diagnostics & Health Monitoring Features** +* **Security & Safety Features (Secure Boot, Secure Flash)** +* **System Management Features (State Machine, Teardown)** + +## 10 Closing the Gaps + +This strategy directly addresses the following gaps: +* **GAP-OTA-001:** Reliable image delivery (chunked download, MQTT/HTTPS) +* **GAP-OTA-002:** Integrity and authenticity verification (SHA-256, Secure Boot) +* **GAP-OTA-003:** Safe rollback mechanisms (A/B partitioning, automatic rollback) diff --git a/system_arch_final/[PWR] Power & Fault Handling Features.md b/system_arch_final/[PWR] Power & Fault Handling Features.md new file mode 100644 index 0000000..45c069d --- /dev/null +++ b/system_arch_final/[PWR] Power & Fault Handling Features.md @@ -0,0 +1,138 @@ +# Power & Fault Handling Features + +**Feature Group ID:** FG-PWR +**Version:** 1.0 +**Date:** 2025-01-19 +**Scope:** Sensor Hub (Sub-Hub only) +**Target Platform:** ESP32-S3–based Sensor Hub, ESP-IDF v5.4 + +## 1 Feature Overview + +The **Power & Fault Handling Features** ensure that the Sensor Hub operates reliably under power fluctuations and recovers gracefully from power interruptions. These features protect critical data during brownouts and enable clean recovery after power restoration. + +**Technology:** +- **Brownout Detection:** Hardware brownout detector (BOD) +- **Power-Loss Protection:** Supercapacitor (optional, recommended) +- **RTC Backup:** External RTC battery (CR2032, optional) + +## 2 Scope and Assumptions + +**In Scope** + +* Brownout detection and handling +* Power-loss data protection +* Graceful shutdown on power loss +* Clean recovery after power restoration + +**Out of Scope** + +* Battery-powered operation (system assumes continuous power) +* Power management for low-power modes (not applicable for real-time requirements) + +## 3 Sub-Feature Breakdown + +### 3.1 F-PWR-01: Brownout Detection and Handling + +#### Description + +The system monitors input voltage and takes immediate action if it drops below safe threshold. + +**Configuration:** +- **Brownout Threshold:** 3.0V (hardware-configurable) +- **Detection:** Hardware brownout detector (BOD) in ESP32-S3 +- **ISR Action:** Set "Power Loss" flag and immediately flush critical buffers to NVS/SD +- **Recovery:** Perform clean reboot once power is stable + +**Hardware Support:** +- **Supercapacitor (Recommended):** 0.5-1.0F for 1-2s at 3.3V + - Provides runtime during brownout to complete data flush + - Enables graceful shutdown +- **External RTC Battery (Optional):** CR2032, 3V, 220mAh + - Maintains time accuracy during power loss + - Not required for basic operation + +#### Responsibilities + +* Monitor input voltage +* Detect brownout condition +* Trigger immediate data flush +* Enter graceful shutdown mode + +#### Constraints + +* Brownout detection must be hardware-based (ESP32-S3 BOD) +* Data flush must complete within supercapacitor runtime (1-2 seconds) +* System must reboot cleanly after power restoration + +### 3.2 F-PWR-02: Power-Loss Recovery + +#### Description + +The system recovers gracefully from power interruptions (< 1 second). + +**Recovery Behavior:** +- Clean reboot after power stabilization +- Data integrity verification +- State restoration from persistent storage +- Diagnostic event generation (if data loss detected) + +**Recovery Sequence:** +1. Power restoration detected +2. Wait for power stabilization (100ms) +3. Perform clean reboot +4. Initialize system from persistent storage +5. Verify data integrity +6. Report recovery status via diagnostics + +#### Responsibilities + +* Detect power restoration +* Perform clean reboot +* Restore system state from persistent storage +* Verify data integrity +* Report recovery status + +## 4 System Requirements (Formal SHALL Statements) + +### Brownout Detection Requirements + +* **SR-PWR-001**: The system shall monitor input voltage and detect brownout conditions below 3.0V. +* **SR-PWR-002**: The system shall immediately flush critical data buffers to non-volatile storage upon brownout detection. +* **SR-PWR-003**: The system shall enter graceful shutdown mode during brownout conditions. +* **SR-PWR-004**: The system shall perform clean reboot after power stabilization. + +### Power-Loss Recovery Requirements + +* **SR-PWR-005**: The system shall recover gracefully from power interruptions. +* **SR-PWR-006**: The system shall verify data integrity after power restoration. +* **SR-PWR-007**: The system shall restore system state from persistent storage after power restoration. +* **SR-PWR-008**: The system shall report power-loss and recovery events via diagnostics. + +## 5 Traceability Matrix (Feature → System Requirements) + +| Feature ID | Related System Requirements | +|------------|----------------------------| +| F-PWR-01 | SR-PWR-001, SR-PWR-002, SR-PWR-003, SR-PWR-004 | +| F-PWR-02 | SR-PWR-005, SR-PWR-006, SR-PWR-007, SR-PWR-008 | + +## 6 Design & Implementation Notes (Non-Normative) + +* **Supercapacitor:** Recommended for production deployment to enable graceful shutdown +* **RTC Battery:** Optional, improves time accuracy during power loss +* **Brownout Threshold:** 3.0V is conservative; adjust based on power supply characteristics +* **Data Flush Priority:** Critical data (calibration, diagnostics) must be flushed first +* **Recovery Time:** System should recover within 5 seconds after power restoration + +## 7 Dependencies + +* **Persistence & Data Management Features** (data flush mechanism) +* **Diagnostics Features** (power-loss event reporting) +* **System Management Features** (graceful shutdown, state restoration) + +## 8 Hardware Recommendations + +| Component | Specification | Purpose | +|-----------|---------------|---------| +| **Supercapacitor** | 0.5-1.0F, 3.3V | Provides runtime during brownout for data flush | +| **RTC Battery** | CR2032, 3V, 220mAh | Maintains time accuracy during power loss | +| **Power Supply** | 3.3V ±5%, minimum 500mA | Stable power for reliable operation | diff --git a/system_arch_final/[SEC] Security & Safety Features.md b/system_arch_final/[SEC] Security & Safety Features.md new file mode 100644 index 0000000..d329004 --- /dev/null +++ b/system_arch_final/[SEC] Security & Safety Features.md @@ -0,0 +1,281 @@ +# Security & Safety Features + +**Feature Group ID:** FG-SEC +**Version:** 2.0 +**Date:** 2025-01-19 +**Scope:** Sensor Hub (Sub-Hub only) +**Target Platform:** ESP32-S3–based Sensor Hub, ESP-IDF v5.4 + +## 1 Feature Overview + +The **Security & Safety Features** ensure that the Sensor Hub operates only with trusted firmware, protects sensitive data at rest, and guarantees confidentiality and integrity of all communications. These features are foundational and cross-cutting, supporting all other functional features (DAQ, DQC, COM, DIAG, DATA, OTA). + +This feature set is designed to: + +* Prevent execution of unauthorized or malicious firmware +* Protect firmware, configuration, and machine constants stored in memory +* Secure all communications with cryptographic mechanisms +* Provide deterministic and auditable behavior in case of security violations + +**Technology Stack:** +- **Secure Boot:** Secure Boot V2 (hardware-enforced) +- **Flash Encryption:** AES-256 (hardware-accelerated) +- **Communication Security:** Mutual TLS (mTLS) with X.509 certificates +- **Anti-Rollback:** eFuse-based version protection + +## 2 Scope and Assumptions + +**In Scope** + +* Sensor Hub (ESP32-S3–based) +* Boot process security +* Flash and external storage protection +* Communication security with Main Hub and peer Sensor Hubs +* Device identity and authentication + +**Out of Scope** + +* Cloud server security policies +* User identity management +* Physical tamper detection hardware (optional future feature) + +## 3 Sub-Feature Breakdown + +### 3.1 F-SEC-01: Secure Boot + +#### Description + +Secure Boot ensures that only authenticated and authorized firmware images are executed on the Sensor Hub using **Secure Boot V2**. During system startup, the bootloader verifies the cryptographic signature of the firmware image before handing over execution. + +If verification fails, the system enters **BOOT_FAILURE** state and prevents normal operation. + +#### Implementation + +**Secure Boot V2 Configuration:** +- **Signature Algorithm:** RSA-3072 or ECDSA-P256 +- **Verification:** Hardware-enforced (ROM bootloader) +- **Key Storage:** Root-of-trust key in eFuse (one-time programmable) +- **Enforcement:** Every boot (cold or warm) + +#### Responsibilities + +* Firmware authenticity verification +* Root-of-trust enforcement +* Prevention of downgrade or rollback attacks (via eFuse anti-rollback) + +#### Constraints + +* Must complete before any application code execution +* Must be enforced on every boot (cold or warm) +* Root-of-trust key is one-time programmable (eFuse) + +### 3.2 F-SEC-02: Secure Flash Storage + +#### Description + +Secure Flash Storage protects sensitive data stored in internal flash and external storage (e.g., SD card) from unauthorized access or modification using **Flash Encryption**. + +**Encryption Method:** AES-256 (hardware-accelerated) + +Sensitive data includes: + +* Firmware images +* Machine constants +* Calibration data +* Cryptographic material +* Persistent diagnostics and logs + +#### Implementation + +**Flash Encryption Configuration:** +- **Algorithm:** AES-256 +- **Mode:** Release mode (recommended for production) +- **Key Derivation:** Hardware-based (eFuse) +- **Transparency:** Automatic decryption on read (transparent to application) + +**External Storage Encryption:** +- **SD Card:** Optional encryption for sensitive files (SWR-SEC-006) +- **Encryption Method:** AES-256 (software-based for SD card) + +#### Responsibilities + +* Encrypted storage of sensitive regions +* Access control enforcement +* Prevention of unauthorized read/write operations + +#### Constraints + +* Encryption must not compromise system boot reliability +* Storage access must be mediated through controlled software components (e.g., DP component) + +### 3.3 F-SEC-03: Encrypted Communication + +#### Description + +Encrypted Communication ensures that all data exchanged between the Sensor Hub and other entities (Main Hub, peer Sensor Hubs) is protected against eavesdropping, tampering, and impersonation using **Mutual TLS (mTLS)**. + +This includes: + +* Sensor data transmission +* Diagnostics reporting +* OTA negotiation and data transfer +* Configuration and machine constant updates + +#### Implementation + +**Device Identity & Authentication:** +- **Identity:** Device-unique X.509 certificate +- **Private Key:** Stored securely in eFuse or encrypted flash +- **Authentication:** Mutual TLS (mTLS) for all broker communications +- **Provisioning:** Handled via secure factory or onboarding mode + +**Key Lifecycle Management:** + +| Phase | Mechanism | +|-------|-----------| +| **Manufacturing** | Injection of unique device certificate and private key | +| **Operation** | Use of TLS session keys for encrypted communication | +| **Rotation** | Certificate rotation managed on broker/server side | +| **Revocation** | Certificate Revocation Lists (CRL) or broker-side denylists | + +**Key Insight:** +The ESP32-S3 is optimized to handle a single device certificate efficiently. It is recommended to avoid managing large certificate chains on the device itself to conserve resources. + +**Certificate Constraints:** +- **Maximum Certificate Size:** <2KB +- **Certificate Format:** X.509 v3 +- **Key Algorithm:** RSA-2048 or ECDSA-P256 + +#### Responsibilities + +* Confidentiality of transmitted data +* Integrity and authenticity verification +* Secure session establishment + +#### Constraints + +* Must be compatible with ESP32-S3 cryptographic capabilities +* Must support reconnection and key renewal mechanisms +* Certificate size must be optimized for ESP32-S3 + +### 3.4 F-SEC-04: Security Violation Handling [NEW] + +#### Description + +The system detects and reports security violations with appropriate responses. + +**Security Violation Types:** +- Secure boot failures +- Authentication failures +- Message tampering +- Unauthorized access attempts +- Certificate validation failures + +**Response Actions:** +- Secure boot failure → BOOT_FAILURE state +- Authentication failure → FATAL diagnostic event, connection rejection +- Message tampering → ERROR diagnostic event (escalates to FATAL if persistent) +- Unauthorized access → FATAL diagnostic event, access denial + +## 4 Functional Flow Overview + +### Secure Boot Flow + +```mermaid +sequenceDiagram + participant Power as Power On + participant ROM as ROM Bootloader + participant SecureBoot as Secure Boot V2 + participant App as Application + + Power->>ROM: System Reset + ROM->>SecureBoot: Load Firmware + SecureBoot->>SecureBoot: Verify Signature + alt Signature Valid + SecureBoot->>App: Jump to Application + else Signature Invalid + SecureBoot->>SecureBoot: Enter BOOT_FAILURE State + end +``` + +### Secure Communication Flow (mTLS) + +```mermaid +sequenceDiagram + participant SH as Sensor Hub + participant Broker as Main Hub Broker + + SH->>Broker: TLS Client Hello + Certificate + Broker->>SH: TLS Server Hello + Certificate + SH->>SH: Verify Server Certificate + Broker->>Broker: Verify Client Certificate + alt Both Valid + SH->>Broker: TLS Session Established + SH->>Broker: Encrypted Data Exchange + else Invalid Certificate + SH->>SH: Reject Connection, Log FATAL + end +``` + +## 5 System SHALL Requirements (Formal) + +### Secure Boot Requirements + +* **SR-SEC-001**: The system shall verify the authenticity of the firmware image before execution during every boot cycle using Secure Boot V2. +* **SR-SEC-002**: The system shall prevent execution of firmware images that fail cryptographic verification. +* **SR-SEC-003**: The system shall enter BOOT_FAILURE state upon secure boot verification failure. +* **SR-SEC-004**: The system shall protect the root-of-trust against modification (eFuse protection). + +### Secure Flash Storage Requirements + +* **SR-SEC-005**: The system shall protect sensitive data stored in internal flash memory from unauthorized access using Flash Encryption (AES-256). +* **SR-SEC-006**: The system shall support encryption of sensitive data stored in external storage devices (SD card). +* **SR-SEC-007**: The system shall restrict access to cryptographic keys to authorized system components only. +* **SR-SEC-008**: The system shall ensure data integrity for stored configuration and machine constant files. + +### Encrypted Communication Requirements + +* **SR-SEC-009**: The system shall encrypt all communication with the Main Hub using TLS 1.2 with mutual authentication (mTLS). +* **SR-SEC-010**: The system shall ensure integrity and authenticity of all received and transmitted messages. +* **SR-SEC-011**: The system shall use secure communication channels for OTA firmware updates. +* **SR-SEC-012**: The system shall detect and report communication security violations. + +### Security Violation Handling Requirements [NEW] + +* **SR-SEC-013**: The system shall report security violations as FATAL diagnostic events. +* **SR-SEC-014**: The system shall implement eFuse-based anti-rollback to prevent downgrade attacks. +* **SR-SEC-015**: The system shall protect cryptographic keys during power loss and system resets. + +## 6 Traceability Matrix (Feature → System Requirements) + +| Feature ID | Related System Requirements | +|------------|----------------------------| +| F-SEC-01 | SR-SEC-001, SR-SEC-002, SR-SEC-003, SR-SEC-004 | +| F-SEC-02 | SR-SEC-005, SR-SEC-006, SR-SEC-007, SR-SEC-008 | +| F-SEC-03 | SR-SEC-009, SR-SEC-010, SR-SEC-011, SR-SEC-012 | +| F-SEC-04 | SR-SEC-013, SR-SEC-014, SR-SEC-015 | + +## 7 Design & Implementation Notes (Non-Normative) + +* **Secure Boot V2:** Mandatory for production deployment. Key management and signing infrastructure must be documented. +* **Flash Encryption:** Release mode recommended for production. Development mode available for debugging. +* **Key Provisioning:** Should occur during manufacturing or secure onboarding. HSM or secure signing server required. +* **Certificate Lifecycle:** Certificate rotation and revocation must be managed on broker/server side. +* **eFuse Anti-Rollback:** Version numbering strategy must be carefully defined (eFuse is one-time programmable). +* **Security Failures:** Should integrate with the Diagnostics & Health Monitoring feature set. +* **Security Features:** Must be active before any sensor data acquisition or communication begins (CFC-SEC-01). + +## 8 Dependencies + +* **OTA Features** (for secure firmware updates) +* **Communication Features** (transport layer for mTLS) +* **Diagnostics Features** (security fault reporting) +* **Persistence & DP Component** (secure storage abstraction) +* **System Management** (BOOT_FAILURE state handling) + +## 9 Industrial Standards Compliance + +* **Secure Boot V2:** Industry standard for production-ready industrial embedded systems +* **Flash Encryption:** Hardware-accelerated AES-256 (industry standard) +* **mTLS:** Industry standard for device authentication +* **X.509 Certificates:** Standard certificate format (RFC 5280) diff --git a/system_arch_final/[SYS] System Management Features.md b/system_arch_final/[SYS] System Management Features.md new file mode 100644 index 0000000..5dfe099 --- /dev/null +++ b/system_arch_final/[SYS] System Management Features.md @@ -0,0 +1,314 @@ + + + +# +System Management Features + +## Sensor Hub (Sub-Hub) Scope + +## 1 Feature Overview + +The **System Management Features** provide deterministic control over the Sensor Hub’s operational lifecycle, runtime state visibility, controlled shutdown behavior, and engineering interaction capabilities. + +This feature group is responsible for: + +* Managing system operational states and transitions + +* Ensuring safe teardown during updates or failures + +* Providing local human–machine interaction via OLED display and buttons + +* Supporting engineering/debug sessions for diagnostics and maintenance + + +These features act as the **supervisory layer** governing all other functional domains (DAQ, DQC, COM, DIAG, DATA, OTA, SEC). + +## 2 Scope and Assumptions + +**In Scope** + +* ESP32-S3 Sensor Hub + +* OLED-based local UI (I2C) + +* Physical input buttons + +* Controlled state transitions and teardown + +* Debug and engineering access + + +**Out of Scope** + +* Main Hub UI + +* Cloud dashboards + +* User authentication / role management + + +## 3 Sub-Feature Breakdown + +### 3.1 F-SYS-01: System State Management + +#### Description + +System State Management defines and controls the operational states of the Sensor Hub and governs all valid transitions between them. + +The system operates as a **finite state machine (FSM)** with deterministic behavior. + +#### Typical System States + +* **INIT** – Hardware and software initialization + +* **RUNNING** – Normal sensor acquisition and communication + +* **WARNING** – Non-fatal fault detected, degraded operation + +* **FAULT** – Fatal error, core functionality disabled + +* **OTA\_UPDATE** – Firmware update in progress + +* **MC\_UPDATE** – Machine constants update in progress + +* **TEARDOWN** – Controlled shutdown sequence + +* **IDLE / SERVICE** – Engineering or diagnostic interaction + + +#### Responsibilities + +* Enforce valid state transitions + +* Notify dependent components of state changes + +* Prevent unsafe operations during restricted states + + +### 3.2 F-SYS-02: Controlled Teardown Mechanism + +#### Description + +The Controlled Teardown Mechanism ensures that the Sensor Hub transitions safely from an active state into reset, update, or shutdown without data loss or corruption. + +Teardown is triggered by: + +* Firmware update + +* Machine constant update + +* Fatal system fault + +* Manual engineering command + + +#### Teardown Sequence (Mandatory) + +1. Stop sensor acquisition tasks + +2. Flush pending data via DP component + +3. Persist calibration, diagnostics, and runtime state + +4. Close communication sessions + +5. Release hardware resources + +6. Enter target state (reset, OTA, idle) + + +#### Responsibilities + +* Guarantee data consistency + +* Ensure deterministic shutdown behavior + +* Prevent flash or SD corruption + + +### 3.3 F-SYS-03: Status Indication (OLED-Based HMI) + +#### Description + +The Sensor Hub provides local system visibility using an **OLED display connected via I2C**, replacing LED indicators. + +The display, together with **three physical buttons (Up / Down / Select)**, forms a minimal local Human–Machine Interface (HMI). + +#### Default Information Displayed (Main Screen) + +1. **Connectivity status** + + * Connected / Disconnected + + * Signal strength (RSSI) if available + +2. **System status** + + * Current system state (RUNNING, WARNING, FAULT, OTA, etc.) + +3. **Connected sensors** + + * Count and/or summary status + +4. **Time and date** + + * Synchronized system time + + +#### Menu Navigation Behavior + +* **Select button** + + * From main screen → opens menu + + * From submenu → returns to main screen + +* **Up / Down buttons** + + * Navigate menu entries + + * Scroll within pages if applicable + + +#### Menu Structure + +**Main Menu** + +* **Diagnostics** + + * Lists active and stored diagnostic codes + + * Displays occurrence count per diagnostic + +* **Sensors** + + * Lists all detected sensors + + * Displays sensor type and configuration status + +* **Health** + + * Displays SD card usage + + * Displays overall system health indicators + + +#### Responsibilities + +* Provide real-time system visibility + +* Support local inspection without external tools + +* Reflect system state and diagnostics accurately + + +### 3.4 F-SYS-04: Debug & Engineering Sessions + +#### Description + +Debug & Engineering Sessions allow authorized engineers to interact with the Sensor Hub for diagnostics, inspection, and controlled operations. + +Sessions may be established via: + +* Wired interface (e.g., USB/UART) + +* Secure communication channel (logical session) + + +#### Supported Capabilities + +* Retrieve diagnostic logs + +* Read machine constant files + +* Inspect system state and health + +* Trigger controlled actions (e.g., reboot, teardown) + +* Monitor runtime logs + + +#### Session Types + +* **Diagnostic Session** – Read-only access for inspection + +* **Debug Session** – Command execution and deeper inspection + + +## 4 Functional Interaction Overview + +### System State & Teardown Relationship + +```text +RUNNING + ↓ (Update / Fault) +TEARDOWN + ↓ +OTA_UPDATE / MC_UPDATE / RESET +``` + +### Local HMI Interaction + +```text +OLED Display ← System State Manager +Buttons → UI Controller → State/Menu Logic +``` + +## 5 System SHALL Requirements (Formal) + +### System State Management + +* **SR-SYS-001**: The system shall implement a defined finite state machine for operational control. + +* **SR-SYS-002**: The system shall restrict operations based on the current system state. + +* **SR-SYS-003**: The system shall notify system components of state transitions. + + +### Controlled Teardown + +* **SR-SYS-004**: The system shall execute a controlled teardown sequence before firmware or machine constant updates. + +* **SR-SYS-005**: The system shall persist all critical runtime data before completing teardown. + +* **SR-SYS-006**: The system shall prevent data corruption during teardown and reset operations. + + +### Status Indication & HMI + +* **SR-SYS-007**: The system shall provide a local OLED display using I2C communication. + +* **SR-SYS-008**: The system shall display connectivity status, system state, sensor summary, and time/date. + +* **SR-SYS-009**: The system shall provide menu navigation using Up, Down, and Select buttons. + +* **SR-SYS-010**: The system shall provide diagnostic, sensor, and health information via the local menu. + + +### Debug & Engineering Sessions + +* **SR-SYS-011**: The system shall support diagnostic sessions for retrieving logs and system status. + +* **SR-SYS-012**: The system shall support debug sessions for controlled engineering operations. + +* **SR-SYS-013**: The system shall restrict debug actions to authorized sessions only. + + +## 6 Traceability Matrix + +

Feature ID

System Requirements

F-SYS-01

SR-SYS-001, SR-SYS-002, SR-SYS-003

F-SYS-02

SR-SYS-004, SR-SYS-005, SR-SYS-006

F-SYS-03

SR-SYS-007, SR-SYS-008, SR-SYS-009, SR-SYS-010

F-SYS-04

SR-SYS-011, SR-SYS-012, SR-SYS-013

+ +## 7 Dependencies + +* Diagnostics & Health Monitoring Features + +* Persistence & DP Component + +* Communication Features + +* Security & Safety Features + +* OTA Features + + +## \ No newline at end of file diff --git a/system_arch_final/asf-arch_1.drawio b/system_arch_final/asf-arch_1.drawio new file mode 100644 index 0000000..c958860 --- /dev/null +++ b/system_arch_final/asf-arch_1.drawio @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/system_arch_final/asf-arch_1.drawio.png b/system_arch_final/asf-arch_1.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..b27f4bc773ccfa2012c7f3c752cc1c4fca0fe6bd GIT binary patch literal 184066 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 QpKO7gGuF@j%kl320g`>iqW}N^ literal 0 HcmV?d00001 diff --git a/system_arch_final/selected sensors.html b/system_arch_final/selected sensors.html new file mode 100644 index 0000000..4d850f6 --- /dev/null +++ b/system_arch_final/selected sensors.html @@ -0,0 +1,697 @@ + + + + + + ESP32-S3 Sensor Array Analysis & Integration Guide + + + + + + + + + + + + + + + + +

+
+
S
+

SensorArchitect for ESP32-S3 / IDF v5.4

+
+
+ System Ready + Total Load: 0.00 mA +
+
+ +
+ + + + +
+ +
+
+ + + + + \ No newline at end of file diff --git a/system_arch_final/selected sensors.txt b/system_arch_final/selected sensors.txt new file mode 100644 index 0000000..f8b5a64 --- /dev/null +++ b/system_arch_final/selected sensors.txt @@ -0,0 +1,453 @@ + + + + + + ESP32-S3 Sensor Array Analysis & Integration Guide + + + + + + + + + + + + + + + + +
+
+
S
+

SensorArchitect for ESP32-S3 / IDF v5.4

+
+
+ System Ready + Total Load: 0.00 mA +
+
+ +
+ + + + +
+ +
+
+ + +