Local REST API
Relevant source files
The following files were used as context for generating this wiki page:
The Local REST API is a core networking component of the OpenAwair project, designed to provide offline, local-first access to air quality data and device control for Awair Glow C and Awair Element monitors. Its primary purpose is to ensure compatibility with original Awair local API schemas while allowing integrations with platforms like Home Assistant without relying on cloud services.
The API architecture follows a modular routing pattern where specific endpoint handlers are registered to a central router. This allows the system to expose sensor telemetry via GET requests and hardware controls, such as the smart plug relay, via POST requests.
Sources: CLAUDE.md:1-20, host/src/firmware/networking/rest.ts:1-25
API Architecture and Routing
The REST implementation is built around a request-response cycle managed by the RestRouter. This router maintains a map of registered RestEndpoint objects, indexed by a combination of their HTTP method and URL path.
Core Components
- RestRouter: The central dispatcher that receives
RestRequestobjects and returnsRestResponseobjects. - RestEndpoint: An interface defining the structure of an API handler, including its path, allowed method, and an asynchronous
handlefunction. - RestRequest/RestResponse: Data structures representing the incoming call and the outgoing status/body.
Sources: host/src/firmware/networking/restRouter.ts:3-30
Request Handling Flow
When a request is received, the router generates a lookup key using the format ${method}:${path}. If a matching endpoint is found, its handler is executed; otherwise, a 404 error is returned in JSON format.
The diagram above illustrates the internal logic of the RestRouter.handle method.
Sources: host/src/firmware/networking/restRouter.ts:20-29, host/test/restRouter.test.ts:15-28
API Endpoints
The project implements specific endpoints to expose device state and telemetry. These endpoints act as bridges between the underlying hardware drivers (like AwairDevice) and the network interface.
Available Endpoints
| Endpoint | Method | Purpose | Source File |
|---|---|---|---|
/api/v1/metrics | GET | Returns latest sensor readings and device metadata | rest.ts:9-17 |
/api/v1/relay | POST | Toggles the smart plug relay state and returns new state | rest.ts:19-27 |
/air-data/latest | GET | Legacy-compatible endpoint for sensor values | CLAUDE.md:126-127 |
Data Models
The GET /api/v1/metrics endpoint returns a DeviceMetrics object, which encapsulates various sensor readings defined in the shared telemetry module.
// host/src/shared/telemetry.ts:13-26
export interface DeviceMetrics {
readonly deviceId: string;
readonly model: 'AwairGlowC' | 'AwairElement';
readonly sensors: {
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-26, host/src/firmware/networking/rest.ts:9-17
Integration with Device Logic
The REST endpoints are instantiated by passing references to device controller methods. For example, the relay endpoint utilizes toggle() and getState() callbacks provided by the AwairDevice instance.
This sequence shows how the REST layer interacts with the hardware abstraction layer to perform actions.
Sources: host/src/firmware/networking/rest.ts:19-27, host/src/firmware/device.ts:21-28
Implementation Details
RestRouter Implementation
The router uses a standard TypeScript class to manage registrations.
// host/src/firmware/networking/restRouter.ts:15-29
export class RestRouter {
private readonly endpoints = new Map<string, RestEndpoint>();
public register(endpoint: RestEndpoint): void {
const key = `${endpoint.method}:${endpoint.path}`;
this.endpoints.set(key, endpoint);
}
public async handle(request: RestRequest): Promise<RestResponse> {
const key = `${request.method}:${request.path}`;
const endpoint = this.endpoints.get(key);
if (!endpoint) {
return { status: 404, body: JSON.stringify({ error: 'Not found' }) };
}
const body = await endpoint.handle();
return { status: 200, body };
}
}
Sources: host/src/firmware/networking/restRouter.ts:15-30
Error Handling
The API follows basic HTTP status code conventions:
- 200 OK: Successful request and execution of the handler.
- 404 Not Found: The requested path or method combination is not registered in the
endpointsmap.
Sources: host/src/firmware/networking/restRouter.ts:23-28, host/test/restRouter.test.ts:25-28
Summary
The Local REST API provides a standardized interface for interacting with OpenAwair firmware. By decoupling the routing logic (RestRouter) from the specific endpoint definitions (RestEndpoint), the system maintains flexibility to support both modern telemetry formats and legacy compatibility with original Awair integrations.
Sources: CLAUDE.md:12-16, host/src/firmware/networking/restRouter.ts:3-13