SmartDB Firebase API and team integration
The implemented v2 bench system consists of the two ESP-IDF firmware targets and this Firebase Auth / Firestore / Cloud Functions HTTP API. The user dashboard belongs to the frontend team. The optional developer console exercises the API locally; it is not the product UI and has not been deployed.
The separate Python CoAP gateway remains available. This HTTPS path does not implement its production CoAP/DTLS transport or a trained AI inference service.
Run locally
Install Node.js 22 LTS with npm and Java 21 or newer, then from the repository root run:
sh system.sh
The launcher installs the locked dependencies when missing, builds the developer console,
starts Firebase emulators, and creates a local administrator. It prints the credentials and
saves them in .local/admin.json with owner-only permissions. No Firebase account or cloud
project is needed. Open http://127.0.0.1:5000; the API base URL is
http://127.0.0.1:5000/api/v1. Emulator inspection is at http://127.0.0.1:4000.
Keep these development services on loopback. Ctrl+C exports local data into .local/firebase
for the next run. .local/ is ignored by Git and is excluded from documentation exports.
sh system.sh firmware opens the existing two-board setup menu. Stop the local services
before sh system.sh test, which uses fresh, disposable Auth/Firestore emulators. Tests
never import or alter the saved .local/firebase data.
Frontend handoff
Import the OpenAPI contract and use the
Postman collection and environment. All routes below
are relative to /api/v1.
Sign in with
POST /auth/loginusing an already-provisioned email/password account. Send the returnedaccess_tokenas a bearer token. On expiry, call/auth/refreshwith the opaquerefresh_token; replace both tokens. Refresh tokens rotate once./auth/logoutrevokes the supplied application session. Raw Firebase SDK tokens obtained outside this login flow do not automatically create an API session.Use
GET /devices, then the selected device’s/status,/telemetry/latest,/telemetry?limit=100,/configand/commands. Latest telemetry returns 404 before the first upload. History is newest server receipt first;from/tofilter that receipt time because a board may lack a synchronized clock. The API currently returns bounded lists, not cursor pagination.Display unavailable readings as unknown: voltage and power are null on v2. Preserve
synthetic, sensor validity andvision.ready. Deviceonlinemeans contact within 180 seconds, not that any sensor reading is currently fresh. Telemetry can contain delayed queued samples. Local fusion freshness applies at capture, not at browser view.Fetch
/devices/{id}/fusion/framewith the bearer header and render a blob URL.X-Received-At,X-Fusion-Sequence,X-Capture-Age-Ms, andX-Syntheticdescribe the stored preview. Label its age; it is not live video and may outlive device connectivity. Only one 320 × 240 BMP is retained per device. Numerical temperatures come from native MLX samples in telemetry, not interpolated image colors.Use
/alertsand/notificationsfor in-app events. Resolving an alert changes only the record. It never re-arms the relay. Email, SMS and push delivery are not implemented.Treat configuration and commands as asynchronous.
PUT /devices/{id}/configrecords desired limits and queuesAPPLY_CONFIG; inspect/commandsfor success/failure. A 200/202 response is not evidence the board acted. There is no remote close/re-arm.
The same-origin console needs no CORS configuration. For a separately hosted team UI,
set SMARTDB_ALLOWED_ORIGINS to an explicit comma-separated list of origins, including
scheme and port. For local emulators, place it in cloud/.env.local, for example
SMARTDB_ALLOWED_ORIGINS=http://localhost:5173. Alternatively proxy /api through your
frontend’s development server. Cross-origin requests still require bearer authentication;
no wildcard origin or cross-site cookie authentication is enabled.
Ownership and device installation
Records are owner-scoped, including for administrators. Operators can create their own device records, upload diagnostics, update desired limits and request commands; viewers cannot write operational data. Administrators can list account profiles and provision or rotate credentials for their own devices. Shared households and device ownership transfer are not implemented. A viewer needs a device record assigned to their UID by the project administrator before it can see that installation.
Create a device with POST /devices, then provision it with POST /device/register
using device_id, serial_number, hardware and firmware. The response contains a
one-time device_key; the server stores only its SHA-256 lookup hash. A device credential
can access only that board and cannot manage accounts or issue control commands. If lost,
an owner administrator can call /devices/{id}/credential/rotate; the old key stops working
immediately. Keep keys out of frontend bundles, logs and committed Postman environments.
In the S3 setup menu, enter the deployed HTTPS URL ending in
/api/v1/devices/DEVICE_ID/telemetry and the device key as telemetry_token, then save and
restart. The camera receives only its separate local token. Physical boards cannot reach
the computer’s loopback address, and the firmware intentionally rejects plain HTTP upload
URLs. The emulator is for software integration; use a reachable HTTPS deployment for boards.
Delivery, configuration and commands
Telemetry is acknowledged with 202 only after Firestore persistence. sample_id is unique
within a device; identical retries return duplicate: true, conflicting content returns 409.
Without sample_id, each legacy diagnostic upload is a new record. Non-synthetic transitions
into a tripped state create an alert and in-app notification in the same transaction.
The 202 body carries at most one pending command, delivered only with a device credential:
Command |
Behavior |
|---|---|
|
Requests local opening; physical re-arm is required |
|
Wakes the telemetry collector |
|
Persists a 5–60 second telemetry interval; does not change sensor sampling |
|
Generated by config PUT; applies 20–100°C, >0–1 A and 5–60 s bounds, opens relay |
Local commissioning and CT calibration are preserved during cloud configuration. A board
acknowledges /commands/{id}/ack with success or failed and an ESP-IDF error name.
An OPEN_RELAY acknowledgement means the request was accepted by firmware; check subsequent
relay telemetry for reported output state. It is not contact-position feedback.
Commands expire for delivery after two minutes; GET returns the last 100 records for users or the oldest available pending command for a device. The board persists its last command ID/result and interval, making an ordinary retry/reboot idempotent. A power failure between applying configuration and recording its command can cause safe reapplication. Do not reset the server command counter for an already-paired board: IDs must keep increasing. For a replacement cloud project, reprovision/reset the board’s cloud-control NVS namespace as part of maintenance. The board never accepts a remote close command.
The S3 sends a best-effort fresh preview after a successful telemetry upload, at most once per 30 seconds (up to the configured telemetry interval when longer). Failed previews are dropped; stale images are never queued for retry. The server validates the fixed BMP layout, limits uploads to six per minute, and stores the latest frame below Firestore’s document size limit. JSON requests are limited to 32 KiB, and API actor rate limits apply.
Firebase deployment
The repository is configured but no live Firebase project has been deployed.
Create/select a Firebase project, enable Email/Password Authentication and create the default Firestore database. Cloud Functions deployment requires a billing-enabled Blaze project. Use a region near the installed devices; the checked-in function region is
asia-southeast1.Copy
cloud/.env.exampletocloud/.env.YOUR_PROJECT_ID, set the Firebase web API key and any team frontend origins. Keep the file private. Login/refresh follow the Firebase Auth REST interface.Create the initial account in Firebase Authentication. With authorized Google application default credentials on the administrator machine, provision its application profile:
node cloud/scripts/provision-user.mjs --project YOUR_PROJECT_ID --email admin@example.com --name Administrator --role admin
This only provisions an existing Firebase account; it does not accept a password on the command line or silently change an existing role.
Deploy the API and deny-by-default Firestore rules using Firebase CLI:
npx firebase login npx firebase deploy --project YOUR_PROJECT_ID --only functions,firestore
A function URL has the form
https://asia-southeast1-YOUR_PROJECT_ID.cloudfunctions.net/api; append/api/v1for the API base. Theapifunction name and/api/v1route prefix are separate. Configure the team’s frontend origin or its reverse proxy accordingly. The checked-in Hosting configuration is for the optional developer console; deployingfunctions,firestoredoes not publish it or replace the team’s user dashboard.
Firestore clients cannot read the database directly; the API uses Admin SDK credentials and enforces ownership/roles. Telemetry and alerts are retained until administratively removed; production retention, backups, session cleanup, monitoring and billing budgets must be configured for the chosen deployment. This bench implementation has no trained anomaly model, OTA updater, production DTLS path or external notification delivery.
Source and verification
File |
Responsibility |
|---|---|
Routes, durable telemetry/alerts, configuration commands, bounded previews |
|
Firebase login, session rotation, owner/role checks, device keys and rate limits |
|
Strict request validation and bench limits |
|
Cloud Functions deployment entry point |
|
Emulator integration tests for persistence, permissions and retries |
Run npm test from the repository root. Firmware verification remains
sh tools/check.sh inside esp_idf/smartdb_fusion, plus PlatformIO target builds.
Software tests do not establish sensor accuracy, power capacity or physical relay behavior.