From cc108f2f4900c2db3dc0a03607a0366fc091d030 Mon Sep 17 00:00:00 2001 From: l5y <220195275+l5yth@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:18:10 +0100 Subject: [PATCH] web: fix telemetry api to return current in amperes (#541) * web: fix telemetry api to return current in amperes * web: address review comments --- web/lib/potato_mesh/application/queries.rb | 12 +++++++- web/spec/app_spec.rb | 32 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/web/lib/potato_mesh/application/queries.rb b/web/lib/potato_mesh/application/queries.rb index 84a973f..16393af 100644 --- a/web/lib/potato_mesh/application/queries.rb +++ b/web/lib/potato_mesh/application/queries.rb @@ -48,6 +48,9 @@ module PotatoMesh soil_moisture soil_temperature ].freeze + TELEMETRY_AGGREGATE_SCALERS = { + "current" => 0.001, + }.freeze # Remove nil or empty values from an API response hash to reduce payload size # while preserving legitimate zero-valued measurements. @@ -479,7 +482,8 @@ module PotatoMesh r["relative_humidity"] = coerce_float(r["relative_humidity"]) r["barometric_pressure"] = coerce_float(r["barometric_pressure"]) r["gas_resistance"] = coerce_float(r["gas_resistance"]) - r["current"] = coerce_float(r["current"]) + current_ma = coerce_float(r["current"]) + r["current"] = current_ma.nil? ? nil : current_ma / 1000.0 r["iaq"] = coerce_integer(r["iaq"]) r["distance"] = coerce_float(r["distance"]) r["lux"] = coerce_float(r["lux"]) @@ -549,6 +553,12 @@ module PotatoMesh avg = coerce_float(row["#{column}_avg"]) min_value = coerce_float(row["#{column}_min"]) max_value = coerce_float(row["#{column}_max"]) + scale = TELEMETRY_AGGREGATE_SCALERS[column] + if scale + avg *= scale unless avg.nil? + min_value *= scale unless min_value.nil? + max_value *= scale unless max_value.nil? + end metrics = {} metrics["avg"] = avg unless avg.nil? diff --git a/web/spec/app_spec.rb b/web/spec/app_spec.rb index 1ec942c..b30737b 100644 --- a/web/spec/app_spec.rb +++ b/web/spec/app_spec.rb @@ -4434,7 +4434,8 @@ RSpec.describe "Potato Mesh Sinatra app" do expect(first_entry["telemetry_time_iso"]).to eq(Time.at(latest["telemetry_time"]).utc.iso8601) expect(first_entry).not_to have_key("device_metrics") expect_same_value(first_entry["battery_level"], telemetry_metric(latest, "battery_level")) - expect_same_value(first_entry["current"], telemetry_metric(latest, "current")) + expected_current = telemetry_metric(latest, "current") + expect_same_value(first_entry["current"], expected_current.nil? ? nil : expected_current / 1000.0) expect_same_value(first_entry["distance"], telemetry_metric(latest, "distance")) expect_same_value(first_entry["lux"], telemetry_metric(latest, "lux")) expect_same_value(first_entry["wind_direction"], telemetry_metric(latest, "wind_direction")) @@ -4576,6 +4577,35 @@ RSpec.describe "Potato Mesh Sinatra app" do expect(a_bucket["aggregates"]).to have_key("battery_level") expect(a_bucket["aggregates"]["battery_level"]).to include("avg") expect(a_bucket).not_to have_key("device_metrics") + + buckets_by_start = {} + buckets.each do |bucket| + start_time = bucket["bucket_start"] + buckets_by_start[start_time] = bucket if start_time + end + bucket_seconds = 300 + current_by_bucket = Hash.new { |hash, key| hash[key] = [] } + telemetry_fixture.each do |entry| + timestamp = entry["rx_time"] || entry["telemetry_time"] + next unless timestamp + + bucket_start = (timestamp / bucket_seconds) * bucket_seconds + current_value = telemetry_metric(entry, "current") + next if current_value.nil? + + current_by_bucket[bucket_start] << current_value + end + + current_by_bucket.each do |bucket_start, values| + bucket = buckets_by_start[bucket_start] + next unless bucket + aggregates = bucket.fetch("aggregates", {}) + metrics = aggregates["current"] + expect(metrics).not_to be_nil + expect_same_value(metrics["avg"], values.sum / values.length / 1000.0) + expect_same_value(metrics["min"], values.min / 1000.0) + expect_same_value(metrics["max"], values.max / 1000.0) + end end it "applies default window and bucket sizes when parameters are omitted" do