Add Starlink consumption sensors (#132262)

This commit is contained in:
David Rapan 2024-12-09 16:19:23 +01:00 committed by GitHub
parent 49800f9aaa
commit 21a2ce6b59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 151 additions and 2 deletions

View File

@ -14,8 +14,10 @@ from starlink_grpc import (
GrpcError,
LocationDict,
ObstructionDict,
PowerDict,
StatusDict,
get_sleep_config,
history_stats,
location_data,
reboot,
set_sleep_config,
@ -39,6 +41,7 @@ class StarlinkData:
status: StatusDict
obstruction: ObstructionDict
alert: AlertDict
consumption: PowerDict
class StarlinkUpdateCoordinator(DataUpdateCoordinator[StarlinkData]):
@ -58,10 +61,11 @@ class StarlinkUpdateCoordinator(DataUpdateCoordinator[StarlinkData]):
def _get_starlink_data(self) -> StarlinkData:
"""Retrieve Starlink data."""
channel_context = self.channel_context
status = status_data(channel_context)
location = location_data(channel_context)
sleep = get_sleep_config(channel_context)
return StarlinkData(location, sleep, *status)
status, obstruction, alert = status_data(channel_context)
statistics = history_stats(parse_samples=-1, context=channel_context)
return StarlinkData(location, sleep, status, obstruction, alert, statistics[-1])
async def _async_update_data(self) -> StarlinkData:
async with asyncio.timeout(4):

View File

@ -18,6 +18,8 @@ from homeassistant.const import (
PERCENTAGE,
EntityCategory,
UnitOfDataRate,
UnitOfEnergy,
UnitOfPower,
UnitOfTime,
)
from homeassistant.core import HomeAssistant
@ -120,4 +122,18 @@ SENSORS: tuple[StarlinkSensorEntityDescription, ...] = (
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda data: data.status["pop_ping_drop_rate"] * 100,
),
StarlinkSensorEntityDescription(
key="power",
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.WATT,
value_fn=lambda data: data.consumption["latest_power"],
),
StarlinkSensorEntityDescription(
key="energy",
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
value_fn=lambda data: data.consumption["total_energy"],
),
)

View File

@ -0,0 +1,112 @@
[
{
"samples": 900,
"end_counter": 119395
},
{
"total_ping_drop": 2.4592087380588055,
"count_full_ping_drop": 0,
"count_obstructed": 0,
"total_obstructed_ping_drop": 0,
"count_full_obstructed_ping_drop": 0,
"count_unscheduled": 0,
"total_unscheduled_ping_drop": 0,
"count_full_unscheduled_ping_drop": 0
},
{
"init_run_fragment": 0,
"final_run_fragment": 0,
"run_seconds[1,]": [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
],
"run_minutes[1,]": [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
]
},
{
"mean_all_ping_latency": 31.55747121333472,
"deciles_all_ping_latency[]": [
21.005102157592773, 22.67989158630371, 25.310760498046875,
26.85667610168457, 27.947458267211914, 29.192155838012695,
31.26323890686035, 34.226768493652344, 38.54373550415039,
42.308048248291016, 60.11151885986328
],
"mean_full_ping_latency": 31.526783029284427,
"deciles_full_ping_latency[]": [
21.070240020751953, 22.841461181640625, 25.34041976928711,
26.908039093017578, 27.947458267211914, 29.135879516601562,
31.122955322265625, 34.1280403137207, 38.49388122558594,
42.308048248291016, 60.11151885986328
],
"stdev_full_ping_latency": 7.8141330200011785
},
{
"load_bucket_samples[]": [738, 24, 39, 55, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"load_bucket_min_latency[]": [
21.070240020751953,
21.35713768005371,
21.156545639038086,
24.763751983642578,
24.7109317779541,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
"load_bucket_median_latency[]": [
29.2450590133667,
27.031108856201172,
25.726211547851562,
31.845806121826172,
28.919479370117188,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
"load_bucket_max_latency[]": [
60.11151885986328,
40.572628021240234,
48.063961029052734,
53.505126953125,
38.7435302734375,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
},
{
"download_usage": 72504227,
"upload_usage": 5719755
},
{
"latest_power": 27.54502296447754,
"mean_power": 31.449254739549424,
"min_power": 21.826229095458984,
"max_power": 41.71160888671875,
"total_energy": 0.007862313684887356
}
]

View File

@ -24,6 +24,11 @@ SLEEP_DATA_SUCCESS_PATCHER = patch(
return_value=json.loads(load_fixture("sleep_data_success.json", "starlink")),
)
HISTORY_STATS_SUCCESS_PATCHER = patch(
"homeassistant.components.starlink.coordinator.history_stats",
return_value=json.loads(load_fixture("history_stats_success.json", "starlink")),
)
DEVICE_FOUND_PATCHER = patch(
"homeassistant.components.starlink.config_flow.get_id", return_value="some-valid-id"
)

View File

@ -16,6 +16,13 @@
'alert_thermal_throttle': False,
'alert_unexpected_location': False,
}),
'consumption': dict({
'latest_power': 27.54502296447754,
'max_power': 41.71160888671875,
'mean_power': 31.449254739549424,
'min_power': 21.826229095458984,
'total_energy': 0.007862313684887356,
}),
'location': dict({
'altitude': '**REDACTED**',
'latitude': '**REDACTED**',

View File

@ -7,6 +7,7 @@ from homeassistant.const import CONF_IP_ADDRESS
from homeassistant.core import HomeAssistant
from .patchers import (
HISTORY_STATS_SUCCESS_PATCHER,
LOCATION_DATA_SUCCESS_PATCHER,
SLEEP_DATA_SUCCESS_PATCHER,
STATUS_DATA_SUCCESS_PATCHER,
@ -32,6 +33,7 @@ async def test_diagnostics(
STATUS_DATA_SUCCESS_PATCHER,
LOCATION_DATA_SUCCESS_PATCHER,
SLEEP_DATA_SUCCESS_PATCHER,
HISTORY_STATS_SUCCESS_PATCHER,
):
entry.add_to_hass(hass)

View File

@ -6,6 +6,7 @@ from homeassistant.const import CONF_IP_ADDRESS
from homeassistant.core import HomeAssistant
from .patchers import (
HISTORY_STATS_SUCCESS_PATCHER,
LOCATION_DATA_SUCCESS_PATCHER,
SLEEP_DATA_SUCCESS_PATCHER,
STATUS_DATA_SUCCESS_PATCHER,
@ -25,6 +26,7 @@ async def test_successful_entry(hass: HomeAssistant) -> None:
STATUS_DATA_SUCCESS_PATCHER,
LOCATION_DATA_SUCCESS_PATCHER,
SLEEP_DATA_SUCCESS_PATCHER,
HISTORY_STATS_SUCCESS_PATCHER,
):
entry.add_to_hass(hass)
@ -46,6 +48,7 @@ async def test_unload_entry(hass: HomeAssistant) -> None:
STATUS_DATA_SUCCESS_PATCHER,
LOCATION_DATA_SUCCESS_PATCHER,
SLEEP_DATA_SUCCESS_PATCHER,
HISTORY_STATS_SUCCESS_PATCHER,
):
entry.add_to_hass(hass)