|
8 | 8 | from __future__ import annotations
|
9 | 9 |
|
10 | 10 | import logging
|
| 11 | +from math import tanh |
11 | 12 | from struct import Struct
|
12 | 13 |
|
13 | 14 | from bluetooth_data_tools import short_address
|
|
27 | 28 | UNPACK_TEMP_HUMID = Struct("<hB").unpack
|
28 | 29 | UNPACK_SPIKE_TEMP = Struct("<BHHH").unpack
|
29 | 30 |
|
30 |
| -TP96_MAX_BAT = 2880 |
31 |
| -TP96_MIN_BAT = 2000 # ?? |
| 31 | + |
| 32 | +# TP96x battery values appear to be a voltage reading, probably in millivolts. |
| 33 | +# This means that calculating battery life from it is a non-linear function. |
| 34 | +# Examining the curve, it looked fairly close to a curve from the tanh function. |
| 35 | +# So, I created a script to use Tensorflow to optimize an equation in the format |
| 36 | +# A*tanh(B*x+C)+D |
| 37 | +# Where A,B,C,D are the variables to optimize for. This yielded the below function |
| 38 | +def tp96_battery(voltage: int) -> float: |
| 39 | + raw = 52.317286 * tanh(voltage / 273.624277936 - 8.76485439394) + 51.06925 |
| 40 | + clamped = max(0, min(raw, 100)) |
| 41 | + return round(clamped, 2) |
32 | 42 |
|
33 | 43 |
|
34 | 44 | class ThermoProBluetoothDeviceData(BluetoothData):
|
@@ -68,22 +78,18 @@ def _start_update(self, service_info: BluetoothServiceInfo) -> None:
|
68 | 78 | return
|
69 | 79 |
|
70 | 80 | if name.startswith("TP96"):
|
71 |
| - bat_range = TP96_MAX_BAT - TP96_MIN_BAT |
72 |
| - |
73 | 81 | # TP96 has a different format
|
74 | 82 | # It has an internal temp probe and an ambient temp probe
|
75 | 83 | (
|
76 | 84 | probe_zero_indexed,
|
77 | 85 | internal_temp,
|
78 |
| - battery, |
| 86 | + battery_voltage, |
79 | 87 | ambient_temp,
|
80 | 88 | ) = UNPACK_SPIKE_TEMP(data)
|
81 | 89 | probe_one_indexed = probe_zero_indexed + 1
|
82 | 90 | internal_temp = internal_temp - 30
|
83 | 91 | ambient_temp = ambient_temp - 30
|
84 |
| - battery_percent = ((battery - TP96_MIN_BAT) / bat_range) * 100 |
85 |
| - if battery_percent > 100: |
86 |
| - battery_percent = 100 |
| 92 | + battery_percent = tp96_battery(battery_voltage) |
87 | 93 | self.update_predefined_sensor(
|
88 | 94 | SensorLibrary.TEMPERATURE__CELSIUS,
|
89 | 95 | internal_temp,
|
|
0 commit comments