Remove the switch entity for Shelly Gas Valve (#119817)
Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>pull/118664/head^2
parent
57308599cd
commit
87c1d5a6a7
|
@ -6,38 +6,22 @@ from dataclasses import dataclass
|
|||
from typing import Any, cast
|
||||
|
||||
from aioshelly.block_device import Block
|
||||
from aioshelly.const import (
|
||||
MODEL_2,
|
||||
MODEL_25,
|
||||
MODEL_GAS,
|
||||
MODEL_WALL_DISPLAY,
|
||||
RPC_GENERATIONS,
|
||||
)
|
||||
from aioshelly.const import MODEL_2, MODEL_25, MODEL_WALL_DISPLAY, RPC_GENERATIONS
|
||||
|
||||
from homeassistant.components.automation import automations_with_entity
|
||||
from homeassistant.components.script import scripts_with_entity
|
||||
from homeassistant.components.switch import (
|
||||
DOMAIN as SWITCH_DOMAIN,
|
||||
SwitchEntity,
|
||||
SwitchEntityDescription,
|
||||
)
|
||||
from homeassistant.components.valve import DOMAIN as VALVE_DOMAIN
|
||||
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
||||
from homeassistant.const import STATE_ON, EntityCategory
|
||||
from homeassistant.core import HomeAssistant, State, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.entity_registry import RegistryEntry
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
from .const import CONF_SLEEP_PERIOD, DOMAIN, GAS_VALVE_OPEN_STATES, MOTION_MODELS
|
||||
from .const import CONF_SLEEP_PERIOD, MOTION_MODELS
|
||||
from .coordinator import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator
|
||||
from .entity import (
|
||||
BlockEntityDescription,
|
||||
ShellyBlockAttributeEntity,
|
||||
ShellyBlockEntity,
|
||||
ShellyRpcEntity,
|
||||
ShellySleepingBlockAttributeEntity,
|
||||
async_setup_block_attribute_entities,
|
||||
async_setup_entry_attribute_entities,
|
||||
)
|
||||
from .utils import (
|
||||
|
@ -56,15 +40,6 @@ class BlockSwitchDescription(BlockEntityDescription, SwitchEntityDescription):
|
|||
"""Class to describe a BLOCK switch."""
|
||||
|
||||
|
||||
# This entity description is deprecated and will be removed in Home Assistant 2024.7.0.
|
||||
GAS_VALVE_SWITCH = BlockSwitchDescription(
|
||||
key="valve|valve",
|
||||
name="Valve",
|
||||
available=lambda block: block.valve not in ("failure", "checking"),
|
||||
removal_condition=lambda _, block: block.valve in ("not_connected", "unknown"),
|
||||
entity_registry_enabled_default=False,
|
||||
)
|
||||
|
||||
MOTION_SWITCH = BlockSwitchDescription(
|
||||
key="sensor|motionActive",
|
||||
name="Motion detection",
|
||||
|
@ -94,17 +69,6 @@ def async_setup_block_entry(
|
|||
coordinator = config_entry.runtime_data.block
|
||||
assert coordinator
|
||||
|
||||
# Add Shelly Gas Valve as a switch
|
||||
if coordinator.model == MODEL_GAS:
|
||||
async_setup_block_attribute_entities(
|
||||
hass,
|
||||
async_add_entities,
|
||||
coordinator,
|
||||
{("valve", "valve"): GAS_VALVE_SWITCH},
|
||||
BlockValveSwitch,
|
||||
)
|
||||
return
|
||||
|
||||
# Add Shelly Motion as a switch
|
||||
if coordinator.model in MOTION_MODELS:
|
||||
async_setup_entry_attribute_entities(
|
||||
|
@ -238,99 +202,6 @@ class BlockSleepingMotionSwitch(
|
|||
self.last_state = last_state
|
||||
|
||||
|
||||
class BlockValveSwitch(ShellyBlockAttributeEntity, SwitchEntity):
|
||||
"""Entity that controls a Gas Valve on Block based Shelly devices.
|
||||
|
||||
This class is deprecated and will be removed in Home Assistant 2024.7.0.
|
||||
"""
|
||||
|
||||
entity_description: BlockSwitchDescription
|
||||
_attr_translation_key = "valve_switch"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: ShellyBlockCoordinator,
|
||||
block: Block,
|
||||
attribute: str,
|
||||
description: BlockSwitchDescription,
|
||||
) -> None:
|
||||
"""Initialize valve."""
|
||||
super().__init__(coordinator, block, attribute, description)
|
||||
self.control_result: dict[str, Any] | None = None
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""If valve is open."""
|
||||
if self.control_result:
|
||||
return self.control_result["state"] in GAS_VALVE_OPEN_STATES
|
||||
|
||||
return self.attribute_value in GAS_VALVE_OPEN_STATES
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Open valve."""
|
||||
async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
"deprecated_valve_switch",
|
||||
breaks_in_ha_version="2024.7.0",
|
||||
is_fixable=True,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_valve_switch",
|
||||
translation_placeholders={
|
||||
"entity": f"{VALVE_DOMAIN}.{cast(str, self.name).lower().replace(' ', '_')}",
|
||||
"service": f"{VALVE_DOMAIN}.open_valve",
|
||||
},
|
||||
)
|
||||
self.control_result = await self.set_state(go="open")
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Close valve."""
|
||||
async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
"deprecated_valve_switch",
|
||||
breaks_in_ha_version="2024.7.0",
|
||||
is_fixable=True,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_valve_switche",
|
||||
translation_placeholders={
|
||||
"entity": f"{VALVE_DOMAIN}.{cast(str, self.name).lower().replace(' ', '_')}",
|
||||
"service": f"{VALVE_DOMAIN}.close_valve",
|
||||
},
|
||||
)
|
||||
self.control_result = await self.set_state(go="close")
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Set up a listener when this entity is added to HA."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
entity_automations = automations_with_entity(self.hass, self.entity_id)
|
||||
entity_scripts = scripts_with_entity(self.hass, self.entity_id)
|
||||
for item in entity_automations + entity_scripts:
|
||||
async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
f"deprecated_valve_{self.entity_id}_{item}",
|
||||
breaks_in_ha_version="2024.7.0",
|
||||
is_fixable=True,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_valve_switch_entity",
|
||||
translation_placeholders={
|
||||
"entity": f"{SWITCH_DOMAIN}.{cast(str, self.name).lower().replace(' ', '_')}",
|
||||
"info": item,
|
||||
},
|
||||
)
|
||||
|
||||
@callback
|
||||
def _update_callback(self) -> None:
|
||||
"""When device updates, clear control result that overrides state."""
|
||||
self.control_result = None
|
||||
|
||||
super()._update_callback()
|
||||
|
||||
|
||||
class BlockRelaySwitch(ShellyBlockEntity, SwitchEntity):
|
||||
"""Entity that controls a relay on Block based Shelly devices."""
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ from .entity import (
|
|||
ShellyBlockAttributeEntity,
|
||||
async_setup_block_attribute_entities,
|
||||
)
|
||||
from .utils import get_device_entry_gen
|
||||
from .utils import async_remove_shelly_entity, get_device_entry_gen
|
||||
|
||||
|
||||
@dataclass(kw_only=True, frozen=True)
|
||||
|
@ -67,6 +67,9 @@ def async_setup_block_entry(
|
|||
{("valve", "valve"): GAS_VALVE},
|
||||
BlockShellyValve,
|
||||
)
|
||||
# Remove deprecated switch entity for gas valve
|
||||
unique_id = f"{coordinator.mac}-valve_0-valve"
|
||||
async_remove_shelly_entity(hass, "switch", unique_id)
|
||||
|
||||
|
||||
class BlockShellyValve(ShellyBlockAttributeEntity, ValveEntity):
|
||||
|
|
|
@ -7,10 +7,7 @@ from aioshelly.const import MODEL_GAS
|
|||
from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError, RpcCallError
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import automation, script
|
||||
from homeassistant.components.automation import automations_with_entity
|
||||
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN
|
||||
from homeassistant.components.script import scripts_with_entity
|
||||
from homeassistant.components.shelly.const import (
|
||||
DOMAIN,
|
||||
MODEL_WALL_DISPLAY,
|
||||
|
@ -30,8 +27,6 @@ from homeassistant.core import HomeAssistant, State
|
|||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.device_registry import DeviceRegistry
|
||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||
import homeassistant.helpers.issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import get_entity_state, init_integration, register_device, register_entity
|
||||
|
||||
|
@ -388,13 +383,12 @@ async def test_rpc_auth_error(
|
|||
assert flow["context"].get("entry_id") == entry.entry_id
|
||||
|
||||
|
||||
async def test_block_device_gas_valve(
|
||||
async def test_remove_gas_valve_switch(
|
||||
hass: HomeAssistant,
|
||||
mock_block_device: Mock,
|
||||
entity_registry: EntityRegistry,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""Test block device Shelly Gas with Valve addon."""
|
||||
"""Test removing deprecated switch entity for Shelly Gas Valve."""
|
||||
entity_id = register_entity(
|
||||
hass,
|
||||
SWITCH_DOMAIN,
|
||||
|
@ -403,41 +397,7 @@ async def test_block_device_gas_valve(
|
|||
)
|
||||
await init_integration(hass, 1, MODEL_GAS)
|
||||
|
||||
entry = entity_registry.async_get(entity_id)
|
||||
assert entry
|
||||
assert entry.unique_id == "123456789ABC-valve_0-valve"
|
||||
|
||||
assert hass.states.get(entity_id).state == STATE_OFF # valve is closed
|
||||
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == STATE_ON # valve is open
|
||||
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == STATE_OFF # valve is closed
|
||||
|
||||
monkeypatch.setattr(mock_block_device.blocks[GAS_VALVE_BLOCK_ID], "valve", "opened")
|
||||
mock_block_device.mock_update()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == STATE_ON # valve is open
|
||||
assert entity_registry.async_get(entity_id) is None
|
||||
|
||||
|
||||
async def test_wall_display_relay_mode(
|
||||
|
@ -470,63 +430,3 @@ async def test_wall_display_relay_mode(
|
|||
entry = entity_registry.async_get(switch_entity_id)
|
||||
assert entry
|
||||
assert entry.unique_id == "123456789ABC-switch:0"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_create_issue_valve_switch(
|
||||
hass: HomeAssistant,
|
||||
mock_block_device: Mock,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test we create an issue when an automation or script is using a deprecated entity."""
|
||||
monkeypatch.setitem(mock_block_device.status, "cloud", {"connected": False})
|
||||
entity_id = register_entity(
|
||||
hass,
|
||||
SWITCH_DOMAIN,
|
||||
"test_name_valve",
|
||||
"valve_0-valve",
|
||||
)
|
||||
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
automation.DOMAIN,
|
||||
{
|
||||
automation.DOMAIN: {
|
||||
"alias": "test",
|
||||
"trigger": {"platform": "state", "entity_id": entity_id},
|
||||
"action": {"service": "switch.turn_on", "entity_id": entity_id},
|
||||
}
|
||||
},
|
||||
)
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
script.DOMAIN,
|
||||
{
|
||||
script.DOMAIN: {
|
||||
"test": {
|
||||
"sequence": [
|
||||
{
|
||||
"service": "switch.turn_on",
|
||||
"data": {"entity_id": entity_id},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
await init_integration(hass, 1, MODEL_GAS)
|
||||
|
||||
assert automations_with_entity(hass, entity_id)[0] == "automation.test"
|
||||
assert scripts_with_entity(hass, entity_id)[0] == "script.test"
|
||||
|
||||
assert issue_registry.async_get_issue(DOMAIN, "deprecated_valve_switch")
|
||||
assert issue_registry.async_get_issue(
|
||||
DOMAIN, "deprecated_valve_switch.test_name_valve_automation.test"
|
||||
)
|
||||
assert issue_registry.async_get_issue(
|
||||
DOMAIN, "deprecated_valve_switch.test_name_valve_script.test"
|
||||
)
|
||||
|
||||
assert len(issue_registry.issues) == 3
|
||||
|
|
Loading…
Reference in New Issue