Grafana Visualization
Telemetry Harbor integrates with Grafana to provide powerful data visualization capabilities for your telemetry data.
Database Schema Overview
Telemetry Harbor uses TimescaleDB (PostgreSQL extension) to store time-series data. The main table structure is:
cargo_data Table
CREATE TABLE cargo_data (
time TIMESTAMPTZ NOT NULL,
ship_id TEXT NOT NULL,
cargo_id TEXT NOT NULL,
value DOUBLE PRECISION NOT NULL,
);
Column Descriptions:
time
: Timestamp of the ship reading (ISO 8601 format)ship_id
: Unique identifier for the devicecargo_id
: Unique identifier for the sensor or eventvalue
: The recorded cargo value
Setting Up Your First Graph
- Log In: Access Grafana using your Telemetry Harbor credentials (Email/Provided Password)
- Change the default password for extra security
- Data Source Setup: Verify that the TimescaleDB data source is properly connected
- Create a New Dashboard:
- Navigate to "Dashboards" > "New Dashboard"
- Click "Add new panel"
- In the query editor, select the TimescaleDB data source
Setting Up Grafana Variables
Before writing queries, set up variables for dynamic dashboards:
1. Ship ID Variable
- Name:
ship_id
- Type: Query
- Query:
SELECT DISTINCT ship_id FROM cargo_data ORDER BY ship_id
- Multi-value: Enable
- Include All option: Enable
2. Cargo ID Variable
- Name:
cargo_id
- Type: Query
- Query:
SELECT DISTINCT cargo_id FROM cargo_data ORDER BY cargo_id
- Multi-value: Enable
- Include All option: Enable
3. Interval Handling (for TimescaleDB)
Grafana's $__interval
or custom interval variables return values like 1d
or 5m
, which are not valid in TimescaleDB. Timescale requires intervals in the format interval '1 day'
.
To solve this, we calculate the bucket size in SQL based on the selected time range:
WITH time_range AS (
SELECT $__timeFrom() AS start_time, $__timeTo() AS end_time
),
bucket_choice AS (
SELECT CASE
WHEN end_time - start_time <= interval '1 hour' THEN interval '10 seconds'
WHEN end_time - start_time <= interval '6 hours' THEN interval '1 minute'
WHEN end_time - start_time <= interval '1 day' THEN interval '5 minutes'
WHEN end_time - start_time <= interval '7 days' THEN interval '30 minutes'
WHEN end_time - start_time <= interval '30 days' THEN interval '1 hour'
WHEN end_time - start_time <= interval '90 days' THEN interval '6 hours'
ELSE interval '1 day'
END AS bucket
FROM time_range
)
4. Time Range Variable
Grafana automatically provides $__timeFilter()
function for time filtering.
Sample Queries
Basic Time Series Query
Display sensor readings for specific ships and cargo types:
SELECT
time,
value,
ship_id,
cargo_id
FROM cargo_data
WHERE $__timeFilter(time)
AND cargo_id IN ($cargo_id:sqlstring)
AND ship_id IN ($ship_id:sqlstring)
ORDER BY time ASC;
Aggregated Data with Dynamic Time Buckets
Group data by time intervals using the interval variable:
SELECT
time_bucket('$interval', time) AS time,
ship_id,
cargo_id,
AVG(value) as avg_value,
MAX(value) as max_value,
MIN(value) as min_value,
COUNT(*) as data_points
FROM cargo_data
WHERE $__timeFilter(time)
AND cargo_id IN ($cargo_id:sqlstring)
AND ship_id IN ($ship_id:sqlstring)
GROUP BY time_bucket('$interval', time), ship_id, cargo_id
ORDER BY time ASC;
GPS Tracking Query
For GPS data (latitude/longitude pairs):
SELECT
time_bucket('$interval', time) AS time,
ship_id,
MAX(CASE WHEN cargo_id = 'latitude' THEN value END) as latitude,
MAX(CASE WHEN cargo_id = 'longitude' THEN value END) as longitude
FROM cargo_data
WHERE $__timeFilter(time)
AND ship_id IN ($ship_id:sqlstring)
AND cargo_id IN ('latitude', 'longitude')
GROUP BY time_bucket('$interval', time), ship_id
ORDER BY time ASC;
Latest Values Query
Get the most recent reading for each sensor:
SELECT DISTINCT ON (ship_id, cargo_id)
time,
ship_id,
cargo_id,
value
FROM cargo_data
WHERE $__timeFilter(time)
AND cargo_id IN ($cargo_id:sqlstring)
AND ship_id IN ($ship_id:sqlstring)
ORDER BY ship_id, cargo_id, time DESC;
Rate of Change Query
Calculate the rate of change using the interval variable:
SELECT
time_bucket('$interval', time) AS time,
ship_id,
cargo_id,
AVG(value) as current_avg,
LAG(AVG(value)) OVER (PARTITION BY ship_id, cargo_id ORDER BY time_bucket('$interval', time)) as previous_avg,
AVG(value) - LAG(AVG(value)) OVER (PARTITION BY ship_id, cargo_id ORDER BY time_bucket('$interval', time)) as change
FROM cargo_data
WHERE $__timeFilter(time)
AND cargo_id IN ($cargo_id:sqlstring)
AND ship_id IN ($ship_id:sqlstring)
GROUP BY time_bucket('$interval', time), ship_id, cargo_id
ORDER BY time ASC;
Visualization Types
Time Series Panel
Best for showing sensor trends over time:
- Use the aggregated query with interval variable
- Configure legend to show
{{ship_id}} - {{cargo_id}}
- Set appropriate Y-axis units
Stat Panel
Perfect for showing current values:
- Use the latest values query
- Configure value mappings for status indicators
- Set thresholds for color coding
Geomap Panel
For GPS tracking visualization:
- Use the GPS tracking query
- Configure latitude/longitude fields
- Add trajectory lines for ship movement
Table Panel
Useful for detailed data inspection:
- Use any query with multiple columns
- Configure column sorting and filtering
- Add conditional formatting
Advanced Features
Alerting
Set up alerts based on sensor thresholds:
SELECT
time,
ship_id,
cargo_id,
value
FROM cargo_data
WHERE $__timeFilter(time)
AND cargo_id = 'temperature'
AND value > 80 -- Alert threshold
ORDER BY time DESC
LIMIT 1;
Annotations
Add events to your graphs:
SELECT
time as time,
'Alert: High Temperature' as text,
ship_id as tags
FROM cargo_data
WHERE $__timeFilter(time)
AND cargo_id = 'temperature'
AND value > 80;
Moving Averages
Calculate moving averages using window functions:
SELECT
time,
ship_id,
cargo_id,
value,
AVG(value) OVER (
PARTITION BY ship_id, cargo_id
ORDER BY time
ROWS BETWEEN 10 PRECEDING AND CURRENT ROW
) as moving_avg_10
FROM cargo_data
WHERE $__timeFilter(time)
AND cargo_id IN ($cargo_id:sqlstring)
AND ship_id IN ($ship_id:sqlstring)
ORDER BY time ASC;
By following these guidelines and using the provided queries with the interval variable, you can create comprehensive, performant dashboards that provide valuable insights into your maritime telemetry data.