mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
LaCrosse View new endpoint (#137284)
* Switch to new endpoint in LaCrosse View * Coverage * Avoid merge conflict * Switch to UpdateFailed
This commit is contained in:
parent
73ad4caf94
commit
efe7050030
@ -10,8 +10,8 @@ from lacrosse_view import HTTPError, LaCrosse, Location, LoginError, Sensor
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import SCAN_INTERVAL
|
||||
|
||||
@ -26,6 +26,7 @@ class LaCrosseUpdateCoordinator(DataUpdateCoordinator[list[Sensor]]):
|
||||
name: str
|
||||
id: str
|
||||
hass: HomeAssistant
|
||||
devices: list[Sensor] | None = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -60,24 +61,34 @@ class LaCrosseUpdateCoordinator(DataUpdateCoordinator[list[Sensor]]):
|
||||
except LoginError as error:
|
||||
raise ConfigEntryAuthFailed from error
|
||||
|
||||
if self.devices is None:
|
||||
_LOGGER.debug("Getting devices")
|
||||
try:
|
||||
self.devices = await self.api.get_devices(
|
||||
location=Location(id=self.id, name=self.name),
|
||||
)
|
||||
except HTTPError as error:
|
||||
raise UpdateFailed from error
|
||||
|
||||
try:
|
||||
# Fetch last hour of data
|
||||
sensors = await self.api.get_sensors(
|
||||
location=Location(id=self.id, name=self.name),
|
||||
tz=self.hass.config.time_zone,
|
||||
start=str(now - 3600),
|
||||
end=str(now),
|
||||
)
|
||||
except HTTPError as error:
|
||||
raise ConfigEntryNotReady from error
|
||||
for sensor in self.devices:
|
||||
sensor.data = (
|
||||
await self.api.get_sensor_status(
|
||||
sensor=sensor,
|
||||
tz=self.hass.config.time_zone,
|
||||
)
|
||||
)["data"]["current"]
|
||||
_LOGGER.debug("Got data: %s", sensor.data)
|
||||
|
||||
_LOGGER.debug("Got data: %s", sensors)
|
||||
except HTTPError as error:
|
||||
raise UpdateFailed from error
|
||||
|
||||
# Verify that we have permission to read the sensors
|
||||
for sensor in sensors:
|
||||
for sensor in self.devices:
|
||||
if not sensor.permissions.get("read", False):
|
||||
raise ConfigEntryAuthFailed(
|
||||
f"This account does not have permission to read {sensor.name}"
|
||||
)
|
||||
|
||||
return sensors
|
||||
return self.devices
|
||||
|
@ -48,7 +48,7 @@ def get_value(sensor: Sensor, field: str) -> float | int | str | None:
|
||||
field_data = sensor.data.get(field)
|
||||
if field_data is None:
|
||||
return None
|
||||
value = field_data["values"][-1]["s"]
|
||||
value = field_data["spot"]["value"]
|
||||
try:
|
||||
value = float(value)
|
||||
except ValueError:
|
||||
|
@ -15,7 +15,13 @@ TEST_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["Temperature"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={"Temperature": {"values": [{"s": "2"}], "unit": "degrees_celsius"}},
|
||||
data={
|
||||
"data": {
|
||||
"current": {
|
||||
"Temperature": {"spot": {"value": "2"}, "unit": "degrees_celsius"}
|
||||
}
|
||||
}
|
||||
},
|
||||
permissions={"read": True},
|
||||
model="Test",
|
||||
)
|
||||
@ -26,7 +32,13 @@ TEST_NO_PERMISSION_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["Temperature"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={"Temperature": {"values": [{"s": "2"}], "unit": "degrees_celsius"}},
|
||||
data={
|
||||
"data": {
|
||||
"current": {
|
||||
"Temperature": {"spot": {"value": "2"}, "unit": "degrees_celsius"}
|
||||
}
|
||||
}
|
||||
},
|
||||
permissions={"read": False},
|
||||
model="Test",
|
||||
)
|
||||
@ -37,7 +49,16 @@ TEST_UNSUPPORTED_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["SomeUnsupportedField"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={"SomeUnsupportedField": {"values": [{"s": "2"}], "unit": "degrees_celsius"}},
|
||||
data={
|
||||
"data": {
|
||||
"current": {
|
||||
"SomeUnsupportedField": {
|
||||
"spot": {"value": "2"},
|
||||
"unit": "degrees_celsius",
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
permissions={"read": True},
|
||||
model="Test",
|
||||
)
|
||||
@ -48,7 +69,13 @@ TEST_FLOAT_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["Temperature"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={"Temperature": {"values": [{"s": "2.3"}], "unit": "degrees_celsius"}},
|
||||
data={
|
||||
"data": {
|
||||
"current": {
|
||||
"Temperature": {"spot": {"value": "2.3"}, "unit": "degrees_celsius"}
|
||||
}
|
||||
}
|
||||
},
|
||||
permissions={"read": True},
|
||||
model="Test",
|
||||
)
|
||||
@ -59,7 +86,9 @@ TEST_STRING_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["WetDry"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={"WetDry": {"values": [{"s": "dry"}], "unit": "wet_dry"}},
|
||||
data={
|
||||
"data": {"current": {"WetDry": {"spot": {"value": "dry"}, "unit": "wet_dry"}}}
|
||||
},
|
||||
permissions={"read": True},
|
||||
model="Test",
|
||||
)
|
||||
@ -70,7 +99,13 @@ TEST_ALREADY_FLOAT_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["HeatIndex"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={"HeatIndex": {"values": [{"s": 2.3}], "unit": "degrees_fahrenheit"}},
|
||||
data={
|
||||
"data": {
|
||||
"current": {
|
||||
"HeatIndex": {"spot": {"value": 2.3}, "unit": "degrees_fahrenheit"}
|
||||
}
|
||||
}
|
||||
},
|
||||
permissions={"read": True},
|
||||
model="Test",
|
||||
)
|
||||
@ -81,7 +116,13 @@ TEST_ALREADY_INT_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["WindSpeed"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={"WindSpeed": {"values": [{"s": 2}], "unit": "kilometers_per_hour"}},
|
||||
data={
|
||||
"data": {
|
||||
"current": {
|
||||
"WindSpeed": {"spot": {"value": 2}, "unit": "kilometers_per_hour"}
|
||||
}
|
||||
}
|
||||
},
|
||||
permissions={"read": True},
|
||||
model="Test",
|
||||
)
|
||||
@ -92,7 +133,7 @@ TEST_NO_FIELD_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["Temperature"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={},
|
||||
data={"data": {"current": {}}},
|
||||
permissions={"read": True},
|
||||
model="Test",
|
||||
)
|
||||
@ -103,7 +144,7 @@ TEST_MISSING_FIELD_DATA_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["Temperature"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={"Temperature": None},
|
||||
data={"data": {"current": {"Temperature": None}}},
|
||||
permissions={"read": True},
|
||||
model="Test",
|
||||
)
|
||||
@ -114,7 +155,13 @@ TEST_UNITS_OVERRIDE_SENSOR = Sensor(
|
||||
sensor_id="2",
|
||||
sensor_field_names=["Temperature"],
|
||||
location=Location(id="1", name="Test"),
|
||||
data={"Temperature": {"values": [{"s": "2.1"}], "unit": "degrees_fahrenheit"}},
|
||||
data={
|
||||
"data": {
|
||||
"current": {
|
||||
"Temperature": {"spot": {"value": "2.1"}, "unit": "degrees_fahrenheit"}
|
||||
}
|
||||
}
|
||||
},
|
||||
permissions={"read": True},
|
||||
model="Test",
|
||||
)
|
||||
|
@ -4,7 +4,7 @@
|
||||
'coordinator_data': list([
|
||||
dict({
|
||||
'__type': "<class 'lacrosse_view.Sensor'>",
|
||||
'repr': "Sensor(name='Test', device_id='1', type='Test', sensor_id='2', sensor_field_names=['Temperature'], location=Location(id='1', name='Test'), permissions={'read': True}, model='Test', data={'Temperature': {'values': [{'s': '2'}], 'unit': 'degrees_celsius'}})",
|
||||
'repr': "Sensor(name='Test', device_id='1', type='Test', sensor_id='2', sensor_field_names=['Temperature'], location=Location(id='1', name='Test'), permissions={'read': True}, model='Test', data={'Temperature': {'spot': {'value': '2'}, 'unit': 'degrees_celsius'}})",
|
||||
}),
|
||||
]),
|
||||
'entry': dict({
|
||||
|
@ -26,9 +26,14 @@ async def test_entry_diagnostics(
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = TEST_SENSOR.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True),
|
||||
patch("lacrosse_view.LaCrosse.get_sensors", return_value=[TEST_SENSOR]),
|
||||
patch("lacrosse_view.LaCrosse.get_devices", return_value=[sensor]),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -20,12 +20,17 @@ async def test_unload_entry(hass: HomeAssistant) -> None:
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = TEST_SENSOR.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True),
|
||||
patch(
|
||||
"lacrosse_view.LaCrosse.get_sensors",
|
||||
return_value=[TEST_SENSOR],
|
||||
"lacrosse_view.LaCrosse.get_devices",
|
||||
return_value=[sensor],
|
||||
),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -68,7 +73,7 @@ async def test_http_error(hass: HomeAssistant) -> None:
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True),
|
||||
patch("lacrosse_view.LaCrosse.get_sensors", side_effect=HTTPError),
|
||||
patch("lacrosse_view.LaCrosse.get_devices", side_effect=HTTPError),
|
||||
):
|
||||
assert not await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -84,12 +89,17 @@ async def test_new_token(hass: HomeAssistant, freezer: FrozenDateTimeFactory) ->
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = TEST_SENSOR.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True) as login,
|
||||
patch(
|
||||
"lacrosse_view.LaCrosse.get_sensors",
|
||||
return_value=[TEST_SENSOR],
|
||||
"lacrosse_view.LaCrosse.get_devices",
|
||||
return_value=[sensor],
|
||||
),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -103,7 +113,7 @@ async def test_new_token(hass: HomeAssistant, freezer: FrozenDateTimeFactory) ->
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True) as login,
|
||||
patch(
|
||||
"lacrosse_view.LaCrosse.get_sensors",
|
||||
"lacrosse_view.LaCrosse.get_devices",
|
||||
return_value=[TEST_SENSOR],
|
||||
),
|
||||
):
|
||||
@ -121,12 +131,17 @@ async def test_failed_token(
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = TEST_SENSOR.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True) as login,
|
||||
patch(
|
||||
"lacrosse_view.LaCrosse.get_sensors",
|
||||
return_value=[TEST_SENSOR],
|
||||
"lacrosse_view.LaCrosse.get_devices",
|
||||
return_value=[sensor],
|
||||
),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -32,9 +32,14 @@ async def test_entities_added(hass: HomeAssistant) -> None:
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = TEST_SENSOR.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True),
|
||||
patch("lacrosse_view.LaCrosse.get_sensors", return_value=[TEST_SENSOR]),
|
||||
patch("lacrosse_view.LaCrosse.get_devices", return_value=[sensor]),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -54,12 +59,17 @@ async def test_sensor_permission(
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = TEST_NO_PERMISSION_SENSOR.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True),
|
||||
patch(
|
||||
"lacrosse_view.LaCrosse.get_sensors",
|
||||
return_value=[TEST_NO_PERMISSION_SENSOR],
|
||||
"lacrosse_view.LaCrosse.get_devices",
|
||||
return_value=[sensor],
|
||||
),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert not await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -79,11 +89,14 @@ async def test_field_not_supported(
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = TEST_UNSUPPORTED_SENSOR.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True),
|
||||
patch(
|
||||
"lacrosse_view.LaCrosse.get_sensors", return_value=[TEST_UNSUPPORTED_SENSOR]
|
||||
),
|
||||
patch("lacrosse_view.LaCrosse.get_devices", return_value=[sensor]),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -114,12 +127,17 @@ async def test_field_types(
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = test_input.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True),
|
||||
patch(
|
||||
"lacrosse_view.LaCrosse.get_sensors",
|
||||
"lacrosse_view.LaCrosse.get_devices",
|
||||
return_value=[test_input],
|
||||
),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -137,12 +155,17 @@ async def test_no_field(hass: HomeAssistant, caplog: pytest.LogCaptureFixture) -
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = TEST_NO_FIELD_SENSOR.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True),
|
||||
patch(
|
||||
"lacrosse_view.LaCrosse.get_sensors",
|
||||
return_value=[TEST_NO_FIELD_SENSOR],
|
||||
"lacrosse_view.LaCrosse.get_devices",
|
||||
return_value=[sensor],
|
||||
),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -160,12 +183,17 @@ async def test_field_data_missing(hass: HomeAssistant) -> None:
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_ENTRY_DATA)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
sensor = TEST_MISSING_FIELD_DATA_SENSOR.model_copy()
|
||||
status = sensor.data
|
||||
sensor.data = None
|
||||
|
||||
with (
|
||||
patch("lacrosse_view.LaCrosse.login", return_value=True),
|
||||
patch(
|
||||
"lacrosse_view.LaCrosse.get_sensors",
|
||||
return_value=[TEST_MISSING_FIELD_DATA_SENSOR],
|
||||
"lacrosse_view.LaCrosse.get_devices",
|
||||
return_value=[sensor],
|
||||
),
|
||||
patch("lacrosse_view.LaCrosse.get_sensor_status", return_value=status),
|
||||
):
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
Loading…
x
Reference in New Issue
Block a user