fix(observers): rename telemetry airtime fields to seconds

airtime_tx_pct/airtime_rx_pct always held the observer's tx_air_secs /
rx_air_secs counters, never a percentage. Rename the columns and the
airtimeTxPct/airtimeRxPct response fields to *Secs. Values are unchanged:
cumulative since boot on 1h points, per-bucket delta on 6h/24h.
This commit is contained in:
MrAlders0n
2026-09-10 07:12:52 -04:00
parent b66573b3b7
commit 0cb0f16217
9 changed files with 43 additions and 38 deletions
@@ -0,0 +1,4 @@
-- These always held seconds of radio time from the observer's tx_air_secs/rx_air_secs
-- status fields, never a percentage; name them for what they are.
ALTER TABLE observer_telemetry RENAME COLUMN airtime_tx_pct TO airtime_tx_secs;
ALTER TABLE observer_telemetry RENAME COLUMN airtime_rx_pct TO airtime_rx_secs;
+6 -6
View File
@@ -158,8 +158,8 @@ func (s *Store) InsertObserverTelemetry(ctx context.Context, observerID uuid.UUI
ObserverID: observerID,
ReportedAt: pgtype.Timestamptz{Time: reportedAt, Valid: true},
BatteryVoltageMv: batteryMV,
AirtimeTxPct: txAirSecs,
AirtimeRxPct: rxAirSecs,
AirtimeTxSecs: txAirSecs,
AirtimeRxSecs: rxAirSecs,
NoiseFloorDb: &noiseFloor,
UptimeSeconds: &uptimeSeconds,
QueueLength: queueLen,
@@ -183,8 +183,8 @@ func (s *Store) GetObserverTelemetry(ctx context.Context, observerID uuid.UUID,
points = append(points, api.ObserverTelemetryPoint{
T: v.ReportedAt.Time.UnixMilli(),
BatteryMV: v.BatteryVoltageMv,
AirtimeTxPct: v.AirtimeTxPct,
AirtimeRxPct: v.AirtimeRxPct,
AirtimeTxSecs: v.AirtimeTxSecs,
AirtimeRxSecs: v.AirtimeRxSecs,
NoiseFloorDB: v.NoiseFloorDb,
UptimeSeconds: v.UptimeSeconds,
QueueLength: v.QueueLength,
@@ -216,8 +216,8 @@ func (s *Store) GetObserverTelemetryBucketed(ctx context.Context, observerID uui
points = append(points, api.ObserverTelemetryPoint{
T: r.Bucket.Time.UnixMilli(),
BatteryMV: &r.BatteryVoltageMv,
AirtimeTxPct: &r.AirtimeTxPct,
AirtimeRxPct: &r.AirtimeRxPct,
AirtimeTxSecs: &r.AirtimeTxSecs,
AirtimeRxSecs: &r.AirtimeRxSecs,
NoiseFloorDB: &r.NoiseFloorDb,
UptimeSeconds: &r.UptimeSeconds,
QueueLength: &r.QueueLength,
+5 -5
View File
@@ -226,14 +226,14 @@ WHERE id = $1;
-- Inserts a telemetry snapshot for an observer. The reported_at timestamp should
-- be truncated to the configured resolution before calling to ensure deduplication.
INSERT INTO observer_telemetry (
observer_id, reported_at, battery_voltage_mv, airtime_tx_pct,
airtime_rx_pct, noise_floor_db, uptime_seconds, queue_length,
observer_id, reported_at, battery_voltage_mv, airtime_tx_secs,
airtime_rx_secs, noise_floor_db, uptime_seconds, queue_length,
debug_flags, receive_errors
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
ON CONFLICT (observer_id, reported_at) DO NOTHING;
-- name: GetObserverTelemetry :many
SELECT id, reported_at, battery_voltage_mv, airtime_tx_pct, airtime_rx_pct,
SELECT id, reported_at, battery_voltage_mv, airtime_tx_secs, airtime_rx_secs,
noise_floor_db, uptime_seconds, queue_length, debug_flags, receive_errors
FROM observer_telemetry
WHERE observer_id = $1
@@ -247,8 +247,8 @@ SELECT
(date_trunc('day', reported_at) +
(EXTRACT(HOUR FROM reported_at)::int / $4::int) * ($4::int * interval '1 hour'))::timestamptz AS bucket,
AVG(battery_voltage_mv)::int AS battery_voltage_mv,
GREATEST(MAX(airtime_tx_pct) - MIN(airtime_tx_pct), 0)::real AS airtime_tx_pct,
GREATEST(MAX(airtime_rx_pct) - MIN(airtime_rx_pct), 0)::real AS airtime_rx_pct,
GREATEST(MAX(airtime_tx_secs) - MIN(airtime_tx_secs), 0)::real AS airtime_tx_secs,
GREATEST(MAX(airtime_rx_secs) - MIN(airtime_rx_secs), 0)::real AS airtime_rx_secs,
AVG(noise_floor_db)::real AS noise_floor_db,
MAX(uptime_seconds)::bigint AS uptime_seconds,
AVG(queue_length)::int AS queue_length,
+2 -2
View File
@@ -258,8 +258,8 @@ type ObserverTelemetry struct {
ObserverID uuid.UUID `json:"observer_id"`
ReportedAt pgtype.Timestamptz `json:"reported_at"`
BatteryVoltageMv *int32 `json:"battery_voltage_mv"`
AirtimeTxPct *float32 `json:"airtime_tx_pct"`
AirtimeRxPct *float32 `json:"airtime_rx_pct"`
AirtimeTxSecs *float32 `json:"airtime_tx_secs"`
AirtimeRxSecs *float32 `json:"airtime_rx_secs"`
NoiseFloorDb *float32 `json:"noise_floor_db"`
UptimeSeconds *int64 `json:"uptime_seconds"`
QueueLength *int32 `json:"queue_length"`
+17 -17
View File
@@ -891,7 +891,7 @@ func (q *Queries) GetObserverScopes(ctx context.Context, observerID uuid.UUID) (
}
const getObserverTelemetry = `-- name: GetObserverTelemetry :many
SELECT id, reported_at, battery_voltage_mv, airtime_tx_pct, airtime_rx_pct,
SELECT id, reported_at, battery_voltage_mv, airtime_tx_secs, airtime_rx_secs,
noise_floor_db, uptime_seconds, queue_length, debug_flags, receive_errors
FROM observer_telemetry
WHERE observer_id = $1
@@ -912,8 +912,8 @@ type GetObserverTelemetryRow struct {
ID int64 `json:"id"`
ReportedAt pgtype.Timestamptz `json:"reported_at"`
BatteryVoltageMv *int32 `json:"battery_voltage_mv"`
AirtimeTxPct *float32 `json:"airtime_tx_pct"`
AirtimeRxPct *float32 `json:"airtime_rx_pct"`
AirtimeTxSecs *float32 `json:"airtime_tx_secs"`
AirtimeRxSecs *float32 `json:"airtime_rx_secs"`
NoiseFloorDb *float32 `json:"noise_floor_db"`
UptimeSeconds *int64 `json:"uptime_seconds"`
QueueLength *int32 `json:"queue_length"`
@@ -939,8 +939,8 @@ func (q *Queries) GetObserverTelemetry(ctx context.Context, arg GetObserverTelem
&i.ID,
&i.ReportedAt,
&i.BatteryVoltageMv,
&i.AirtimeTxPct,
&i.AirtimeRxPct,
&i.AirtimeTxSecs,
&i.AirtimeRxSecs,
&i.NoiseFloorDb,
&i.UptimeSeconds,
&i.QueueLength,
@@ -962,8 +962,8 @@ SELECT
(date_trunc('day', reported_at) +
(EXTRACT(HOUR FROM reported_at)::int / $4::int) * ($4::int * interval '1 hour'))::timestamptz AS bucket,
AVG(battery_voltage_mv)::int AS battery_voltage_mv,
GREATEST(MAX(airtime_tx_pct) - MIN(airtime_tx_pct), 0)::real AS airtime_tx_pct,
GREATEST(MAX(airtime_rx_pct) - MIN(airtime_rx_pct), 0)::real AS airtime_rx_pct,
GREATEST(MAX(airtime_tx_secs) - MIN(airtime_tx_secs), 0)::real AS airtime_tx_secs,
GREATEST(MAX(airtime_rx_secs) - MIN(airtime_rx_secs), 0)::real AS airtime_rx_secs,
AVG(noise_floor_db)::real AS noise_floor_db,
MAX(uptime_seconds)::bigint AS uptime_seconds,
AVG(queue_length)::int AS queue_length,
@@ -986,8 +986,8 @@ type GetObserverTelemetryBucketedParams struct {
type GetObserverTelemetryBucketedRow struct {
Bucket pgtype.Timestamptz `json:"bucket"`
BatteryVoltageMv int32 `json:"battery_voltage_mv"`
AirtimeTxPct float32 `json:"airtime_tx_pct"`
AirtimeRxPct float32 `json:"airtime_rx_pct"`
AirtimeTxSecs float32 `json:"airtime_tx_secs"`
AirtimeRxSecs float32 `json:"airtime_rx_secs"`
NoiseFloorDb float32 `json:"noise_floor_db"`
UptimeSeconds int64 `json:"uptime_seconds"`
QueueLength int32 `json:"queue_length"`
@@ -1011,8 +1011,8 @@ func (q *Queries) GetObserverTelemetryBucketed(ctx context.Context, arg GetObser
if err := rows.Scan(
&i.Bucket,
&i.BatteryVoltageMv,
&i.AirtimeTxPct,
&i.AirtimeRxPct,
&i.AirtimeTxSecs,
&i.AirtimeRxSecs,
&i.NoiseFloorDb,
&i.UptimeSeconds,
&i.QueueLength,
@@ -2016,8 +2016,8 @@ func (q *Queries) InsertObservation(ctx context.Context, arg InsertObservationPa
const insertObserverTelemetry = `-- name: InsertObserverTelemetry :exec
INSERT INTO observer_telemetry (
observer_id, reported_at, battery_voltage_mv, airtime_tx_pct,
airtime_rx_pct, noise_floor_db, uptime_seconds, queue_length,
observer_id, reported_at, battery_voltage_mv, airtime_tx_secs,
airtime_rx_secs, noise_floor_db, uptime_seconds, queue_length,
debug_flags, receive_errors
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
ON CONFLICT (observer_id, reported_at) DO NOTHING
@@ -2027,8 +2027,8 @@ type InsertObserverTelemetryParams struct {
ObserverID uuid.UUID `json:"observer_id"`
ReportedAt pgtype.Timestamptz `json:"reported_at"`
BatteryVoltageMv *int32 `json:"battery_voltage_mv"`
AirtimeTxPct *float32 `json:"airtime_tx_pct"`
AirtimeRxPct *float32 `json:"airtime_rx_pct"`
AirtimeTxSecs *float32 `json:"airtime_tx_secs"`
AirtimeRxSecs *float32 `json:"airtime_rx_secs"`
NoiseFloorDb *float32 `json:"noise_floor_db"`
UptimeSeconds *int64 `json:"uptime_seconds"`
QueueLength *int32 `json:"queue_length"`
@@ -2043,8 +2043,8 @@ func (q *Queries) InsertObserverTelemetry(ctx context.Context, arg InsertObserve
arg.ObserverID,
arg.ReportedAt,
arg.BatteryVoltageMv,
arg.AirtimeTxPct,
arg.AirtimeRxPct,
arg.AirtimeTxSecs,
arg.AirtimeRxSecs,
arg.NoiseFloorDb,
arg.UptimeSeconds,
arg.QueueLength,
+2 -2
View File
@@ -3204,10 +3204,10 @@ const docTemplate = `{
"github_com_MeshCore-Beacon_beacon-server_internal_api.ObserverTelemetryPoint": {
"type": "object",
"properties": {
"airtimeRxPct": {
"airtimeRxSecs": {
"type": "number"
},
"airtimeTxPct": {
"airtimeTxSecs": {
"type": "number"
},
"batteryMv": {
+2 -2
View File
@@ -3202,10 +3202,10 @@
"github_com_MeshCore-Beacon_beacon-server_internal_api.ObserverTelemetryPoint": {
"type": "object",
"properties": {
"airtimeRxPct": {
"airtimeRxSecs": {
"type": "number"
},
"airtimeTxPct": {
"airtimeTxSecs": {
"type": "number"
},
"batteryMv": {
+2 -2
View File
@@ -576,9 +576,9 @@ definitions:
type: object
github_com_MeshCore-Beacon_beacon-server_internal_api.ObserverTelemetryPoint:
properties:
airtimeRxPct:
airtimeRxSecs:
type: number
airtimeTxPct:
airtimeTxSecs:
type: number
batteryMv:
type: integer
+3 -2
View File
@@ -49,11 +49,12 @@ type Observer struct {
}
// ObserverTelemetryPoint is a single telemetry snapshot for an observer.
// Airtime is radio seconds: cumulative since boot on 1h points, per-bucket delta on 6h/24h.
type ObserverTelemetryPoint struct {
T int64 `json:"t"` // epoch ms
BatteryMV *int32 `json:"batteryMv,omitempty"`
AirtimeTxPct *float32 `json:"airtimeTxPct,omitempty"`
AirtimeRxPct *float32 `json:"airtimeRxPct,omitempty"`
AirtimeTxSecs *float32 `json:"airtimeTxSecs,omitempty"`
AirtimeRxSecs *float32 `json:"airtimeRxSecs,omitempty"`
NoiseFloorDB *float32 `json:"noiseFloorDb,omitempty"`
UptimeSeconds *int64 `json:"uptimeSeconds,omitempty"`
QueueLength *int32 `json:"queueLength,omitempty"`