C/C++ Firmware Implementation
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
The C/C++ Firmware Implementation for OpenAwair is designed to restore local-first functionality to discontinued Awair Glow C and Awair Element air quality monitors. These devices are based on the Laird Sterling-EWB module, which contains an STM32F412 ARM Cortex-M4 MCU and a Cypress CYW4343W Wi-Fi/BLE radio. The firmware enables fully offline operation, allowing data access via MQTT or a local REST API for integration with platforms like Home Assistant.
The firmware architecture is structured to support sensor data collection, wireless networking (Wi-Fi and BLE), and persistent storage for sensor baselines and device configuration. It targets the STM32F412 platform using the ARM GCC compiler and is intended to be built within the Infineon ModusToolbox or WICED SDK environments to leverage existing Wi-Fi/BLE drivers and RTOS capabilities.
Sources: CLAUDE.md:1-12, firmware/README.md:1-5
System Architecture
The firmware is designed around a multi-layered architecture that interacts with specific hardware components found in the Awair Glow C and Element devices.
Hardware Abstraction and MCU
The core of the system is the STM32F412 MCU. The firmware must handle hardware-specific constraints such as reading-protected MCUs (requiring a full erase for custom firmware) and communicating with peripherals via I2C, UART, and GPIO.
The diagram above represents the hardware peripheral connections described for both Awair models.
Sources: CLAUDE.md:14-36, firmware/include/firmware_config.h:1-10
Memory and Flash Layout
The firmware utilizes a specific flash memory layout to support safe updates and persistent storage.
| Region | Size | Purpose |
|---|---|---|
| Bootloader | 64-128KB | Handles BLE DFU and recovery modes. |
| Application | Remainder | Main firmware including sensor tasks and networking logic. |
| Flash Storage | N/A | Key-value storage for Wi-Fi credentials and SGP30 baselines. |
Sources: CLAUDE.md:67-72, 85-88
Firmware Configuration and Device Logic
The firmware includes a configuration structure to identify the hardware model and device identity. This is critical because the firmware must auto-detect whether it is running on a Glow C or an Element by probing for specific sensors like the CO2 NDIR sensor.
Device Configuration Structure
The project defines a standard configuration structure for device identification:
typedef struct {
unsigned int model;
const char *device_id;
} openawair_device_config_t;
Sources: firmware/include/firmware_config.h:7-10
Supported Models
The firmware recognizes two primary hardware targets:
OPENAWAIR_MODEL_GLOW_C(Value: 1)OPENAWAIR_MODEL_ELEMENT(Value: 2)
Sources: firmware/include/firmware_config.h:4-5
Functional Modules
Sensor Management
The firmware implements drivers for various air quality sensors with specific timing and maintenance requirements.
- SGP30 (VOC): Requires reading at 2-10 second intervals and saving calibration baselines to flash every ~12 hours.
- HPMA115S0 (PM2.5): Requires a fan warm-up period before accurate readings can be taken.
- T6703 (CO2): Standard output every 2 seconds.
Sources: CLAUDE.md:74-80, 108-110
Networking and Connectivity
The networking stack is responsible for providing local and remote access to sensor data.
- Wi-Fi Provisioning: On first boot, the device enters a provisioning mode, advertising a BLE Provisioning service to receive credentials.
- MQTT Client: Publishes telemetry to
openawair/{deviceId}/telemetryand status toopenawair/{deviceId}/availability. - REST API: Serves local requests via endpoints such as
GET /air-data/latest. - Home Assistant Integration: Sends MQTT Discovery configuration messages to allow automatic entity creation.
Sources: CLAUDE.md:99-105, 126-135
Bootloader and DFU Protocol
The bootloader implements a custom DFU (Device Firmware Update) protocol modeled after Nordic Secure DFU.
The sequence above illustrates the BLE DFU streaming and validation process.
Sources: CLAUDE.md:85-97
Development and Build Environment
The firmware is structured to be compatible with standard ARM development tools.
- Compiler: ARM GCC.
- SDK: Infineon ModusToolbox or WICED (Broadcom/Cypress) SDK.
- Debug Interface: SWD (Serial Wire Debug) using pins SWDIO, SWDCLK, NRST, GND, and 3.3V.
- Entry Point: The standard
mainfunction initializes the device configuration and enters the application loop.
#include "firmware_config.h"
int main(void) {
openawair_device_config_t config = {
.model = OPENAWAIR_MODEL_GLOW_C,
.device_id = "awair-glowc-01",
};
(void)config;
while (1) {
// Application logic and sensor scheduling
}
return 0;
}
Sources: firmware/src/main.c:3-14, firmware/README.md:3-11
Conclusion
The OpenAwair C/C++ firmware provides the essential logic to repurpose legacy Awair hardware as local-first IoT sensors. By leveraging the STM32F412 MCU and the WICED/ModusToolbox ecosystem, it implements a robust stack including sensor scheduling, persistent storage management, and multiple communication interfaces. The inclusion of a dedicated bootloader and BLE DFU protocol ensures that the devices remain maintainable and updatable without requiring physical access after the initial flash.