Telemetry and Timeseries
Beacon Tower collects, stores, and streams telemetry data from connected assets in real time. The platform provides both historical timeseries queries and live data streaming via SignalR.
Data Ingestion Flow
Telemetry data flows through the following pipeline:
- Provider Client pushes data using its respective protocol (Azure IoT Hub, file import, HTTP, etc.)
- Asset Processor (Orleans grain) receives the data, validates it against the asset's model definition
- Timeseries Storage persists validated data points to TimescaleDB
Each asset has a dedicated processor grain that handles validation and storage operations. The grain ensures incoming data conforms to the asset's model schema before persisting it.
Related: See Telemetry Ingestion for the NATS message format, required headers, and JSON payload structure. See Assets, Providers, and Bindings for details on how assets connect to data sources.
Timeseries Storage
Beacon Tower uses TimescaleDB, a PostgreSQL extension optimized for time-series workloads. Each data point is stored with the following metadata:
| Field | Description |
|---|---|
time | Timestamp of the measurement |
assetId | Unique identifier of the asset |
componentId | Optional component identifier within the asset |
timeseries_name | Name of the telemetry signal (e.g., "temperature") |
timeseries_type | Type of data: "telemetry", "property", "command" |
modelId | Reference to the asset's model definition |
messageId | Unique identifier for the ingestion message |
value | The actual measurement value |
This schema enables efficient queries across time ranges, assets, and signal types.
Querying Historical Timeseries
The Beacon Tower API provides powerful endpoints for retrieving historical telemetry data with aggregation support.
Basic Timeseries Query
Use POST /timeseries/get to retrieve historical data. Note this uses POST (not GET) because it requires a JSON request body.
Request Body Schema (TimeseriesGet):
{
"assetId": "asset1",
"timeseriesName": ["temperature", "humidity"],
"searchSpanFrom": "2024-03-04T19:03:00.39+00:00",
"searchSpanTo": "2024-03-10T19:03:00+00:00",
"aggregationType": "avg",
"aggregationInterval": "PT5M"
}
Example Request:
curl -X POST https://api.beacontower.ai/timeseries/get \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"assetId": "pump-007",
"timeseriesName": ["pressure", "flow_rate"],
"searchSpanFrom": "2024-03-04T00:00:00Z",
"searchSpanTo": "2024-03-04T23:59:59Z",
"aggregationType": "avg",
"aggregationInterval": "PT15M"
}'
Aggregation Types
The aggregationType parameter supports:
avg— Average value over the intervalmin— Minimum valuemax— Maximum valuefirst— First value in the intervallast— Last value in the intervalsum— Sum of all valuesmedian— Median value
Aggregation Intervals
The aggregationInterval parameter uses ISO 8601 duration format:
PT1M— 1 minutePT5M— 5 minutesPT15M— 15 minutesPT1H— 1 hourPT12H— 12 hoursP1M— 1 monthP1Y— 1 year
Custom intervals are also supported, such as "12 minutes".
Advanced Filtering with WHERE Clause
Use the optional whereClause parameter for SQL-like filtering on timeseries data:
curl -X POST https://api.beacontower.ai/timeseries/get \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"assetId": "pump-007",
"timeseriesName": ["pressure"],
"searchSpanFrom": "2024-03-04T00:00:00Z",
"searchSpanTo": "2024-03-04T23:59:59Z",
"whereClause": "value > 100 AND timeseries_type = '\''telemetry'\''"
}'
You can filter on: time, assetid, componentid, timeseries_name, timeseries_type, modelid, messageid, value.
Querying Latest Values
For the most recent value of each timeseries, use POST /timeseries/get/last.
Request Body Schema (TimeseriesGetLast):
{
"items": [
{
"assetId": "asset1",
"componentId": null,
"timeseries": null
},
{
"assetId": null,
"componentId": null,
"timeseries": [
{ "name": "temperature", "type": "telemetry" },
{ "name": "batterylevel", "type": "telemetry" }
]
}
]
}
Example Request:
curl -X POST https://api.beacontower.ai/timeseries/get/last \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"assetId": "pump-007",
"componentId": null,
"timeseries": [
{ "name": "pressure", "type": "telemetry" },
{ "name": "temperature", "type": "telemetry" }
]
}
]
}'
This endpoint is optimized for fetching current asset states without scanning historical data.
Real-Time Streaming with SignalR
For real-time telemetry updates, Beacon Tower provides a SignalR-based push notification system. This is more efficient than polling when you need live data updates.
1. Negotiate SignalR Connection
First, obtain a SignalR connection URL and access token:
curl -X POST https://api.beacontower.ai/push/negotiate \
-H "X-API-Key: your-api-key"
Response:
{
"url": "wss://beacon-signalr.service.signalr.net/client/?hub=push",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Use the returned url and accessToken to establish a SignalR client connection.
2. Create a Subscription
Once connected to SignalR, create a subscription to receive telemetry updates:
curl -X POST https://api.beacontower.ai/push/subscription \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"connectionId": "your-signalr-connection-id",
"topic": "telemetry",
"assets": ["pump-007", "pump-008"],
"samplingType": "none"
}'
Parameters:
connectionId— Your SignalR connection identifiertopic— Subscription topic:"telemetry"or"alarm"assets— Array of asset IDs to monitorsamplingType—"none"(send all updates) or"first"(send first update per interval)
Response:
{
"subscriptionId": "sub-12345",
"expiresAt": "2024-03-04T20:13:00Z"
}
3. Manage Subscriptions
Subscriptions have a TTL of 600 seconds (10 minutes). Renew them to keep receiving updates:
Renew Subscription:
curl -X PUT https://api.beacontower.ai/push/subscription/sub-12345 \
-H "X-API-Key: your-api-key"
Get Subscription Details:
curl -X GET https://api.beacontower.ai/push/subscription/sub-12345 \
-H "X-API-Key: your-api-key"
Delete Subscription:
curl -X DELETE https://api.beacontower.ai/push/subscription/sub-12345 \
-H "X-API-Key: your-api-key"
Subscription Topics
| Topic | Description |
|---|---|
telemetry | Receive telemetry data updates from subscribed assets |
alarm | Receive alarm notifications from subscribed assets |
Sampling Types
| Type | Behavior |
|---|---|
none | Send all telemetry updates immediately |
first | Send only the first update within each sampling window |
Dashboard Integration
Beacon Tower dashboards support both data access patterns:
- Polling Mode: Periodically query
POST /timeseries/getfor updated data - Real-Time Mode: Establish SignalR connection and subscribe to live telemetry streams
Real-time mode is recommended for operational dashboards that require low-latency updates. Polling mode is suitable for historical analysis and custom aggregation windows.
Related: See Dashboards for details on creating and configuring visualizations.
Next Steps
- Explore the full timeseries API in the API Reference
- Learn about Telemetry Ingestion for message formats and data validation
- Learn about Assets, Providers, and Bindings to connect data sources
- Build custom visualizations with Dashboards
API Endpoints Summary:
| Endpoint | Method | Purpose |
|---|---|---|
/timeseries/get | POST | Query historical timeseries with aggregation |
/timeseries/get/last | POST | Get latest values for specified timeseries |
/push/negotiate | POST | Obtain SignalR connection credentials |
/push/subscription | POST | Create a new push notification subscription |
/push/subscription/{id} | GET | Get subscription details |
/push/subscription/{id} | PUT | Renew subscription TTL |
/push/subscription/{id} | DELETE | Delete subscription |