Sensor Interface Abstraction
Relevant source files
The following files were used as context for generating this wiki page:
- host/src/firmware/sensors/sensor.ts
- host/src/firmware/sensors/scheduler.ts
- host/src/shared/telemetry.ts
- host/src/firmware/sensors/sgp30.ts
- host/src/firmware/sensors/shtc3.ts
- host/src/firmware/sensors/sht30.ts
- host/src/firmware/sensors/t6703.ts
- host/src/firmware/sensors/hpma115s0.ts
- host/src/firmware/device.ts
The Sensor Interface Abstraction in OpenAwair provides a unified mechanism for interacting with various environmental sensors found across different Awair hardware models, specifically the Glow C and Element. This abstraction decouples the hardware-specific communication logic from the higher-level telemetry and application logic, allowing the system to handle diverse data types like temperature, humidity, VOCs, CO2, and particulate matter through a standardized interface.
At its core, the system utilizes a common driver interface and a scheduling mechanism to aggregate data into consolidated metrics. This architecture supports the project's goal of local-first functionality by ensuring that data collection is consistent regardless of whether the physical sensor uses I2C, UART, or GPIO.
Sources: CLAUDE.md:10-22, host/src/firmware/sensors/sensor.ts:3-7
Architecture and Core Interfaces
The abstraction is built around the SensorDriver interface, which defines the contract for all individual sensor implementations.
SensorDriver Interface
Every sensor in the system must implement the SensorDriver interface. This ensures that the SensorScheduler can interact with any sensor without knowing its specific hardware implementation details.
| Property | Type | Description |
|---|---|---|
name | string | The technical identifier for the sensor (e.g., "SGP30", "T6703"). |
sampleIntervalMs | number | The recommended frequency for reading data from the sensor. |
read() | () => Promise<SensorReading> | Asynchronous method to retrieve current environmental data. |
Sources: host/src/firmware/sensors/sensor.ts:3-7
Data Consolidation
Since individual sensors may only contribute a subset of environmental data (e.g., a SHTC3 only provides temperature and humidity), the system includes a mergeReadings utility. This function takes an array of partial SensorReading objects and collapses them into a single, unified state.
The diagram above illustrates how multiple discrete sensor outputs are combined into a single data structure.
Sources: host/src/firmware/sensors/sensor.ts:9-18
Implementation Details
Concrete Sensor Drivers
The repository provides specific implementations for the hardware components found in Awair devices.
| Sensor | Model Context | Data Provided | File Path |
|---|---|---|---|
| SGP30 | Glow C / Element | TVOC (ppb), eCO2 | host/src/firmware/sensors/sgp30.ts |
| SHTC3 | Glow C | Temperature, Humidity | host/src/firmware/sensors/shtc3.ts |
| SHT30 | Element | Temperature, Humidity | host/src/firmware/sensors/sht30.ts |
| T6703 | Element | CO2 (ppm) | host/src/firmware/sensors/t6703.ts |
| HPMA115S0 | Element | PM2.5 (ug/m3) | host/src/firmware/sensors/hpma115s0.ts |
Sources: CLAUDE.md:13-22, host/src/firmware/sensors/sgp30.ts:4-19, host/src/firmware/sensors/shtc3.ts:4-14
Sensor Reading Structure
The SensorReading interface (defined in shared telemetry) acts as the data transfer object between the hardware abstraction layer and the rest of the application.
export interface SensorReading {
readonly timestamp: Date;
readonly temperatureC?: number;
readonly humidityPercent?: number;
readonly vocPpb?: number;
readonly pm25UgM3?: number;
readonly co2Ppm?: number;
}
Sources: host/src/shared/telemetry.ts:7-14
Scheduling and Collection
The SensorScheduler manages the lifecycle of data collection. It holds a collection of SensorDriver instances and coordinates the execution of their read() methods.
The sequence diagram demonstrates the asynchronous, parallel execution of sensor reads facilitated by the scheduler.
Sources: host/src/firmware/sensors/scheduler.ts:5-16, host/src/firmware/device.ts:13-21
AwairDevice Integration
The AwairDevice class serves as the top-level controller. It consumes the SensorScheduler to produce DeviceMetrics, which include not just sensor data but also device-specific metadata like deviceId and model.
Key method: collectMetrics(deviceId, model)
- Triggers
scheduler.sampleAll(). - Packages the resulting
SensorReadinginto aDeviceMetricsobject. - Incorporates static or stateful data such as
motionDetected.
Sources: host/src/firmware/device.ts:13-21, host/src/shared/telemetry.ts:16-22
Sensor Constraints and Requirements
Certain sensors require specific handling within their drivers or the broader system logic:
- SGP30 (VOC): Requires a baseline to be set. The implementation provides a
setBaseline(baseline: number)method to persist and restore calibration data. In actual hardware, this baseline should be saved to flash every ~12 hours. - HPMA115S0 (PM2.5): Operates in a UART-based active mode and typically requires a "fan spin-up" period before accurate readings are available.
- T6703 (CO2): An NDIR sensor that outputs data approximately every 2 seconds.
Sources: CLAUDE.md:47-51, host/src/firmware/sensors/sgp30.ts:8-10, host/src/firmware/sensors/hpma115s0.ts:5-6
Summary
The Sensor Interface Abstraction provides a scalable and type-safe way to manage environmental monitoring in OpenAwair. By standardizing the communication via SensorDriver and the data format via SensorReading, the system can easily support new hardware revisions or different sensor configurations between the Glow C and Element models while maintaining a consistent API for telemetry and Home Assistant integration.