mirror of
https://github.com/home-assistant/core.git
synced 2025-07-07 21:37:07 +00:00
Add Starlink consumption sensors (#132262)
This commit is contained in:
parent
49800f9aaa
commit
21a2ce6b59
@ -14,8 +14,10 @@ from starlink_grpc import (
|
|||||||
GrpcError,
|
GrpcError,
|
||||||
LocationDict,
|
LocationDict,
|
||||||
ObstructionDict,
|
ObstructionDict,
|
||||||
|
PowerDict,
|
||||||
StatusDict,
|
StatusDict,
|
||||||
get_sleep_config,
|
get_sleep_config,
|
||||||
|
history_stats,
|
||||||
location_data,
|
location_data,
|
||||||
reboot,
|
reboot,
|
||||||
set_sleep_config,
|
set_sleep_config,
|
||||||
@ -39,6 +41,7 @@ class StarlinkData:
|
|||||||
status: StatusDict
|
status: StatusDict
|
||||||
obstruction: ObstructionDict
|
obstruction: ObstructionDict
|
||||||
alert: AlertDict
|
alert: AlertDict
|
||||||
|
consumption: PowerDict
|
||||||
|
|
||||||
|
|
||||||
class StarlinkUpdateCoordinator(DataUpdateCoordinator[StarlinkData]):
|
class StarlinkUpdateCoordinator(DataUpdateCoordinator[StarlinkData]):
|
||||||
@ -58,10 +61,11 @@ class StarlinkUpdateCoordinator(DataUpdateCoordinator[StarlinkData]):
|
|||||||
def _get_starlink_data(self) -> StarlinkData:
|
def _get_starlink_data(self) -> StarlinkData:
|
||||||
"""Retrieve Starlink data."""
|
"""Retrieve Starlink data."""
|
||||||
channel_context = self.channel_context
|
channel_context = self.channel_context
|
||||||
status = status_data(channel_context)
|
|
||||||
location = location_data(channel_context)
|
location = location_data(channel_context)
|
||||||
sleep = get_sleep_config(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 def _async_update_data(self) -> StarlinkData:
|
||||||
async with asyncio.timeout(4):
|
async with asyncio.timeout(4):
|
||||||
|
@ -18,6 +18,8 @@ from homeassistant.const import (
|
|||||||
PERCENTAGE,
|
PERCENTAGE,
|
||||||
EntityCategory,
|
EntityCategory,
|
||||||
UnitOfDataRate,
|
UnitOfDataRate,
|
||||||
|
UnitOfEnergy,
|
||||||
|
UnitOfPower,
|
||||||
UnitOfTime,
|
UnitOfTime,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -120,4 +122,18 @@ SENSORS: tuple[StarlinkSensorEntityDescription, ...] = (
|
|||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
value_fn=lambda data: data.status["pop_ping_drop_rate"] * 100,
|
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"],
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
112
tests/components/starlink/fixtures/history_stats_success.json
Normal file
112
tests/components/starlink/fixtures/history_stats_success.json
Normal 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
|
||||||
|
}
|
||||||
|
]
|
@ -24,6 +24,11 @@ SLEEP_DATA_SUCCESS_PATCHER = patch(
|
|||||||
return_value=json.loads(load_fixture("sleep_data_success.json", "starlink")),
|
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(
|
DEVICE_FOUND_PATCHER = patch(
|
||||||
"homeassistant.components.starlink.config_flow.get_id", return_value="some-valid-id"
|
"homeassistant.components.starlink.config_flow.get_id", return_value="some-valid-id"
|
||||||
)
|
)
|
||||||
|
@ -16,6 +16,13 @@
|
|||||||
'alert_thermal_throttle': False,
|
'alert_thermal_throttle': False,
|
||||||
'alert_unexpected_location': 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({
|
'location': dict({
|
||||||
'altitude': '**REDACTED**',
|
'altitude': '**REDACTED**',
|
||||||
'latitude': '**REDACTED**',
|
'latitude': '**REDACTED**',
|
||||||
|
@ -7,6 +7,7 @@ from homeassistant.const import CONF_IP_ADDRESS
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .patchers import (
|
from .patchers import (
|
||||||
|
HISTORY_STATS_SUCCESS_PATCHER,
|
||||||
LOCATION_DATA_SUCCESS_PATCHER,
|
LOCATION_DATA_SUCCESS_PATCHER,
|
||||||
SLEEP_DATA_SUCCESS_PATCHER,
|
SLEEP_DATA_SUCCESS_PATCHER,
|
||||||
STATUS_DATA_SUCCESS_PATCHER,
|
STATUS_DATA_SUCCESS_PATCHER,
|
||||||
@ -32,6 +33,7 @@ async def test_diagnostics(
|
|||||||
STATUS_DATA_SUCCESS_PATCHER,
|
STATUS_DATA_SUCCESS_PATCHER,
|
||||||
LOCATION_DATA_SUCCESS_PATCHER,
|
LOCATION_DATA_SUCCESS_PATCHER,
|
||||||
SLEEP_DATA_SUCCESS_PATCHER,
|
SLEEP_DATA_SUCCESS_PATCHER,
|
||||||
|
HISTORY_STATS_SUCCESS_PATCHER,
|
||||||
):
|
):
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ from homeassistant.const import CONF_IP_ADDRESS
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .patchers import (
|
from .patchers import (
|
||||||
|
HISTORY_STATS_SUCCESS_PATCHER,
|
||||||
LOCATION_DATA_SUCCESS_PATCHER,
|
LOCATION_DATA_SUCCESS_PATCHER,
|
||||||
SLEEP_DATA_SUCCESS_PATCHER,
|
SLEEP_DATA_SUCCESS_PATCHER,
|
||||||
STATUS_DATA_SUCCESS_PATCHER,
|
STATUS_DATA_SUCCESS_PATCHER,
|
||||||
@ -25,6 +26,7 @@ async def test_successful_entry(hass: HomeAssistant) -> None:
|
|||||||
STATUS_DATA_SUCCESS_PATCHER,
|
STATUS_DATA_SUCCESS_PATCHER,
|
||||||
LOCATION_DATA_SUCCESS_PATCHER,
|
LOCATION_DATA_SUCCESS_PATCHER,
|
||||||
SLEEP_DATA_SUCCESS_PATCHER,
|
SLEEP_DATA_SUCCESS_PATCHER,
|
||||||
|
HISTORY_STATS_SUCCESS_PATCHER,
|
||||||
):
|
):
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
@ -46,6 +48,7 @@ async def test_unload_entry(hass: HomeAssistant) -> None:
|
|||||||
STATUS_DATA_SUCCESS_PATCHER,
|
STATUS_DATA_SUCCESS_PATCHER,
|
||||||
LOCATION_DATA_SUCCESS_PATCHER,
|
LOCATION_DATA_SUCCESS_PATCHER,
|
||||||
SLEEP_DATA_SUCCESS_PATCHER,
|
SLEEP_DATA_SUCCESS_PATCHER,
|
||||||
|
HISTORY_STATS_SUCCESS_PATCHER,
|
||||||
):
|
):
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user