Skip to content

Commit 49edc01

Browse files
Copilotkylegordon
andcommitted
Fix battery percentage calculation (3600mV=0%, 4100mV=100%)
Co-authored-by: kylegordon <231528+kylegordon@users.noreply.github.com>
1 parent 8cbd154 commit 49edc01

4 files changed

Lines changed: 61 additions & 21 deletions

File tree

custom_components/pettracer/device_tracker.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,16 +156,16 @@ def battery_level(self) -> int | None:
156156
"""Return the battery level of the device."""
157157
device = self._get_device_data()
158158
if device and device.bat:
159-
# Convert from millivolts to percentage (rough estimate)
160-
# Typical LiPo: 4.2V full, 3.0V empty
161-
# 4200mV = 100%, 3000mV = 0%
159+
# Convert from millivolts to percentage
160+
# Based on actual PetTracer device behavior:
161+
# 4100mV = 100%, 3600mV = 0%
162162
mv = device.bat
163-
if mv >= 4200:
163+
if mv >= 4100:
164164
return 100
165-
elif mv <= 3000:
165+
elif mv <= 3600:
166166
return 0
167167
else:
168-
return int(((mv - 3000) / 1200) * 100)
168+
return int(((mv - 3600) / 500) * 100)
169169
return None
170170

171171
@property

custom_components/pettracer/sensor.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,16 @@ def native_value(self) -> int | None:
131131
"""Return the state of the sensor."""
132132
device = self._get_device_data()
133133
if device and device.bat:
134-
# Convert from millivolts to percentage (rough estimate)
135-
# Typical LiPo: 4.2V full, 3.0V empty
136-
# 4200mV = 100%, 3000mV = 0%
134+
# Convert from millivolts to percentage
135+
# Based on actual PetTracer device behavior:
136+
# 4100mV = 100%, 3600mV = 0%
137137
mv = device.bat
138-
if mv >= 4200:
138+
if mv >= 4100:
139139
return 100
140-
elif mv <= 3000:
140+
elif mv <= 3600:
141141
return 0
142142
else:
143-
return int(((mv - 3000) / 1200) * 100)
143+
return int(((mv - 3600) / 500) * 100)
144144
return None
145145

146146

tests/test_device_tracker.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,20 @@ async def test_device_tracker_battery_conversion(hass, mock_device):
7878
coordinator = MagicMock()
7979
coordinator.data = {"devices": [mock_device]}
8080

81-
# Test with 4100mV (mid-range)
81+
# Test with 4100mV (full battery)
8282
mock_device.bat = 4100
8383
tracker = PetTracerDeviceTracker(coordinator, mock_device)
8484
battery = tracker.battery_level
85-
assert battery is not None
86-
assert 80 <= battery <= 95
85+
assert battery == 100
8786

88-
# Test with full battery (4200mV)
87+
# Test with above max (4200mV should cap at 100%)
8988
mock_device.bat = 4200
9089
coordinator.data = {"devices": [mock_device]}
9190
battery = tracker.battery_level
9291
assert battery == 100
9392

94-
# Test with low battery (3000mV)
95-
mock_device.bat = 3000
93+
# Test with low battery (3600mV = 0%)
94+
mock_device.bat = 3600
9695
coordinator.data = {"devices": [mock_device]}
9796
battery = tracker.battery_level
9897
assert battery == 0

tests/test_sensor.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,9 @@ async def test_battery_sensor(hass, mock_device):
8585
assert sensor.native_unit_of_measurement == "%"
8686
assert sensor.state_class == SensorStateClass.MEASUREMENT
8787

88-
# Test battery conversion (4100mV should be around 91%)
88+
# Test battery conversion (4100mV should be 100%)
8989
battery = sensor.native_value
90-
assert battery is not None
91-
assert 80 <= battery <= 95
90+
assert battery == 100
9291

9392

9493
async def test_battery_voltage_sensor(hass, mock_device):
@@ -422,3 +421,45 @@ async def test_sensor_no_details(hass):
422421

423422
device_info = sensor.device_info
424423
assert device_info["sw_version"] is None
424+
425+
426+
async def test_battery_percentage_edge_cases(hass, mock_device):
427+
"""Test battery percentage calculation with edge cases."""
428+
from custom_components.pettracer.sensor import PetTracerBatterySensor
429+
430+
coordinator = MagicMock()
431+
coordinator.data = {"devices": [mock_device]}
432+
433+
sensor = PetTracerBatterySensor(coordinator, mock_device)
434+
435+
# Test minimum voltage (3600mV = 0%)
436+
mock_device.bat = 3600
437+
assert sensor.native_value == 0
438+
439+
# Test maximum voltage (4100mV = 100%)
440+
mock_device.bat = 4100
441+
assert sensor.native_value == 100
442+
443+
# Test below minimum (should cap at 0%)
444+
mock_device.bat = 3500
445+
assert sensor.native_value == 0
446+
447+
# Test above maximum (should cap at 100%)
448+
mock_device.bat = 4200
449+
assert sensor.native_value == 100
450+
451+
# Test mid-range (3850mV = 50%)
452+
mock_device.bat = 3850
453+
assert sensor.native_value == 50
454+
455+
# Test 3800mV (should be 40%)
456+
mock_device.bat = 3800
457+
assert sensor.native_value == 40
458+
459+
# Test 3900mV (should be 60%)
460+
mock_device.bat = 3900
461+
assert sensor.native_value == 60
462+
463+
# Test 4000mV (should be 80%)
464+
mock_device.bat = 4000
465+
assert sensor.native_value == 80

0 commit comments

Comments
 (0)