mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 14:57:09 +00:00
Fixed issue where the device was already disconnected when setting up the event platform (#140722)
* Changed where the script events are collected to remove any device communication from async_setup_entry * Implemented improvements and added a test to test whats happends when script_getcode fails * Renamed script_events to rpc_script_event to make clear this is only for RPC devices Co-authored-by: Shay Levy <levyshay1@gmail.com> --------- Co-authored-by: Shay Levy <levyshay1@gmail.com>
This commit is contained in:
parent
4ed2689678
commit
858f0e6657
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
|
from aioshelly.ble.const import BLE_SCRIPT_NAME
|
||||||
from aioshelly.block_device import BlockDevice
|
from aioshelly.block_device import BlockDevice
|
||||||
from aioshelly.common import ConnectionOptions
|
from aioshelly.common import ConnectionOptions
|
||||||
from aioshelly.const import DEFAULT_COAP_PORT, RPC_GENERATIONS
|
from aioshelly.const import DEFAULT_COAP_PORT, RPC_GENERATIONS
|
||||||
@ -11,6 +12,7 @@ from aioshelly.exceptions import (
|
|||||||
DeviceConnectionError,
|
DeviceConnectionError,
|
||||||
InvalidAuthError,
|
InvalidAuthError,
|
||||||
MacAddressMismatchError,
|
MacAddressMismatchError,
|
||||||
|
RpcCallError,
|
||||||
)
|
)
|
||||||
from aioshelly.rpc_device import RpcDevice, bluetooth_mac_from_primary_mac
|
from aioshelly.rpc_device import RpcDevice, bluetooth_mac_from_primary_mac
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -59,6 +61,7 @@ from .utils import (
|
|||||||
get_coap_context,
|
get_coap_context,
|
||||||
get_device_entry_gen,
|
get_device_entry_gen,
|
||||||
get_http_port,
|
get_http_port,
|
||||||
|
get_rpc_scripts_event_types,
|
||||||
get_ws_context,
|
get_ws_context,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -270,7 +273,10 @@ async def _async_setup_rpc_entry(hass: HomeAssistant, entry: ShellyConfigEntry)
|
|||||||
async_create_issue_unsupported_firmware(hass, entry)
|
async_create_issue_unsupported_firmware(hass, entry)
|
||||||
await device.shutdown()
|
await device.shutdown()
|
||||||
raise ConfigEntryNotReady
|
raise ConfigEntryNotReady
|
||||||
except (DeviceConnectionError, MacAddressMismatchError) as err:
|
runtime_data.rpc_script_events = await get_rpc_scripts_event_types(
|
||||||
|
device, ignore_scripts=[BLE_SCRIPT_NAME]
|
||||||
|
)
|
||||||
|
except (DeviceConnectionError, MacAddressMismatchError, RpcCallError) as err:
|
||||||
await device.shutdown()
|
await device.shutdown()
|
||||||
raise ConfigEntryNotReady(repr(err)) from err
|
raise ConfigEntryNotReady(repr(err)) from err
|
||||||
except InvalidAuthError as err:
|
except InvalidAuthError as err:
|
||||||
|
@ -88,6 +88,7 @@ class ShellyEntryData:
|
|||||||
rest: ShellyRestCoordinator | None = None
|
rest: ShellyRestCoordinator | None = None
|
||||||
rpc: ShellyRpcCoordinator | None = None
|
rpc: ShellyRpcCoordinator | None = None
|
||||||
rpc_poll: ShellyRpcPollingCoordinator | None = None
|
rpc_poll: ShellyRpcPollingCoordinator | None = None
|
||||||
|
rpc_script_events: dict[int, list[str]] | None = None
|
||||||
|
|
||||||
|
|
||||||
type ShellyConfigEntry = ConfigEntry[ShellyEntryData]
|
type ShellyConfigEntry = ConfigEntry[ShellyEntryData]
|
||||||
|
@ -34,7 +34,6 @@ from .utils import (
|
|||||||
get_device_entry_gen,
|
get_device_entry_gen,
|
||||||
get_rpc_entity_name,
|
get_rpc_entity_name,
|
||||||
get_rpc_key_instances,
|
get_rpc_key_instances,
|
||||||
get_rpc_script_event_types,
|
|
||||||
is_block_momentary_input,
|
is_block_momentary_input,
|
||||||
is_rpc_momentary_input,
|
is_rpc_momentary_input,
|
||||||
)
|
)
|
||||||
@ -109,18 +108,15 @@ async def async_setup_entry(
|
|||||||
script_instances = get_rpc_key_instances(
|
script_instances = get_rpc_key_instances(
|
||||||
coordinator.device.status, SCRIPT_EVENT.key
|
coordinator.device.status, SCRIPT_EVENT.key
|
||||||
)
|
)
|
||||||
|
script_events = config_entry.runtime_data.rpc_script_events
|
||||||
for script in script_instances:
|
for script in script_instances:
|
||||||
script_name = get_rpc_entity_name(coordinator.device, script)
|
script_name = get_rpc_entity_name(coordinator.device, script)
|
||||||
if script_name == BLE_SCRIPT_NAME:
|
if script_name == BLE_SCRIPT_NAME:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
event_types = await get_rpc_script_event_types(
|
script_id = int(script.split(":")[-1])
|
||||||
coordinator.device, int(script.split(":")[-1])
|
if script_events and (event_types := script_events[script_id]):
|
||||||
)
|
entities.append(ShellyRpcScriptEvent(coordinator, script, event_types))
|
||||||
if not event_types:
|
|
||||||
continue
|
|
||||||
|
|
||||||
entities.append(ShellyRpcScriptEvent(coordinator, script, event_types))
|
|
||||||
|
|
||||||
# If a script is removed, from the device configuration, we need to remove orphaned entities
|
# If a script is removed, from the device configuration, we need to remove orphaned entities
|
||||||
async_remove_orphaned_entities(
|
async_remove_orphaned_entities(
|
||||||
|
@ -664,3 +664,20 @@ def get_shelly_air_lamp_life(lamp_seconds: int) -> float:
|
|||||||
if lamp_hours >= SHAIR_MAX_WORK_HOURS:
|
if lamp_hours >= SHAIR_MAX_WORK_HOURS:
|
||||||
return 0.0
|
return 0.0
|
||||||
return 100 * (1 - lamp_hours / SHAIR_MAX_WORK_HOURS)
|
return 100 * (1 - lamp_hours / SHAIR_MAX_WORK_HOURS)
|
||||||
|
|
||||||
|
|
||||||
|
async def get_rpc_scripts_event_types(
|
||||||
|
device: RpcDevice, ignore_scripts: list[str]
|
||||||
|
) -> dict[int, list[str]]:
|
||||||
|
"""Return a dict of all scripts and their event types."""
|
||||||
|
script_instances = get_rpc_key_instances(device.status, "script")
|
||||||
|
script_events = {}
|
||||||
|
for script in script_instances:
|
||||||
|
script_name = get_rpc_entity_name(device, script)
|
||||||
|
if script_name in ignore_scripts:
|
||||||
|
continue
|
||||||
|
|
||||||
|
script_id = int(script.split(":")[-1])
|
||||||
|
script_events[script_id] = await get_rpc_script_event_types(device, script_id)
|
||||||
|
|
||||||
|
return script_events
|
||||||
|
@ -513,6 +513,9 @@ def _mock_blu_rtv_device(version: str | None = None):
|
|||||||
firmware_version="some fw string",
|
firmware_version="some fw string",
|
||||||
initialized=True,
|
initialized=True,
|
||||||
connected=True,
|
connected=True,
|
||||||
|
script_getcode=AsyncMock(
|
||||||
|
side_effect=lambda script_id: {"data": MOCK_SCRIPTS[script_id - 1]}
|
||||||
|
),
|
||||||
xmod_info={},
|
xmod_info={},
|
||||||
)
|
)
|
||||||
type(device).name = PropertyMock(return_value="Test name")
|
type(device).name = PropertyMock(return_value="Test name")
|
||||||
|
@ -10,6 +10,7 @@ from aioshelly.exceptions import (
|
|||||||
DeviceConnectionError,
|
DeviceConnectionError,
|
||||||
InvalidAuthError,
|
InvalidAuthError,
|
||||||
MacAddressMismatchError,
|
MacAddressMismatchError,
|
||||||
|
RpcCallError,
|
||||||
)
|
)
|
||||||
from aioshelly.rpc_device.utils import bluetooth_mac_from_primary_mac
|
from aioshelly.rpc_device.utils import bluetooth_mac_from_primary_mac
|
||||||
import pytest
|
import pytest
|
||||||
@ -555,3 +556,17 @@ async def test_bluetooth_cleanup_on_remove_entry(
|
|||||||
remove_mock.assert_called_once_with(
|
remove_mock.assert_called_once_with(
|
||||||
hass, format_mac(bluetooth_mac_from_primary_mac(entry.unique_id)).upper()
|
hass, format_mac(bluetooth_mac_from_primary_mac(entry.unique_id)).upper()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_device_script_getcode_error(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_rpc_device: Mock,
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
) -> None:
|
||||||
|
"""Test device script get code error."""
|
||||||
|
monkeypatch.setattr(
|
||||||
|
mock_rpc_device, "script_getcode", AsyncMock(side_effect=RpcCallError(0))
|
||||||
|
)
|
||||||
|
|
||||||
|
entry = await init_integration(hass, 2)
|
||||||
|
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||||
|
Loading…
x
Reference in New Issue
Block a user