From 589d1a2faba757797520472d80b9e1235f9f5cdf Mon Sep 17 00:00:00 2001 From: Jaime Roldan Date: Mon, 20 Apr 2026 19:45:07 -0500 Subject: [PATCH 1/2] fix(telemetry): stop emitting -0.001V sentinel when battery unavailable (#7958) --- src/modules/Telemetry/DeviceTelemetry.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 1c2d18c717c..1d6124d2c64 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -99,17 +99,21 @@ meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry() t.variant.device_metrics.has_air_util_tx = true; t.variant.device_metrics.has_battery_level = true; t.variant.device_metrics.has_channel_utilization = true; - t.variant.device_metrics.has_voltage = true; t.variant.device_metrics.has_uptime_seconds = true; - t.variant.device_metrics.air_util_tx = airTime->utilizationTXPercent(); t.variant.device_metrics.battery_level = (!powerStatus->getHasBattery() || powerStatus->getIsCharging()) ? MAGIC_USB_BATTERY_LEVEL : powerStatus->getBatteryChargePercent(); t.variant.device_metrics.channel_utilization = airTime->channelUtilizationPercent(); - t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0; + // Only populate voltage when we actually have a battery reading. Previously this assigned + // -0.001 (from -1 mV / 1000) whenever the ADC returned -1, leaking a sentinel onto the wire + // that clients then displayed as a real negative voltage. See GH #7958. + uint16_t batteryMv = powerStatus->getBatteryVoltageMv(); + if (powerStatus->getHasBattery() && batteryMv > 0) { + t.variant.device_metrics.has_voltage = true; + t.variant.device_metrics.voltage = batteryMv / 1000.0f; + } t.variant.device_metrics.uptime_seconds = getUptimeSeconds(); - return t; } From a0a822f8fced80d717cf1589ccc008f0b94a4e22 Mon Sep 17 00:00:00 2001 From: Jaime Roldan Date: Tue, 21 Apr 2026 10:10:33 -0500 Subject: [PATCH 2/2] address review: use int32_t for batteryMv to avoid uint16_t signed wrap --- src/modules/Telemetry/DeviceTelemetry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 1d6124d2c64..f1a0b8c67a7 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -108,7 +108,7 @@ meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry() // Only populate voltage when we actually have a battery reading. Previously this assigned // -0.001 (from -1 mV / 1000) whenever the ADC returned -1, leaking a sentinel onto the wire // that clients then displayed as a real negative voltage. See GH #7958. - uint16_t batteryMv = powerStatus->getBatteryVoltageMv(); + int32_t batteryMv = powerStatus->getBatteryVoltageMv(); if (powerStatus->getHasBattery() && batteryMv > 0) { t.variant.device_metrics.has_voltage = true; t.variant.device_metrics.voltage = batteryMv / 1000.0f;