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
2 changes: 1 addition & 1 deletion homeassistant/components/debugpy/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"integration_type": "service",
"iot_class": "local_push",
"quality_scale": "internal",
"requirements": ["debugpy==1.8.14"]
"requirements": ["debugpy==1.8.16"]
}
2 changes: 0 additions & 2 deletions homeassistant/components/shelly/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,6 @@ def __init__(
device_class=BinarySensorDeviceClass.GAS,
translation_key="gas",
value=lambda value: value in ["mild", "heavy"],
# Deprecated, remove in 2025.10
extra_state_attributes=lambda block: {"detected": block.gas},
),
("sensor", "smoke"): BlockBinarySensorDescription(
key="sensor|smoke", name="Smoke", device_class=BinarySensorDeviceClass.SMOKE
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/shelly/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
# min RPC light transition time in seconds (max=10800, limited by light entity to 6553)
RPC_MIN_TRANSITION_TIME_SEC = 0.5

# time in seconds between two cover state updates when moving
RPC_COVER_UPDATE_TIME_SEC = 1.0

RGBW_MODELS: Final = (
MODEL_BULB,
MODEL_RGBW2,
Expand Down
30 changes: 30 additions & 0 deletions homeassistant/components/shelly/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import asyncio
from typing import Any, cast

from aioshelly.block_device import Block
Expand All @@ -17,6 +18,7 @@
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .const import RPC_COVER_UPDATE_TIME_SEC
from .coordinator import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator
from .entity import ShellyBlockEntity, ShellyRpcEntity
from .utils import get_device_entry_gen, get_rpc_key_ids
Expand Down Expand Up @@ -158,6 +160,7 @@ def __init__(self, coordinator: ShellyRpcCoordinator, id_: int) -> None:
"""Initialize rpc cover."""
super().__init__(coordinator, f"cover:{id_}")
self._id = id_
self._update_task: asyncio.Task | None = None
if self.status["pos_control"]:
self._attr_supported_features |= CoverEntityFeature.SET_POSITION
if coordinator.device.config[f"cover:{id_}"].get("slat", {}).get("enable"):
Expand Down Expand Up @@ -199,6 +202,33 @@ def is_opening(self) -> bool:
"""Return if the cover is opening."""
return cast(bool, self.status["state"] == "opening")

def launch_update_task(self) -> None:
"""Launch the update position task if needed."""
if not self._update_task or self._update_task.done():
self._update_task = (
self.coordinator.config_entry.async_create_background_task(
self.hass,
self.update_position(),
f"Shelly cover update [{self._id} - {self.name}]",
)
)

async def update_position(self) -> None:
"""Update the cover position every second."""
try:
while self.is_closing or self.is_opening:
await self.coordinator.device.update_status()
self.async_write_ha_state()
await asyncio.sleep(RPC_COVER_UPDATE_TIME_SEC)
finally:
self._update_task = None

def _update_callback(self) -> None:
"""Handle device update. Use a task when opening/closing is in progress."""
super()._update_callback()
if self.is_closing or self.is_opening:
self.launch_update_task()

async def async_close_cover(self, **kwargs: Any) -> None:
"""Close cover."""
await self.call_rpc("Cover.Close", {"id": self._id})
Expand Down
9 changes: 0 additions & 9 deletions homeassistant/components/shelly/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ class BlockEntityDescription(EntityDescription):
available: Callable[[Block], bool] | None = None
# Callable (settings, block), return true if entity should be removed
removal_condition: Callable[[dict, Block], bool] | None = None
extra_state_attributes: Callable[[Block], dict | None] | None = None


@dataclass(frozen=True, kw_only=True)
Expand Down Expand Up @@ -494,14 +493,6 @@ def available(self) -> bool:

return self.entity_description.available(self.block)

@property
def extra_state_attributes(self) -> dict[str, Any] | None:
"""Return the state attributes."""
if self.entity_description.extra_state_attributes is None:
return None

return self.entity_description.extra_state_attributes(self.block)


class ShellyRestAttributeEntity(CoordinatorEntity[ShellyBlockCoordinator]):
"""Class to load info from REST."""
Expand Down
6 changes: 0 additions & 6 deletions homeassistant/components/shelly/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,6 @@ def __init__(
translation_key="lamp_life",
value=get_shelly_air_lamp_life,
suggested_display_precision=1,
# Deprecated, remove in 2025.10
extra_state_attributes=lambda block: {
"Operational hours": round(cast(int, block.totalWorkTime) / 3600, 1)
},
entity_category=EntityCategory.DIAGNOSTIC,
),
("adc", "adc"): BlockSensorDescription(
Expand All @@ -403,8 +399,6 @@ def __init__(
options=["warmup", "normal", "fault"],
translation_key="operation",
value=lambda value: None if value == "unknown" else value,
# Deprecated, remove in 2025.10
extra_state_attributes=lambda block: {"self_test": block.selfTest},
),
("valve", "valve"): BlockSensorDescription(
key="valve|valve",
Expand Down
24 changes: 0 additions & 24 deletions homeassistant/components/shelly/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,6 @@
}
},
"entity": {
"binary_sensor": {
"gas": {
"state_attributes": {
"detected": {
"state": {
"none": "None",
"mild": "Mild",
"heavy": "Heavy",
"test": "Test"
}
}
}
}
},
"event": {
"input": {
"state_attributes": {
Expand Down Expand Up @@ -178,16 +164,6 @@
"warmup": "Warm-up",
"normal": "[%key:common::state::normal%]",
"fault": "[%key:common::state::fault%]"
},
"state_attributes": {
"self_test": {
"state": {
"not_completed": "[%key:component::shelly::entity::sensor::self_test::state::not_completed%]",
"completed": "[%key:component::shelly::entity::sensor::self_test::state::completed%]",
"running": "[%key:component::shelly::entity::sensor::self_test::state::running%]",
"pending": "[%key:component::shelly::entity::sensor::self_test::state::pending%]"
}
}
}
},
"self_test": {
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/tibber/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"documentation": "https://www.home-assistant.io/integrations/tibber",
"iot_class": "cloud_polling",
"loggers": ["tibber"],
"requirements": ["pyTibber==0.31.6"]
"requirements": ["pyTibber==0.31.7"]
}
6 changes: 3 additions & 3 deletions homeassistant/package_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ bluetooth-auto-recovery==1.5.2
bluetooth-data-tools==1.28.2
cached-ipaddress==0.10.0
certifi>=2021.5.30
ciso8601==2.3.2
ciso8601==2.3.3
cronsim==2.6
cryptography==45.0.3
cryptography==45.0.7
dbus-fast==2.44.3
fnv-hash-fast==1.5.0
go2rtc-client==0.2.1
Expand Down Expand Up @@ -60,7 +60,7 @@ pyspeex-noise==1.0.2
python-slugify==8.0.4
PyTurboJPEG==1.8.0
PyYAML==6.0.2
requests==2.32.4
requests==2.32.5
securetar==2025.2.1
SQLAlchemy==2.0.41
standard-aifc==3.13.0
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ dependencies = [
"awesomeversion==25.5.0",
"bcrypt==4.3.0",
"certifi>=2021.5.30",
"ciso8601==2.3.2",
"ciso8601==2.3.3",
"cronsim==2.6",
"fnv-hash-fast==1.5.0",
# hass-nabucasa is imported by helpers which don't depend on the cloud
Expand All @@ -57,7 +57,7 @@ dependencies = [
"lru-dict==1.3.0",
"PyJWT==2.10.1",
# PyJWT has loose dependency. We want the latest one.
"cryptography==45.0.3",
"cryptography==45.0.7",
"Pillow==11.3.0",
"propcache==0.3.2",
"pyOpenSSL==25.1.0",
Expand All @@ -66,7 +66,7 @@ dependencies = [
"psutil-home-assistant==0.0.1",
"python-slugify==8.0.4",
"PyYAML==6.0.2",
"requests==2.32.4",
"requests==2.32.5",
"securetar==2025.2.1",
"SQLAlchemy==2.0.41",
"standard-aifc==3.13.0",
Expand Down
6 changes: 3 additions & 3 deletions requirements.txt

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

4 changes: 2 additions & 2 deletions 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.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pytest-timeout==2.4.0
pytest-unordered==0.7.0
pytest-picked==0.5.1
pytest-xdist==3.8.0
pytest==8.4.1
pytest==8.4.2
requests-mock==1.12.1
respx==0.22.0
syrupy==4.9.1
Expand Down
4 changes: 2 additions & 2 deletions requirements_test_all.txt

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

6 changes: 4 additions & 2 deletions tests/components/shelly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,12 @@ async def mock_rest_update(


async def mock_polling_rpc_update(
hass: HomeAssistant, freezer: FrozenDateTimeFactory
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
seconds: float = RPC_SENSORS_POLLING_INTERVAL,
) -> None:
"""Move time to create polling RPC sensors update event."""
freezer.tick(timedelta(seconds=RPC_SENSORS_POLLING_INTERVAL))
freezer.tick(timedelta(seconds=seconds))
async_fire_time_changed(hass)
await hass.async_block_till_done()

Expand Down
6 changes: 2 additions & 4 deletions tests/components/shelly/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,24 @@ async def test_block_binary_sensor(
assert entry.unique_id == "123456789ABC-relay_0-overpower"


async def test_block_binary_sensor_extra_state_attr(
async def test_block_binary_gas_sensor_creation(
hass: HomeAssistant,
mock_block_device: Mock,
monkeypatch: pytest.MonkeyPatch,
entity_registry: EntityRegistry,
) -> None:
"""Test block binary sensor extra state attributes."""
"""Test block binary gas sensor creation."""
entity_id = f"{BINARY_SENSOR_DOMAIN}.test_name_gas"
await init_integration(hass, 1)

assert (state := hass.states.get(entity_id))
assert state.state == STATE_ON
assert state.attributes.get("detected") == "mild"

monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "gas", "none")
mock_block_device.mock_update()

assert (state := hass.states.get(entity_id))
assert state.state == STATE_OFF
assert state.attributes.get("detected") == "none"

assert (entry := entity_registry.async_get(entity_id))
assert entry.unique_id == "123456789ABC-sensor_0-gas"
Expand Down
Loading
Loading