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
17 changes: 12 additions & 5 deletions homeassistant/components/cast/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -816,13 +816,20 @@ def state(self) -> MediaPlayerState | None:
return MediaPlayerState.PAUSED
if media_status.player_is_idle:
return MediaPlayerState.IDLE
if self.app_id is not None and self.app_id != pychromecast.IDLE_APP_ID:
if self.app_id in APP_IDS_UNRELIABLE_MEDIA_INFO:
# Some apps don't report media status, show the player as playing
return MediaPlayerState.PLAYING
return MediaPlayerState.IDLE

if self._chromecast is not None and self._chromecast.is_idle:
# If library consider us idle, that is our off state
# it takes HDMI status into account for cast devices.
return MediaPlayerState.OFF

if self.app_id in APP_IDS_UNRELIABLE_MEDIA_INFO:
# Some apps don't report media status, show the player as playing
return MediaPlayerState.PLAYING

if self.app_id is not None:
# We have an active app
return MediaPlayerState.IDLE

return None

@property
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/nuki/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ async def handle_webhook(
translation_placeholders={
"base_url": hass_url,
"network_link": "https://my.home-assistant.io/redirect/network/",
"sample_ip": "192.168.1.10",
"sample_url": "http://192.168.1.10:8123",
},
)
else:
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/nuki/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,5 @@ async def async_step_validate(
step_id="user",
data_schema=self.add_suggested_values_to_schema(data_schema, user_input),
errors=errors,
description_placeholders={"sample_ip": "192.168.1.25"},
)
4 changes: 2 additions & 2 deletions homeassistant/components/nuki/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"encrypt_token": "Use an encrypted token for authentication."
},
"data_description": {
"host": "The hostname or IP address of your Nuki bridge. For example: 192.168.1.25."
"host": "The hostname or IP address of your Nuki bridge. For example: {sample_ip}."
}
},
"reauth_confirm": {
Expand All @@ -34,7 +34,7 @@
"issues": {
"https_webhook": {
"title": "Nuki webhook URL uses HTTPS (SSL)",
"description": "The Nuki bridge can not push events to an HTTPS address (SSL), please configure a (local) HTTP address under \"Home Assistant URL\" in the [network settings]({network_link}). The current (local) address is: `{base_url}`, a valid address could, for example, be `http://192.168.1.10:8123` where `192.168.1.10` is the IP of the Home Assistant device"
"description": "The Nuki bridge cannot push events to an HTTPS address (SSL), please configure a (local) HTTP address under \"Home Assistant URL\" in the [network settings]({network_link}). The current (local) address is: `{base_url}`, a valid address could, for example, be `{sample_url}` where `{sample_ip}` is the IP of the Home Assistant device"
}
},
"entity": {
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/plugwise/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"iot_class": "local_polling",
"loggers": ["plugwise"],
"quality_scale": "platinum",
"requirements": ["plugwise==1.8.1"],
"requirements": ["plugwise==1.8.2"],
"zeroconf": ["_plugwise._tcp.local."]
}
2 changes: 1 addition & 1 deletion homeassistant/components/portainer/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,5 +142,5 @@ def available(self) -> bool:
def is_on(self) -> bool | None:
"""Return true if the binary sensor is on."""
return self.entity_description.state_fn(
self.coordinator.data[self.endpoint_id].containers[self.device_id]
self.coordinator.data[self.endpoint_id].containers[self.device_name]
)
7 changes: 1 addition & 6 deletions homeassistant/components/portainer/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,7 @@ def __init__(
self.entity_description = entity_description
super().__init__(device_info, coordinator, via_device)

device_identifier = (
self._device_info.names[0].replace("/", " ").strip()
if self._device_info.names
else None
)
self._attr_unique_id = f"{coordinator.config_entry.entry_id}_{device_identifier}_{entity_description.key}"
self._attr_unique_id = f"{coordinator.config_entry.entry_id}_{self.device_name}_{entity_description.key}"

async def async_press(self) -> None:
"""Trigger the Portainer button press service."""
Expand Down
5 changes: 4 additions & 1 deletion homeassistant/components/portainer/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ async def _async_update_data(self) -> dict[int, PortainerCoordinatorData]:
id=endpoint.id,
name=endpoint.name,
endpoint=endpoint,
containers={container.id: container for container in containers},
containers={
container.names[0].replace("/", " ").strip(): container
for container in containers
},
docker_version=docker_version,
docker_info=docker_info,
)
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/portainer/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def available(self) -> bool:
def native_value(self) -> StateType:
"""Return the state of the sensor."""
return self.entity_description.value_fn(
self.coordinator.data[self.endpoint_id].containers[self.device_id]
self.coordinator.data[self.endpoint_id].containers[self.device_name]
)


Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/portainer/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def __init__(
def is_on(self) -> bool | None:
"""Return the state of the device."""
return self.entity_description.is_on_fn(
self.coordinator.data[self.endpoint_id].containers[self.device_id]
self.coordinator.data[self.endpoint_id].containers[self.device_name]
)

async def async_turn_on(self, **kwargs: Any) -> None:
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/teslemetry/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/teslemetry",
"iot_class": "cloud_polling",
"loggers": ["tesla-fleet-api"],
"requirements": ["tesla-fleet-api==1.2.3", "teslemetry-stream==0.7.9"]
"requirements": ["tesla-fleet-api==1.2.3", "teslemetry-stream==0.7.10"]
}
6 changes: 3 additions & 3 deletions homeassistant/components/vodafone_station/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Vodafone Station integration."""

from aiohttp import ClientSession, CookieJar
from aiovodafone.api import VodafoneStationCommonApi
from aiovodafone.models import get_device_type

from homeassistant.const import CONF_HOST, Platform
from homeassistant.core import HomeAssistant
Expand Down Expand Up @@ -42,7 +42,7 @@ async def async_migrate_entry(hass: HomeAssistant, entry: VodafoneConfigEntry) -
session = ClientSession(cookie_jar=jar)

try:
device_type, url = await VodafoneStationCommonApi.get_device_type(
device_type, url = await get_device_type(
entry.data[CONF_HOST],
session,
)
Expand All @@ -54,7 +54,7 @@ async def async_migrate_entry(hass: HomeAssistant, entry: VodafoneConfigEntry) -
new_data.update(
{
CONF_DEVICE_DETAILS: {
DEVICE_TYPE: device_type,
DEVICE_TYPE: device_type.value,
DEVICE_URL: str(url),
}
},
Expand Down
8 changes: 4 additions & 4 deletions homeassistant/components/vodafone_station/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import Any

from aiovodafone import exceptions as aiovodafone_exceptions
from aiovodafone.api import VodafoneStationCommonApi, init_api_class
from aiovodafone.models import get_device_type, init_device_class
import voluptuous as vol

from homeassistant.components.device_tracker import (
Expand Down Expand Up @@ -54,12 +54,12 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str,

session = await async_client_session(hass)

device_type, url = await VodafoneStationCommonApi.get_device_type(
device_type, url = await get_device_type(
data[CONF_HOST],
session,
)

api = init_api_class(url, device_type, data, session)
api = init_device_class(url, device_type, data, session)

try:
await api.login()
Expand All @@ -69,7 +69,7 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str,
return {
"title": data[CONF_HOST],
CONF_DEVICE_DETAILS: {
DEVICE_TYPE: device_type,
DEVICE_TYPE: device_type.value,
DEVICE_URL: str(url),
},
}
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/components/vodafone_station/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

from aiohttp import ClientSession
from aiovodafone import exceptions
from aiovodafone.api import VodafoneStationDevice, init_api_class
from aiovodafone.api import VodafoneStationDevice
from aiovodafone.models import init_device_class
from yarl import URL

from homeassistant.components.device_tracker import (
Expand Down Expand Up @@ -70,7 +71,7 @@ def __init__(

data = config_entry.data

self.api = init_api_class(
self.api = init_device_class(
URL(data[CONF_DEVICE_DETAILS][DEVICE_URL]),
data[CONF_DEVICE_DETAILS][DEVICE_TYPE],
data,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/vodafone_station/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "local_polling",
"loggers": ["aiovodafone"],
"quality_scale": "platinum",
"requirements": ["aiovodafone==2.0.1"]
"requirements": ["aiovodafone==3.0.0"]
}
6 changes: 3 additions & 3 deletions requirements_all.txt

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

6 changes: 3 additions & 3 deletions requirements_test_all.txt

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

6 changes: 6 additions & 0 deletions tests/components/cast/test_media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def get_fake_chromecast(info: ChromecastInfo):
mock = MagicMock(uuid=info.uuid)
mock.app_id = None
mock.media_controller.status = None
mock.is_idle = True
return mock


Expand Down Expand Up @@ -887,6 +888,7 @@ async def test_entity_cast_status(
assert not state.attributes.get("is_volume_muted")

chromecast.app_id = "1234"
chromecast.is_idle = False
cast_status = MagicMock()
cast_status.volume_level = 0.5
cast_status.volume_muted = False
Expand Down Expand Up @@ -1599,6 +1601,7 @@ async def test_entity_media_states(

# App id updated, but no media status
chromecast.app_id = app_id
chromecast.is_idle = False
cast_status = MagicMock()
cast_status_cb(cast_status)
await hass.async_block_till_done()
Expand Down Expand Up @@ -1641,13 +1644,15 @@ async def test_entity_media_states(

# App no longer running
chromecast.app_id = pychromecast.IDLE_APP_ID
chromecast.is_idle = True
cast_status = MagicMock()
cast_status_cb(cast_status)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state.state == "off"

# No cast status
chromecast.app_id = None
chromecast.is_idle = False
cast_status_cb(None)
await hass.async_block_till_done()
Expand Down Expand Up @@ -1722,6 +1727,7 @@ async def test_entity_media_states_lovelace_app(
state = hass.states.get(entity_id)
assert state.state == "off"

chromecast.app_id = None
chromecast.is_idle = False
media_status_cb(media_status)
await hass.async_block_till_done()
Expand Down
15 changes: 9 additions & 6 deletions tests/components/vodafone_station/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from datetime import UTC, datetime

from aiovodafone.api import VodafoneStationCommonApi, VodafoneStationDevice
from aiovodafone.api import VodafoneStationDevice
import pytest
from yarl import URL

Expand Down Expand Up @@ -49,16 +49,19 @@ def mock_vodafone_station_router() -> Generator[AsyncMock]:
"""Mock a Vodafone Station router."""
with (
patch(
"homeassistant.components.vodafone_station.coordinator.init_api_class",
"homeassistant.components.vodafone_station.coordinator.init_device_class",
autospec=True,
) as mock_router,
patch(
"homeassistant.components.vodafone_station.config_flow.init_api_class",
"homeassistant.components.vodafone_station.config_flow.init_device_class",
new=mock_router,
),
patch.object(
VodafoneStationCommonApi,
"get_device_type",
patch(
"homeassistant.components.vodafone_station.config_flow.get_device_type",
new=AsyncMock(return_value=(TEST_TYPE, URL(TEST_URL))),
),
patch(
"homeassistant.components.vodafone_station.get_device_type",
new=AsyncMock(return_value=(TEST_TYPE, URL(TEST_URL))),
),
):
Expand Down
4 changes: 3 additions & 1 deletion tests/components/vodafone_station/const.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"""Common stuff for Vodafone Station tests."""

from aiovodafone.models import DeviceType

DEVICE_1_HOST = "WifiDevice0"
DEVICE_1_MAC = "xx:xx:xx:xx:xx:xx"
DEVICE_2_HOST = "LanDevice1"
DEVICE_2_MAC = "yy:yy:yy:yy:yy:yy"

TEST_HOST = "fake_host"
TEST_PASSWORD = "fake_password"
TEST_TYPE = "Sercomm"
TEST_TYPE = DeviceType.SERCOMM
TEST_URL = f"https://{TEST_HOST}"
TEST_USERNAME = "fake_username"
2 changes: 1 addition & 1 deletion tests/components/vodafone_station/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from unittest.mock import AsyncMock

from aiovodafone import (
from aiovodafone.exceptions import (
AlreadyLogged,
CannotAuthenticate,
CannotConnect,
Expand Down
2 changes: 1 addition & 1 deletion tests/components/vodafone_station/test_coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
from unittest.mock import AsyncMock

from aiovodafone import VodafoneStationDevice
from aiovodafone.api import VodafoneStationDevice
from freezegun.api import FrozenDateTimeFactory
import pytest

Expand Down
3 changes: 1 addition & 2 deletions tests/components/vodafone_station/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

from unittest.mock import AsyncMock, patch

from aiovodafone import CannotAuthenticate
from aiovodafone.exceptions import AlreadyLogged, CannotConnect
from aiovodafone.exceptions import AlreadyLogged, CannotAuthenticate, CannotConnect
from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy.assertion import SnapshotAssertion
Expand Down
Loading