Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions homeassistant/components/icloud/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,8 @@ def setup(self) -> None:
return

try:
api_devices = self.api.devices
# Gets device owners infos
user_info = api_devices.response["userInfo"]
user_info = self.api.devices.user_info
except (
PyiCloudServiceNotActivatedException,
PyiCloudNoDevicesException,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/icloud/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/icloud",
"iot_class": "cloud_polling",
"loggers": ["keyrings.alt", "pyicloud"],
"requirements": ["pyicloud==2.0.3"]
"requirements": ["pyicloud==2.1.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/knx/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ class _KnxBinarySensor(BinarySensorEntity, RestoreEntity):

async def async_added_to_hass(self) -> None:
"""Restore last state."""
await super().async_added_to_hass()
if (
last_state := await self.async_get_last_state()
) and last_state.state not in (STATE_UNKNOWN, STATE_UNAVAILABLE):
self._device.remote_value.update_value(last_state.state == STATE_ON)
await super().async_added_to_hass()

@property
def is_on(self) -> bool:
Expand Down
42 changes: 27 additions & 15 deletions homeassistant/components/knx/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
from dataclasses import dataclass
from datetime import datetime, timedelta
from functools import partial
from typing import Any

from xknx import XKNX
from xknx.core.connection_state import XknxConnectionState, XknxConnectionType
from xknx.devices import Sensor as XknxSensor
from xknx.devices import Device as XknxDevice, Sensor as XknxSensor

from homeassistant import config_entries
from homeassistant.components.sensor import (
CONF_STATE_CLASS,
RestoreSensor,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
Expand All @@ -25,6 +25,8 @@
CONF_ENTITY_CATEGORY,
CONF_NAME,
CONF_TYPE,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
EntityCategory,
Platform,
)
Expand Down Expand Up @@ -141,7 +143,7 @@ def _create_sensor(xknx: XKNX, config: ConfigType) -> XknxSensor:
)


class KNXSensor(KnxYamlEntity, SensorEntity):
class KNXSensor(KnxYamlEntity, RestoreSensor):
"""Representation of a KNX sensor."""

_device: XknxSensor
Expand All @@ -164,20 +166,30 @@ def __init__(self, knx_module: KNXModule, config: ConfigType) -> None:
self._attr_unique_id = str(self._device.sensor_value.group_address_state)
self._attr_native_unit_of_measurement = self._device.unit_of_measurement()
self._attr_state_class = config.get(CONF_STATE_CLASS)
self._attr_extra_state_attributes = {}

@property
def native_value(self) -> StateType:
"""Return the state of the sensor."""
return self._device.resolve_state()

@property
def extra_state_attributes(self) -> dict[str, Any] | None:
"""Return device specific state attributes."""
attr: dict[str, Any] = {}
async def async_added_to_hass(self) -> None:
"""Restore last state."""
if (
(last_state := await self.async_get_last_state())
and last_state.state not in (STATE_UNKNOWN, STATE_UNAVAILABLE)
and (
(last_sensor_data := await self.async_get_last_sensor_data())
is not None
)
):
self._attr_native_value = last_sensor_data.native_value
self._attr_extra_state_attributes.update(last_state.attributes)
await super().async_added_to_hass()

if self._device.last_telegram is not None:
attr[ATTR_SOURCE] = str(self._device.last_telegram.source_address)
return attr
def after_update_callback(self, device: XknxDevice) -> None:
"""Call after device was updated."""
self._attr_native_value = self._device.resolve_state()
if telegram := self._device.last_telegram:
self._attr_extra_state_attributes[ATTR_SOURCE] = str(
telegram.source_address
)
super().after_update_callback(device)


class KNXSystemSensor(SensorEntity):
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/miele/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"config_flow": true,
"dependencies": ["application_credentials"],
"documentation": "https://www.home-assistant.io/integrations/miele",
"integration_type": "hub",
"iot_class": "cloud_push",
"loggers": ["pymiele"],
"quality_scale": "platinum",
Expand Down
8 changes: 4 additions & 4 deletions homeassistant/components/snapcast/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def register_services() -> None:
"""Register snapcast services."""
platform = entity_platform.async_get_current_platform()

platform.async_register_entity_service(SERVICE_SNAPSHOT, None, "snapshot")
platform.async_register_entity_service(SERVICE_SNAPSHOT, None, "async_snapshot")
platform.async_register_entity_service(SERVICE_RESTORE, None, "async_restore")
platform.async_register_entity_service(
SERVICE_JOIN, {vol.Required(ATTR_MASTER): cv.entity_id}, "async_join"
Expand Down Expand Up @@ -250,7 +250,7 @@ async def async_set_volume_level(self, volume: float) -> None:
await self._device.set_volume(round(volume * 100))
self.async_write_ha_state()

def snapshot(self) -> None:
async def async_snapshot(self) -> None:
"""Snapshot the group state."""
self._device.snapshot()

Expand Down Expand Up @@ -428,12 +428,12 @@ async def async_set_volume_level(self, volume: float) -> None:

await super().async_set_volume_level(volume)

def snapshot(self) -> None:
async def async_snapshot(self) -> None:
"""Snapshot the group state."""
# Groups are deprecated, create an issue when used
self._async_create_group_deprecation_issue()

super().snapshot()
await super().async_snapshot()

async def async_restore(self) -> None:
"""Restore the group state."""
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/voip/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"config_flow": true,
"dependencies": ["assist_pipeline", "assist_satellite", "intent", "network"],
"documentation": "https://www.home-assistant.io/integrations/voip",
"integration_type": "hub",
"iot_class": "local_push",
"loggers": ["voip_utils"],
"quality_scale": "internal",
Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion requirements_test_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 6 additions & 24 deletions tests/components/google_assistant_sdk/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async def test_full_flow(
) -> None:
"""Check full flow."""
result = await hass.config_entries.flow.async_init(
"google_assistant_sdk", context={"source": config_entries.SOURCE_USER}
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
state = config_entry_oauth2_flow._encode_jwt(
hass,
Expand Down Expand Up @@ -88,25 +88,14 @@ async def test_reauth(
hass_client_no_auth: ClientSessionGenerator,
aioclient_mock: AiohttpClientMocker,
setup_credentials: None,
config_entry: MockConfigEntry,
) -> None:
"""Test the reauthentication case updates the existing config entry."""

config_entry = MockConfigEntry(
domain=DOMAIN,
data={
"token": {
"access_token": "mock-access-token",
},
},
)
config_entry.add_to_hass(hass)

config_entry.async_start_reauth(hass)
await hass.async_block_till_done()
result = await config_entry.start_reauth_flow(hass)

flows = hass.config_entries.flow.async_progress()
assert len(flows) == 1
result = flows[0]
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"

result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
Expand Down Expand Up @@ -219,20 +208,13 @@ async def test_single_instance_allowed(
hass_client_no_auth: ClientSessionGenerator,
aioclient_mock: AiohttpClientMocker,
setup_credentials: None,
config_entry: MockConfigEntry,
) -> None:
"""Test case where config flow allows a single test."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data={
"token": {
"access_token": "mock-access-token",
},
},
)
config_entry.add_to_hass(hass)

result = await hass.config_entries.flow.async_init(
"google_assistant_sdk", context={"source": config_entries.SOURCE_USER}
DOMAIN, context={"source": config_entries.SOURCE_USER}
)

assert result.get("type") is FlowResultType.ABORT
Expand Down
8 changes: 5 additions & 3 deletions tests/components/knx/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,8 @@ async def test_binary_sensor_reset(
assert state.state is STATE_OFF


async def test_binary_sensor_restore_and_respond(hass: HomeAssistant, knx) -> None:
"""Test restoring KNX binary sensor state and respond to read."""
async def test_binary_sensor_restore(hass: HomeAssistant, knx: KNXTestKit) -> None:
"""Test restoring KNX binary sensor state."""
_ADDRESS = "2/2/2"
fake_state = State("binary_sensor.test", STATE_ON)
mock_restore_cache(hass, (fake_state,))
Expand All @@ -312,7 +312,9 @@ async def test_binary_sensor_restore_and_respond(hass: HomeAssistant, knx) -> No
assert state.state is STATE_OFF


async def test_binary_sensor_restore_invert(hass: HomeAssistant, knx) -> None:
async def test_binary_sensor_restore_invert(
hass: HomeAssistant, knx: KNXTestKit
) -> None:
"""Test restoring KNX binary sensor state with invert."""
_ADDRESS = "2/2/2"
fake_state = State("binary_sensor.test", STATE_ON)
Expand Down
49 changes: 46 additions & 3 deletions tests/components/knx/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@

from freezegun.api import FrozenDateTimeFactory

from homeassistant.components.knx.const import CONF_STATE_ADDRESS, CONF_SYNC_STATE
from homeassistant.components.knx.const import (
ATTR_SOURCE,
CONF_STATE_ADDRESS,
CONF_SYNC_STATE,
)
from homeassistant.components.knx.schema import SensorSchema
from homeassistant.const import CONF_NAME, CONF_TYPE, STATE_UNKNOWN
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, State

from .conftest import KNXTestKit

from tests.common import async_capture_events, async_fire_time_changed
from tests.common import (
async_capture_events,
async_fire_time_changed,
mock_restore_cache_with_extra_data,
)


async def test_sensor(hass: HomeAssistant, knx: KNXTestKit) -> None:
Expand Down Expand Up @@ -43,6 +51,41 @@ async def test_sensor(hass: HomeAssistant, knx: KNXTestKit) -> None:
await knx.assert_no_telegram()


async def test_sensor_restore(hass: HomeAssistant, knx: KNXTestKit) -> None:
"""Test restoring KNX sensor state."""
ADDRESS = "2/2/2"
RAW_FLOAT_21_0 = (0x0C, 0x1A)
RESTORED_STATE = "21.0"
RESTORED_STATE_ATTRIBUTES = {ATTR_SOURCE: knx.INDIVIDUAL_ADDRESS}
fake_state = State(
"sensor.test", "ignored in favour of native_value", RESTORED_STATE_ATTRIBUTES
)
extra_data = {"native_value": RESTORED_STATE, "native_unit_of_measurement": "°C"}
mock_restore_cache_with_extra_data(hass, [(fake_state, extra_data)])

await knx.setup_integration(
{
SensorSchema.PLATFORM: [
{
CONF_NAME: "test",
CONF_STATE_ADDRESS: ADDRESS,
CONF_TYPE: "temperature", # 2 byte float
CONF_SYNC_STATE: False,
},
]
}
)

# restored state - no read-response due to sync_state False
knx.assert_state("sensor.test", RESTORED_STATE, **RESTORED_STATE_ATTRIBUTES)
await knx.assert_telegram_count(0)

# receiving the restored value from restored source does not trigger state_changed event
events = async_capture_events(hass, "state_changed")
await knx.receive_write(ADDRESS, RAW_FLOAT_21_0)
assert not events


async def test_last_reported(
hass: HomeAssistant,
knx: KNXTestKit,
Expand Down
2 changes: 1 addition & 1 deletion tests/components/knx/test_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ async def test_switch_state(hass: HomeAssistant, knx: KNXTestKit) -> None:
await knx.assert_telegram_count(0)


async def test_switch_restore_and_respond(hass: HomeAssistant, knx) -> None:
async def test_switch_restore_and_respond(hass: HomeAssistant, knx: KNXTestKit) -> None:
"""Test restoring KNX switch state and respond to read."""
_ADDRESS = "1/1/1"
fake_state = State("switch.test", "on")
Expand Down
Loading