Skip to content

Feature Specification: Unified Telemetry Hub

Status: Active / Implementing Last Updated: 2026-01-11

1. Executive Summary

The Unified Telemetry Hub is a polymorphic communication and data ingestion layer designed to capture any building infrastructure reading (liquid levels, electrical metrics, environmental status, mechanical flow) through a single, standardized envelope. It abstracts measurement points from physical assets, enabling a "plug-and-play" architecture for both manual logs and automated IoT bridges.

2. Problem Statement

  • Current State: Telemetry is currently implemented as "pilot" widgets (e.g., Cistern Level) with specific hardcoded expectations. Data is recorded against an assetId with a generic metric string, but lacks semantic definition (Unit, Data Type, Scale).
  • Impact: Scaling the platform to monitor hundreds of electrical, hydraulic, and environmental points would lead to a fragmented codebase, redundant widgets, and high maintenance costs.

3. Solution Architecture

Core Concepts

  1. Measurement Point (MP): A metadata-rich definition of a physical or logical sensor.
  2. Telemetry Ledger: A single, time-ordered collection (operations_telemetry_readings) that stores all readings in a standardized polymorphic envelope.
  3. IoT Bridge API: A universal endpoint /api/telemetry/ingest that accepts standard JSON payloads from external IoT gateways, bypassing the need for per-device integration logic.

Visualization Strategy (Smart Components)

Instead of a CisternWidget, a DynamicTelemetryWidget will: * Identify the dataType (gauge, binary, counter). * Map to a visual archetype (Radial Gauge, Status Light, Area Sparkline). * Apply the defined units and scale automatically.

4. Data Models

4.1. Measurement Point Configuration

Determines how a specific point is interpreted.

export const MetricDataType = z.enum([
    'gauge',    // Values that float up/down (level, temp)
    'counter',  // Incrementing values (flow meter, kWh)
    'binary',   // On/Off, Open/Closed
    'state'     // Enumerated states (Error, Standby, Running)
]);

export interface MeasurementPoint {
    id: string;          // e.g., "cistern-1.level"
    assetId: string;     // e.g., "cistern-1"
    displayName: string; // e.g., "Main Tank Level"
    dataType: MetricDataType;
    unit: string;        // "%", "cm", "psi", "gpm", "kWh"
    precision: number;   // Decimals to show
    scale?: {            // For translating raw dipstick to %
        min: number;
        max: number;
    }
}

4.2. Standard Telemetry Reading (The Envelope)

The unified record in the database.

export interface TelemetryReading {
    id: string;           // asset_point_timestamp
    assetId: string;
    pointId: string;      // specific sensor ID
    value: number | string | boolean;
    timestamp: Timestamp;
    source: 'iot' | 'manual' | 'system';

    // Semantic Context
    unit: string;
    metadata?: Record<string, any>; // Extra raw data (e.g. RSSI, battery)
}

5. IoT Bridge API Interface

The bridge will support batch ingestion:

{
  "gatewayId": "sd-ops-bridge-01",
  "readings": [
    {
      "pointId": "cistern-1.level",
      "value": 85.2,
      "ts": "2026-01-10T22:00:00Z"
    },
    {
      "pointId": "pump-2.status",
      "value": true,
      "ts": "2026-01-10T22:01:00Z"
    }
  ]
}

6. Implementation Plan

Phase 1: Foundation & Ledger Refactor (COMPLETED)

  • [x] Polymorphic Data Envelope: Single Firestore collection for all telemetry types.
  • [x] Service Migration: TelemetryService refactored for point-based recording.
  • [x] Registry & Metadata: MeasurementPoint registry for resolving types/units.

Phase 2: Ingestion Logic (COMPLETED)

  • [x] Universal IoT Ingest API: REST endpoint with API Key protection.
  • [x] Registry Enrichment: Server-side metadata resolution (assetId, dataType, unit).
  • [x] Manual Input Upgrade: TelemetryRecorder integrated with registry-based logging.

Phase 3: Smart Visualizer (IN PROGRESS)

  • [x] Smart Unit Conversion: On-the-fly math for Liters/Gallons/Celsius/Fahrenheit.
  • [x] Interactive Time-Series: Range switching (24h to 1y) in the UI.
  • [ ] Dynamic Component: Refactor to UniversalTelemetryWidget for auto-rendering unknown points.

7. Success Metrics

  • Capability Traceability: Full @cap coverage for IoT ingestion.
  • Scale: Ability to add a "Generator Fuel Level" point by only adding a configuration entry, with zero code changes to the dashboard.
  • Stability: Resolution of serialization issues by ensuring all readings are processed through the same ISO-string conversion layer.