Updated changes for aioshelly 1.0.0 (#56083)

This commit is contained in:
Shay Levy 2021-09-11 00:48:55 +03:00 committed by GitHub
parent ac1251c52b
commit 8c3c2ad8e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 108 additions and 86 deletions

View file

@ -7,6 +7,7 @@ import logging
from typing import Any, Final, cast
import aioshelly
from aioshelly.block_device import BlockDevice
import async_timeout
import voluptuous as vol
@ -89,7 +90,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
temperature_unit = "C" if hass.config.units.is_metric else "F"
options = aioshelly.ConnectionOptions(
options = aioshelly.common.ConnectionOptions(
entry.data[CONF_HOST],
entry.data.get(CONF_USERNAME),
entry.data.get(CONF_PASSWORD),
@ -98,7 +99,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
coap_context = await get_coap_context(hass)
device = await aioshelly.Device.create(
device = await BlockDevice.create(
aiohttp_client.async_get_clientsession(hass),
coap_context,
options,
@ -134,7 +135,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
_LOGGER.debug("Setting up online device %s", entry.title)
try:
async with async_timeout.timeout(AIOSHELLY_DEVICE_TIMEOUT_SEC):
await device.initialize(True)
await device.initialize()
except (asyncio.TimeoutError, OSError) as err:
raise ConfigEntryNotReady from err
@ -146,7 +147,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"Setup for device %s will resume when device is online", entry.title
)
device.subscribe_updates(_async_device_online)
await device.coap_request("s")
else:
# Restore sensors for sleeping device
_LOGGER.debug("Setting up offline device %s", entry.title)
@ -156,7 +156,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_device_setup(
hass: HomeAssistant, entry: ConfigEntry, device: aioshelly.Device
hass: HomeAssistant, entry: ConfigEntry, device: BlockDevice
) -> None:
"""Set up a device that is online."""
device_wrapper = hass.data[DOMAIN][DATA_CONFIG_ENTRY][entry.entry_id][
@ -179,7 +179,7 @@ class ShellyDeviceWrapper(update_coordinator.DataUpdateCoordinator):
"""Wrapper for a Shelly device with Home Assistant specific functions."""
def __init__(
self, hass: HomeAssistant, entry: ConfigEntry, device: aioshelly.Device
self, hass: HomeAssistant, entry: ConfigEntry, device: BlockDevice
) -> None:
"""Initialize the Shelly device wrapper."""
self.device_id: str | None = None
@ -208,7 +208,9 @@ class ShellyDeviceWrapper(update_coordinator.DataUpdateCoordinator):
)
self._last_input_events_count: dict = {}
entry.async_on_unload(
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self._handle_ha_stop)
)
@callback
def _async_device_updates_handler(self) -> None:
@ -216,6 +218,8 @@ class ShellyDeviceWrapper(update_coordinator.DataUpdateCoordinator):
if not self.device.initialized:
return
assert self.device.blocks
# For buttons which are battery powered - set initial value for last_event_count
if self.model in SHBTN_MODELS and self._last_input_events_count.get(1) is None:
for block in self.device.blocks:
@ -298,7 +302,7 @@ class ShellyDeviceWrapper(update_coordinator.DataUpdateCoordinator):
# This is duplicate but otherwise via_device can't work
identifiers={(DOMAIN, self.mac)},
manufacturer="Shelly",
model=aioshelly.MODEL_NAMES.get(self.model, self.model),
model=aioshelly.const.MODEL_NAMES.get(self.model, self.model),
sw_version=sw_version,
)
self.device_id = entry.id
@ -306,10 +310,8 @@ class ShellyDeviceWrapper(update_coordinator.DataUpdateCoordinator):
def shutdown(self) -> None:
"""Shutdown the wrapper."""
if self.device:
self.device.shutdown()
self._async_remove_device_updates_handler()
self.device = None
@callback
def _handle_ha_stop(self, _event: Event) -> None:
@ -321,7 +323,7 @@ class ShellyDeviceWrapper(update_coordinator.DataUpdateCoordinator):
class ShellyDeviceRestWrapper(update_coordinator.DataUpdateCoordinator):
"""Rest Wrapper for a Shelly device with Home Assistant specific functions."""
def __init__(self, hass: HomeAssistant, device: aioshelly.Device) -> None:
def __init__(self, hass: HomeAssistant, device: BlockDevice) -> None:
"""Initialize the Shelly device wrapper."""
if (
device.settings["device"]["type"]

View file

@ -48,7 +48,7 @@ SENSORS: Final = {
("sensor", "dwIsOpened"): BlockAttributeDescription(
name="Door",
device_class=DEVICE_CLASS_OPENING,
available=lambda block: cast(bool, block.dwIsOpened != -1),
available=lambda block: cast(int, block.dwIsOpened) != -1,
),
("sensor", "flood"): BlockAttributeDescription(
name="Flood", device_class=DEVICE_CLASS_MOISTURE

View file

@ -7,6 +7,7 @@ from typing import Any, Dict, Final, cast
import aiohttp
import aioshelly
from aioshelly.block_device import BlockDevice
import async_timeout
import voluptuous as vol
@ -39,13 +40,13 @@ async def validate_input(
Data has the keys from DATA_SCHEMA with values provided by the user.
"""
options = aioshelly.ConnectionOptions(
options = aioshelly.common.ConnectionOptions(
host, data.get(CONF_USERNAME), data.get(CONF_PASSWORD)
)
coap_context = await get_coap_context(hass)
async with async_timeout.timeout(AIOSHELLY_DEVICE_TIMEOUT_SEC):
device = await aioshelly.Device.create(
device = await BlockDevice.create(
aiohttp_client.async_get_clientsession(hass),
coap_context,
options,
@ -82,7 +83,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
info = await self._async_get_info(host)
except HTTP_CONNECT_ERRORS:
errors["base"] = "cannot_connect"
except aioshelly.FirmwareUnsupported:
except aioshelly.exceptions.FirmwareUnsupported:
return self.async_abort(reason="unsupported_firmware")
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
@ -165,7 +166,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self.info = info = await self._async_get_info(discovery_info["host"])
except HTTP_CONNECT_ERRORS:
return self.async_abort(reason="cannot_connect")
except aioshelly.FirmwareUnsupported:
except aioshelly.exceptions.FirmwareUnsupported:
return self.async_abort(reason="unsupported_firmware")
await self.async_set_unique_id(info["mac"])
@ -206,7 +207,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
return self.async_show_form(
step_id="confirm_discovery",
description_placeholders={
"model": aioshelly.MODEL_NAMES.get(
"model": aioshelly.const.MODEL_NAMES.get(
self.info["type"], self.info["type"]
),
"host": self.host,
@ -219,7 +220,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async with async_timeout.timeout(AIOSHELLY_DEVICE_TIMEOUT_SEC):
return cast(
Dict[str, Any],
await aioshelly.get_info(
await aioshelly.common.get_info(
aiohttp_client.async_get_clientsession(self.hass),
host,
),

View file

@ -3,7 +3,7 @@ from __future__ import annotations
from typing import Any, cast
from aioshelly import Block
from aioshelly.block_device import Block
from homeassistant.components.cover import (
ATTR_POSITION,
@ -57,7 +57,7 @@ class ShellyCover(ShellyBlockEntity, CoverEntity):
if self.control_result:
return cast(bool, self.control_result["current_pos"] == 0)
return cast(bool, self.block.rollerPos == 0)
return cast(int, self.block.rollerPos) == 0
@property
def current_cover_position(self) -> int:
@ -73,7 +73,7 @@ class ShellyCover(ShellyBlockEntity, CoverEntity):
if self.control_result:
return cast(bool, self.control_result["state"] == "close")
return cast(bool, self.block.roller == "close")
return self.block.roller == "close"
@property
def is_opening(self) -> bool:
@ -81,7 +81,7 @@ class ShellyCover(ShellyBlockEntity, CoverEntity):
if self.control_result:
return cast(bool, self.control_result["state"] == "open")
return cast(bool, self.block.roller == "open")
return self.block.roller == "open"
@property
def supported_features(self) -> int:

View file

@ -60,6 +60,8 @@ async def async_validate_trigger_config(
trigger = (config[CONF_TYPE], config[CONF_SUBTYPE])
assert wrapper.device.blocks
for block in wrapper.device.blocks:
input_triggers = get_input_triggers(wrapper.device, block)
if trigger in input_triggers:
@ -93,6 +95,8 @@ async def async_get_triggers(
)
return triggers
assert wrapper.device.blocks
for block in wrapper.device.blocks:
input_triggers = get_input_triggers(wrapper.device, block)

View file

@ -6,7 +6,7 @@ from dataclasses import dataclass
import logging
from typing import Any, Callable, Final, cast
import aioshelly
from aioshelly.block_device import Block
import async_timeout
from homeassistant.components.sensor import ATTR_STATE_CLASS
@ -62,6 +62,8 @@ async def async_setup_block_attribute_entities(
"""Set up entities for block attributes."""
blocks = []
assert wrapper.device.blocks
for block in wrapper.device.blocks:
for sensor_id in block.sensor_ids:
description = sensors.get((block.type, sensor_id))
@ -175,10 +177,10 @@ class BlockAttributeDescription:
device_class: str | None = None
state_class: str | None = None
default_enabled: bool = True
available: Callable[[aioshelly.Block], bool] | None = None
available: Callable[[Block], bool] | None = None
# Callable (settings, block), return true if entity should be removed
removal_condition: Callable[[dict, aioshelly.Block], bool] | None = None
extra_state_attributes: Callable[[aioshelly.Block], dict | None] | None = None
removal_condition: Callable[[dict, Block], bool] | None = None
extra_state_attributes: Callable[[Block], dict | None] | None = None
@dataclass
@ -198,7 +200,7 @@ class RestAttributeDescription:
class ShellyBlockEntity(entity.Entity):
"""Helper class to represent a block."""
def __init__(self, wrapper: ShellyDeviceWrapper, block: aioshelly.Block) -> None:
def __init__(self, wrapper: ShellyDeviceWrapper, block: Block) -> None:
"""Initialize Shelly entity."""
self.wrapper = wrapper
self.block = block
@ -267,7 +269,7 @@ class ShellyBlockAttributeEntity(ShellyBlockEntity, entity.Entity):
def __init__(
self,
wrapper: ShellyDeviceWrapper,
block: aioshelly.Block,
block: Block,
attribute: str,
description: BlockAttributeDescription,
) -> None:
@ -418,7 +420,7 @@ class ShellySleepingBlockAttributeEntity(ShellyBlockAttributeEntity, RestoreEnti
def __init__(
self,
wrapper: ShellyDeviceWrapper,
block: aioshelly.Block,
block: Block | None,
attribute: str,
description: BlockAttributeDescription,
entry: entity_registry.RegistryEntry | None = None,
@ -429,7 +431,7 @@ class ShellySleepingBlockAttributeEntity(ShellyBlockAttributeEntity, RestoreEnti
self.last_state: StateType = None
self.wrapper = wrapper
self.attribute = attribute
self.block = block
self.block: Block | None = block # type: ignore[assignment]
self.description = description
self._unit = self.description.unit
@ -468,6 +470,8 @@ class ShellySleepingBlockAttributeEntity(ShellyBlockAttributeEntity, RestoreEnti
_, entity_block, entity_sensor = self.unique_id.split("-")
assert self.wrapper.device.blocks
for block in self.wrapper.device.blocks:
if block.description != entity_block:
continue

View file

@ -5,7 +5,7 @@ import asyncio
import logging
from typing import Any, Final, cast
from aioshelly import Block
from aioshelly.block_device import Block
import async_timeout
from homeassistant.components.light import (
@ -117,7 +117,7 @@ class ShellyLight(ShellyBlockEntity, LightEntity):
self._supported_features |= SUPPORT_EFFECT
if wrapper.model in MODELS_SUPPORTING_LIGHT_TRANSITION:
match = FIRMWARE_PATTERN.search(wrapper.device.settings.get("fw"))
match = FIRMWARE_PATTERN.search(wrapper.device.settings.get("fw", ""))
if (
match is not None
and int(match[0]) >= LIGHT_TRANSITION_MIN_FIRMWARE_DATE

View file

@ -3,7 +3,7 @@
"name": "Shelly",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/shelly",
"requirements": ["aioshelly==0.6.4"],
"requirements": ["aioshelly==1.0.0"],
"zeroconf": [
{
"type": "_http._tcp.local.",

View file

@ -40,7 +40,7 @@ SENSORS: Final = {
device_class=sensor.DEVICE_CLASS_BATTERY,
state_class=sensor.STATE_CLASS_MEASUREMENT,
removal_condition=lambda settings, _: settings.get("external_power") == 1,
available=lambda block: cast(bool, block.battery != -1),
available=lambda block: cast(int, block.battery) != -1,
),
("device", "deviceTemp"): BlockAttributeDescription(
name="Device Temperature",
@ -162,7 +162,7 @@ SENSORS: Final = {
value=lambda value: round(value, 1),
device_class=sensor.DEVICE_CLASS_TEMPERATURE,
state_class=sensor.STATE_CLASS_MEASUREMENT,
available=lambda block: cast(bool, block.extTemp != 999),
available=lambda block: cast(int, block.extTemp) != 999,
),
("sensor", "humidity"): BlockAttributeDescription(
name="Humidity",
@ -170,14 +170,14 @@ SENSORS: Final = {
value=lambda value: round(value, 1),
device_class=sensor.DEVICE_CLASS_HUMIDITY,
state_class=sensor.STATE_CLASS_MEASUREMENT,
available=lambda block: cast(bool, block.extTemp != 999),
available=lambda block: cast(int, block.extTemp) != 999,
),
("sensor", "luminosity"): BlockAttributeDescription(
name="Luminosity",
unit=LIGHT_LUX,
device_class=sensor.DEVICE_CLASS_ILLUMINANCE,
state_class=sensor.STATE_CLASS_MEASUREMENT,
available=lambda block: cast(bool, block.luminosity != -1),
available=lambda block: cast(int, block.luminosity) != -1,
),
("sensor", "tilt"): BlockAttributeDescription(
name="Tilt",
@ -191,7 +191,7 @@ SENSORS: Final = {
icon="mdi:progress-wrench",
value=lambda value: round(100 - (value / 3600 / SHAIR_MAX_WORK_HOURS), 1),
extra_state_attributes=lambda block: {
"Operational hours": round(block.totalWorkTime / 3600, 1)
"Operational hours": round(cast(int, block.totalWorkTime) / 3600, 1)
},
),
("adc", "adc"): BlockAttributeDescription(

View file

@ -3,7 +3,7 @@ from __future__ import annotations
from typing import Any, cast
from aioshelly import Block
from aioshelly.block_device import Block
from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry

View file

@ -5,7 +5,7 @@ from datetime import datetime, timedelta
import logging
from typing import Any, Final, cast
import aioshelly
from aioshelly.block_device import BLOCK_VALUE_UNIT, COAP, Block, BlockDevice
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, TEMP_CELSIUS, TEMP_FAHRENHEIT
from homeassistant.core import HomeAssistant, callback
@ -40,18 +40,20 @@ async def async_remove_shelly_entity(
def temperature_unit(block_info: dict[str, Any]) -> str:
"""Detect temperature unit."""
if block_info[aioshelly.BLOCK_VALUE_UNIT] == "F":
if block_info[BLOCK_VALUE_UNIT] == "F":
return TEMP_FAHRENHEIT
return TEMP_CELSIUS
def get_device_name(device: aioshelly.Device) -> str:
def get_device_name(device: BlockDevice) -> str:
"""Naming for device."""
return cast(str, device.settings["name"] or device.settings["device"]["hostname"])
def get_number_of_channels(device: aioshelly.Device, block: aioshelly.Block) -> int:
def get_number_of_channels(device: BlockDevice, block: Block) -> int:
"""Get number of channels for block type."""
assert isinstance(device.shelly, dict)
channels = None
if block.type == "input":
@ -71,8 +73,8 @@ def get_number_of_channels(device: aioshelly.Device, block: aioshelly.Block) ->
def get_entity_name(
device: aioshelly.Device,
block: aioshelly.Block,
device: BlockDevice,
block: Block | None,
description: str | None = None,
) -> str:
"""Naming for switch and sensors."""
@ -84,10 +86,7 @@ def get_entity_name(
return channel_name
def get_device_channel_name(
device: aioshelly.Device,
block: aioshelly.Block,
) -> str:
def get_device_channel_name(device: BlockDevice, block: Block | None) -> str:
"""Get name based on device and channel name."""
entity_name = get_device_name(device)
@ -98,8 +97,10 @@ def get_device_channel_name(
):
return entity_name
assert block.channel
channel_name: str | None = None
mode = block.type + "s"
mode = cast(str, block.type) + "s"
if mode in device.settings:
channel_name = device.settings[mode][int(block.channel)].get("name")
@ -114,7 +115,7 @@ def get_device_channel_name(
return f"{entity_name} channel {chr(int(block.channel)+base)}"
def is_momentary_input(settings: dict[str, Any], block: aioshelly.Block) -> bool:
def is_momentary_input(settings: dict[str, Any], block: Block) -> bool:
"""Return true if input button settings is set to a momentary type."""
# Shelly Button type is fixed to momentary and no btn_type
if settings["device"]["type"] in SHBTN_MODELS:
@ -150,9 +151,7 @@ def get_device_uptime(status: dict[str, Any], last_uptime: str | None) -> str:
return last_uptime
def get_input_triggers(
device: aioshelly.Device, block: aioshelly.Block
) -> list[tuple[str, str]]:
def get_input_triggers(device: BlockDevice, block: Block) -> list[tuple[str, str]]:
"""Return list of input triggers for block."""
if "inputEvent" not in block.sensor_ids or "inputEventCnt" not in block.sensor_ids:
return []
@ -165,6 +164,7 @@ def get_input_triggers(
if block.type == "device" or get_number_of_channels(device, block) == 1:
subtype = "button"
else:
assert block.channel
subtype = f"button{int(block.channel)+1}"
if device.settings["device"]["type"] in SHBTN_MODELS:
@ -181,9 +181,9 @@ def get_input_triggers(
@singleton.singleton("shelly_coap")
async def get_coap_context(hass: HomeAssistant) -> aioshelly.COAP:
async def get_coap_context(hass: HomeAssistant) -> COAP:
"""Get CoAP context to be used in all Shelly devices."""
context = aioshelly.COAP()
context = COAP()
if DOMAIN in hass.data:
port = hass.data[DOMAIN].get(CONF_COAP_PORT, DEFAULT_COAP_PORT)
else:

View file

@ -240,7 +240,7 @@ aiopylgtv==0.4.0
aiorecollect==1.0.8
# homeassistant.components.shelly
aioshelly==0.6.4
aioshelly==1.0.0
# homeassistant.components.switcher_kis
aioswitcher==2.0.5

View file

@ -161,7 +161,7 @@ aiopylgtv==0.4.0
aiorecollect==1.0.8
# homeassistant.components.shelly
aioshelly==0.6.4
aioshelly==1.0.0
# homeassistant.components.switcher_kis
aioswitcher==2.0.5

View file

@ -32,10 +32,10 @@ async def test_form(hass):
assert result["errors"] == {}
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False},
), patch(
"aioshelly.Device.create",
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(
return_value=Mock(
settings=MOCK_SETTINGS,
@ -78,10 +78,10 @@ async def test_title_without_name(hass):
settings["device"] = settings["device"].copy()
settings["device"]["hostname"] = "shelly1pm-12345"
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False},
), patch(
"aioshelly.Device.create",
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(
return_value=Mock(
settings=settings,
@ -119,7 +119,7 @@ async def test_form_auth(hass):
assert result["errors"] == {}
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={"mac": "test-mac", "type": "SHSW-1", "auth": True},
):
result2 = await hass.config_entries.flow.async_configure(
@ -131,7 +131,7 @@ async def test_form_auth(hass):
assert result["errors"] == {}
with patch(
"aioshelly.Device.create",
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(
return_value=Mock(
settings=MOCK_SETTINGS,
@ -172,7 +172,7 @@ async def test_form_errors_get_info(hass, error):
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch("aioshelly.get_info", side_effect=exc):
with patch("aioshelly.common.get_info", side_effect=exc):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"host": "1.1.1.1"},
@ -193,8 +193,10 @@ async def test_form_errors_test_connection(hass, error):
)
with patch(
"aioshelly.get_info", return_value={"mac": "test-mac", "auth": False}
), patch("aioshelly.Device.create", new=AsyncMock(side_effect=exc)):
"aioshelly.common.get_info", return_value={"mac": "test-mac", "auth": False}
), patch(
"aioshelly.block_device.BlockDevice.create", new=AsyncMock(side_effect=exc)
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"host": "1.1.1.1"},
@ -217,7 +219,7 @@ async def test_form_already_configured(hass):
)
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False},
):
result2 = await hass.config_entries.flow.async_configure(
@ -252,10 +254,10 @@ async def test_user_setup_ignored_device(hass):
settings["fw"] = "20201124-092534/v1.9.0@57ac4ad8"
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False},
), patch(
"aioshelly.Device.create",
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(
return_value=Mock(
settings=settings,
@ -287,7 +289,10 @@ async def test_form_firmware_unsupported(hass):
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch("aioshelly.get_info", side_effect=aioshelly.FirmwareUnsupported):
with patch(
"aioshelly.common.get_info",
side_effect=aioshelly.exceptions.FirmwareUnsupported,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"host": "1.1.1.1"},
@ -313,14 +318,17 @@ async def test_form_auth_errors_test_connection(hass, error):
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch("aioshelly.get_info", return_value={"mac": "test-mac", "auth": True}):
with patch(
"aioshelly.common.get_info",
return_value={"mac": "test-mac", "auth": True},
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"host": "1.1.1.1"},
)
with patch(
"aioshelly.Device.create",
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(side_effect=exc),
):
result3 = await hass.config_entries.flow.async_configure(
@ -336,10 +344,10 @@ async def test_zeroconf(hass):
await setup.async_setup_component(hass, "persistent_notification", {})
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False},
), patch(
"aioshelly.Device.create",
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(
return_value=Mock(
settings=MOCK_SETTINGS,
@ -388,7 +396,7 @@ async def test_zeroconf_sleeping_device(hass):
await setup.async_setup_component(hass, "persistent_notification", {})
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={
"mac": "test-mac",
"type": "SHSW-1",
@ -396,7 +404,7 @@ async def test_zeroconf_sleeping_device(hass):
"sleep_mode": True,
},
), patch(
"aioshelly.Device.create",
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(
return_value=Mock(
settings={
@ -460,7 +468,7 @@ async def test_zeroconf_sleeping_device_error(hass, error):
await setup.async_setup_component(hass, "persistent_notification", {})
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={
"mac": "test-mac",
"type": "SHSW-1",
@ -468,7 +476,7 @@ async def test_zeroconf_sleeping_device_error(hass, error):
"sleep_mode": True,
},
), patch(
"aioshelly.Device.create",
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(side_effect=exc),
):
result = await hass.config_entries.flow.async_init(
@ -489,7 +497,7 @@ async def test_zeroconf_already_configured(hass):
entry.add_to_hass(hass)
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False},
):
result = await hass.config_entries.flow.async_init(
@ -506,7 +514,10 @@ async def test_zeroconf_already_configured(hass):
async def test_zeroconf_firmware_unsupported(hass):
"""Test we abort if device firmware is unsupported."""
with patch("aioshelly.get_info", side_effect=aioshelly.FirmwareUnsupported):
with patch(
"aioshelly.common.get_info",
side_effect=aioshelly.exceptions.FirmwareUnsupported,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
data=DISCOVERY_INFO,
@ -519,7 +530,7 @@ async def test_zeroconf_firmware_unsupported(hass):
async def test_zeroconf_cannot_connect(hass):
"""Test we get the form."""
with patch("aioshelly.get_info", side_effect=asyncio.TimeoutError):
with patch("aioshelly.common.get_info", side_effect=asyncio.TimeoutError):
result = await hass.config_entries.flow.async_init(
DOMAIN,
data=DISCOVERY_INFO,
@ -534,7 +545,7 @@ async def test_zeroconf_require_auth(hass):
await setup.async_setup_component(hass, "persistent_notification", {})
with patch(
"aioshelly.get_info",
"aioshelly.common.get_info",
return_value={"mac": "test-mac", "type": "SHSW-1", "auth": True},
):
result = await hass.config_entries.flow.async_init(
@ -546,7 +557,7 @@ async def test_zeroconf_require_auth(hass):
assert result["errors"] == {}
with patch(
"aioshelly.Device.create",
"aioshelly.block_device.BlockDevice.create",
new=AsyncMock(
return_value=Mock(
settings=MOCK_SETTINGS,