Committed the Phase 2-3 changeset (+2,598 lines, 42 files), then built a full Airthings sensor integration with Prometheus metrics and wired JefeHome into the Jenkins service launcher. Real air quality data now flowing from four Airthings devices at the Cabin into SQLite time-series storage and Prometheus gauges ready for Grafana.
Phase 2-3 Commit
The first order of business was getting the previous session's work committed. 42 files spanning FCM push delivery, OAuth2 auth middleware, Google Smart Home fulfillment, and the device registry all went in as a single commit. Sensitive files (google-services.json, firebase-service-account.json, .env) were already in .gitignore, though the Android data/ directory tripped a broad ignore pattern and needed -f to stage the Kotlin source files inside it.
Airthings: Business vs Consumer API
The Airthings API has two tiers: Business (ext-api, paid subscription) and Consumer (consumer-api, free for personal devices). First attempt hit a 403 on the Business API. Switching to Consumer revealed completely different response shapes — devices use serialNumber instead of id, and sensor readings come as [{sensorType, value, unit}] arrays instead of flat key-value pairs. The account listing also wraps in an {"accounts": [...]} envelope instead of returning a bare list. Three rounds of fix-and-test to get the shapes right, then all four devices came back: two Wave Gen2 units, a Wave Plus, and a View Plus.
Stale Device Filtering
Two of the four devices turned out to be dead — one last reported December 2023, the other August 2024. Without filtering, we'd store identical stale readings every 5 minutes forever. Added a 1-hour staleness threshold on the recorded timestamp from the API response. Now only the two live devices (Cabin / Bedroom and Cabin / Living Room) produce readings. The dead ones log a debug message and get skipped.
Prometheus Metrics
Built a custom Prometheus registry with gauges for temperature, humidity, CO2, VOC, PM2.5, radon, pressure, and battery — all labeled by device_id, device_name, and source. Service health counters track poll success/failure. The /metrics endpoint returns standard Prometheus text format, added to the auth middleware's PUBLIC_PATHS so Grafana can scrape without credentials. Point a Prometheus data source at the JefeHome metrics endpoint and it just works.
Service Startup Integration
JefeHome was missing from the Jenkins service launcher. Added it to three places: the jefe-service-launcher.groovy pipeline (starts in a Windows Terminal tab via scheduled task, same pattern as JefeAI), the jefe-service-stopper.groovy pipeline (graceful shutdown with port fallback), and the manual launch script. Health checks at /health in both the Jenkins verify stage and the service check script.
What's Next
- Set up Airthings API client credentials and test live polling on server startup
- Wire Grafana dashboard with Prometheus data source for sensor visualization
- Integrate Google Nest thermostat via Device Access API
- Cloudflare tunnel for JefeHome to enable Google Smart Home fulfillment
- Alert threshold tuning (temperature, CO2, radon levels)