mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Add Refoss integration (#100573)
* refoss * refoss * refoss * refoss * refoss modify * ip * 8.22 * format * format * format * bugfix * test * test * test * test * test * test * 9.1 * refosss * refoss * refoss * refoss * refoss * refoss * refoss * refoss * test * requirements_test_all.txt * codeowners * refoss * Review feedback repair * strings * refoss * refoss * refoss * 1.1.1 * 1.1.2 * refoss * refoss * refoss.1.1.7 * refoss-gree * 1.1.7 * test * refoss * test refoss * test refoss * refoss-test * refoss * refoss * test * test * refoss * CODEOWNERS * fix * Update homeassistant/components/refoss/__init__.py --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
f536bc1d0c
commit
102c7f1959
@ -1035,6 +1035,12 @@ omit =
|
||||
homeassistant/components/recorder/repack.py
|
||||
homeassistant/components/recswitch/switch.py
|
||||
homeassistant/components/reddit/sensor.py
|
||||
homeassistant/components/refoss/__init__.py
|
||||
homeassistant/components/refoss/bridge.py
|
||||
homeassistant/components/refoss/coordinator.py
|
||||
homeassistant/components/refoss/entity.py
|
||||
homeassistant/components/refoss/switch.py
|
||||
homeassistant/components/refoss/util.py
|
||||
homeassistant/components/rejseplanen/sensor.py
|
||||
homeassistant/components/remember_the_milk/__init__.py
|
||||
homeassistant/components/remote_rpi_gpio/*
|
||||
|
@ -1056,6 +1056,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/recorder/ @home-assistant/core
|
||||
/homeassistant/components/recovery_mode/ @home-assistant/core
|
||||
/tests/components/recovery_mode/ @home-assistant/core
|
||||
/homeassistant/components/refoss/ @ashionky
|
||||
/tests/components/refoss/ @ashionky
|
||||
/homeassistant/components/rejseplanen/ @DarkFox
|
||||
/homeassistant/components/remote/ @home-assistant/core
|
||||
/tests/components/remote/ @home-assistant/core
|
||||
|
56
homeassistant/components/refoss/__init__.py
Normal file
56
homeassistant/components/refoss/__init__.py
Normal file
@ -0,0 +1,56 @@
|
||||
"""Refoss devices platform loader."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import Final
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
|
||||
from .bridge import DiscoveryService
|
||||
from .const import COORDINATORS, DATA_DISCOVERY_SERVICE, DISCOVERY_SCAN_INTERVAL, DOMAIN
|
||||
from .util import refoss_discovery_server
|
||||
|
||||
PLATFORMS: Final = [
|
||||
Platform.SWITCH,
|
||||
]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Refoss from a config entry."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
discover = await refoss_discovery_server(hass)
|
||||
refoss_discovery = DiscoveryService(hass, discover)
|
||||
hass.data[DOMAIN][DATA_DISCOVERY_SERVICE] = refoss_discovery
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
async def _async_scan_update(_=None):
|
||||
await refoss_discovery.discovery.broadcast_msg()
|
||||
|
||||
await _async_scan_update()
|
||||
|
||||
entry.async_on_unload(
|
||||
async_track_time_interval(
|
||||
hass, _async_scan_update, timedelta(seconds=DISCOVERY_SCAN_INTERVAL)
|
||||
)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
if hass.data[DOMAIN].get(DATA_DISCOVERY_SERVICE) is not None:
|
||||
refoss_discovery: DiscoveryService = hass.data[DOMAIN][DATA_DISCOVERY_SERVICE]
|
||||
refoss_discovery.discovery.clean_up()
|
||||
hass.data[DOMAIN].pop(DATA_DISCOVERY_SERVICE)
|
||||
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
||||
if unload_ok:
|
||||
hass.data[DOMAIN].pop(COORDINATORS)
|
||||
|
||||
return unload_ok
|
45
homeassistant/components/refoss/bridge.py
Normal file
45
homeassistant/components/refoss/bridge.py
Normal file
@ -0,0 +1,45 @@
|
||||
"""Refoss integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
from refoss_ha.device import DeviceInfo
|
||||
from refoss_ha.device_manager import async_build_base_device
|
||||
from refoss_ha.discovery import Discovery, Listener
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
from .const import COORDINATORS, DISPATCH_DEVICE_DISCOVERED, DOMAIN
|
||||
from .coordinator import RefossDataUpdateCoordinator
|
||||
|
||||
|
||||
class DiscoveryService(Listener):
|
||||
"""Discovery event handler for refoss devices."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, discovery: Discovery) -> None:
|
||||
"""Init discovery service."""
|
||||
self.hass = hass
|
||||
|
||||
self.discovery = discovery
|
||||
self.discovery.add_listener(self)
|
||||
|
||||
hass.data[DOMAIN].setdefault(COORDINATORS, [])
|
||||
|
||||
async def device_found(self, device_info: DeviceInfo) -> None:
|
||||
"""Handle new device found on the network."""
|
||||
|
||||
device = await async_build_base_device(device_info)
|
||||
if device is None:
|
||||
return None
|
||||
|
||||
coordo = RefossDataUpdateCoordinator(self.hass, device)
|
||||
self.hass.data[DOMAIN][COORDINATORS].append(coordo)
|
||||
await coordo.async_refresh()
|
||||
|
||||
async_dispatcher_send(self.hass, DISPATCH_DEVICE_DISCOVERED, coordo)
|
||||
|
||||
async def device_update(self, device_info: DeviceInfo) -> None:
|
||||
"""Handle updates in device information, update if ip has changed."""
|
||||
for coordinator in self.hass.data[DOMAIN][COORDINATORS]:
|
||||
if coordinator.device.device_info.mac == device_info.mac:
|
||||
coordinator.device.device_info.inner_ip = device_info.inner_ip
|
||||
await coordinator.async_refresh()
|
20
homeassistant/components/refoss/config_flow.py
Normal file
20
homeassistant/components/refoss/config_flow.py
Normal file
@ -0,0 +1,20 @@
|
||||
"""Config Flow for Refoss integration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import config_entry_flow
|
||||
|
||||
from .const import DISCOVERY_TIMEOUT, DOMAIN
|
||||
from .util import refoss_discovery_server
|
||||
|
||||
|
||||
async def _async_has_devices(hass: HomeAssistant) -> bool:
|
||||
"""Return if there are devices that can be discovered."""
|
||||
|
||||
refoss_discovery = await refoss_discovery_server(hass)
|
||||
devices = await refoss_discovery.broadcast_msg(wait_for=DISCOVERY_TIMEOUT)
|
||||
return len(devices) > 0
|
||||
|
||||
|
||||
config_entry_flow.register_discovery_flow(DOMAIN, "Refoss", _async_has_devices)
|
20
homeassistant/components/refoss/const.py
Normal file
20
homeassistant/components/refoss/const.py
Normal file
@ -0,0 +1,20 @@
|
||||
"""const."""
|
||||
from __future__ import annotations
|
||||
|
||||
from logging import Logger, getLogger
|
||||
|
||||
_LOGGER: Logger = getLogger(__package__)
|
||||
|
||||
COORDINATORS = "coordinators"
|
||||
|
||||
DATA_DISCOVERY_SERVICE = "refoss_discovery"
|
||||
|
||||
DISCOVERY_SCAN_INTERVAL = 30
|
||||
DISCOVERY_TIMEOUT = 8
|
||||
DISPATCH_DEVICE_DISCOVERED = "refoss_device_discovered"
|
||||
DISPATCHERS = "dispatchers"
|
||||
|
||||
DOMAIN = "refoss"
|
||||
COORDINATOR = "coordinator"
|
||||
|
||||
MAX_ERRORS = 2
|
39
homeassistant/components/refoss/coordinator.py
Normal file
39
homeassistant/components/refoss/coordinator.py
Normal file
@ -0,0 +1,39 @@
|
||||
"""Helper and coordinator for refoss."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from refoss_ha.controller.device import BaseDevice
|
||||
from refoss_ha.exceptions import DeviceTimeoutError
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from .const import _LOGGER, DOMAIN, MAX_ERRORS
|
||||
|
||||
|
||||
class RefossDataUpdateCoordinator(DataUpdateCoordinator[None]):
|
||||
"""Manages polling for state changes from the device."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, device: BaseDevice) -> None:
|
||||
"""Initialize the data update coordinator."""
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
name=f"{DOMAIN}-{device.device_info.dev_name}",
|
||||
update_interval=timedelta(seconds=15),
|
||||
)
|
||||
self.device = device
|
||||
self._error_count = 0
|
||||
|
||||
async def _async_update_data(self) -> None:
|
||||
"""Update the state of the device."""
|
||||
try:
|
||||
await self.device.async_handle_update()
|
||||
self.last_update_success = True
|
||||
self._error_count = 0
|
||||
except DeviceTimeoutError:
|
||||
self._error_count += 1
|
||||
|
||||
if self._error_count >= MAX_ERRORS:
|
||||
self.last_update_success = False
|
31
homeassistant/components/refoss/entity.py
Normal file
31
homeassistant/components/refoss/entity.py
Normal file
@ -0,0 +1,31 @@
|
||||
"""Entity object for shared properties of Refoss entities."""
|
||||
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .bridge import RefossDataUpdateCoordinator
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
class RefossEntity(CoordinatorEntity[RefossDataUpdateCoordinator]):
|
||||
"""Refoss entity."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(self, coordinator: RefossDataUpdateCoordinator, channel: int) -> None:
|
||||
"""Initialize the entity."""
|
||||
super().__init__(coordinator)
|
||||
|
||||
mac = coordinator.device.mac
|
||||
self.channel_id = channel
|
||||
if channel == 0:
|
||||
self._attr_name = None
|
||||
else:
|
||||
self._attr_name = str(channel)
|
||||
|
||||
self._attr_unique_id = f"{mac}_{channel}"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
connections={(CONNECTION_NETWORK_MAC, mac)},
|
||||
identifiers={(DOMAIN, mac)},
|
||||
manufacturer="Refoss",
|
||||
name=coordinator.device.dev_name,
|
||||
)
|
9
homeassistant/components/refoss/manifest.json
Normal file
9
homeassistant/components/refoss/manifest.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"domain": "refoss",
|
||||
"name": "Refoss",
|
||||
"codeowners": ["@ashionky"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/refoss",
|
||||
"iot_class": "local_polling",
|
||||
"requirements": ["refoss-ha==1.2.0"]
|
||||
}
|
13
homeassistant/components/refoss/strings.json
Normal file
13
homeassistant/components/refoss/strings.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "[%key:common::config_flow::description::confirm_setup%]"
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]"
|
||||
}
|
||||
}
|
||||
}
|
69
homeassistant/components/refoss/switch.py
Normal file
69
homeassistant/components/refoss/switch.py
Normal file
@ -0,0 +1,69 @@
|
||||
"""Switch for Refoss."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from refoss_ha.controller.toggle import ToggleXMix
|
||||
|
||||
from homeassistant.components.switch import SwitchEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import COORDINATORS, DISPATCH_DEVICE_DISCOVERED, DOMAIN
|
||||
from .entity import RefossEntity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the Refoss device from a config entry."""
|
||||
|
||||
@callback
|
||||
def init_device(coordinator):
|
||||
"""Register the device."""
|
||||
device = coordinator.device
|
||||
if not isinstance(device, ToggleXMix):
|
||||
return
|
||||
|
||||
new_entities = []
|
||||
for channel in device.channels:
|
||||
entity = RefossSwitch(coordinator=coordinator, channel=channel)
|
||||
new_entities.append(entity)
|
||||
|
||||
async_add_entities(new_entities)
|
||||
|
||||
for coordinator in hass.data[DOMAIN][COORDINATORS]:
|
||||
init_device(coordinator)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, DISPATCH_DEVICE_DISCOVERED, init_device)
|
||||
)
|
||||
|
||||
|
||||
class RefossSwitch(RefossEntity, SwitchEntity):
|
||||
"""Refoss Switch Device."""
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if switch is on."""
|
||||
return self.coordinator.device.is_on(channel=self.channel_id)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch on."""
|
||||
await self.coordinator.device.async_turn_on(self.channel_id)
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch off."""
|
||||
await self.coordinator.device.async_turn_off(self.channel_id)
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_toggle(self, **kwargs: Any) -> None:
|
||||
"""Toggle the switch."""
|
||||
await self.coordinator.device.async_toggle(channel=self.channel_id)
|
||||
self.async_write_ha_state()
|
15
homeassistant/components/refoss/util.py
Normal file
15
homeassistant/components/refoss/util.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""Refoss helpers functions."""
|
||||
from __future__ import annotations
|
||||
|
||||
from refoss_ha.discovery import Discovery
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import singleton
|
||||
|
||||
|
||||
@singleton.singleton("refoss_discovery_server")
|
||||
async def refoss_discovery_server(hass: HomeAssistant) -> Discovery:
|
||||
"""Get refoss Discovery server."""
|
||||
discovery_server = Discovery()
|
||||
await discovery_server.initialize()
|
||||
return discovery_server
|
@ -398,6 +398,7 @@ FLOWS = {
|
||||
"rapt_ble",
|
||||
"rdw",
|
||||
"recollect_waste",
|
||||
"refoss",
|
||||
"renault",
|
||||
"renson",
|
||||
"reolink",
|
||||
|
@ -4746,6 +4746,12 @@
|
||||
"config_flow": false,
|
||||
"iot_class": "cloud_polling"
|
||||
},
|
||||
"refoss": {
|
||||
"name": "Refoss",
|
||||
"integration_type": "hub",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"rejseplanen": {
|
||||
"name": "Rejseplanen",
|
||||
"integration_type": "hub",
|
||||
|
@ -2355,6 +2355,9 @@ rapt-ble==0.1.2
|
||||
# homeassistant.components.raspyrfm
|
||||
raspyrfm-client==1.2.8
|
||||
|
||||
# homeassistant.components.refoss
|
||||
refoss-ha==1.2.0
|
||||
|
||||
# homeassistant.components.rainmachine
|
||||
regenmaschine==2023.06.0
|
||||
|
||||
|
@ -1773,6 +1773,9 @@ radiotherm==2.1.0
|
||||
# homeassistant.components.rapt_ble
|
||||
rapt-ble==0.1.2
|
||||
|
||||
# homeassistant.components.refoss
|
||||
refoss-ha==1.2.0
|
||||
|
||||
# homeassistant.components.rainmachine
|
||||
regenmaschine==2023.06.0
|
||||
|
||||
|
107
tests/components/refoss/__init__.py
Normal file
107
tests/components/refoss/__init__.py
Normal file
@ -0,0 +1,107 @@
|
||||
"""Common helpers for refoss test cases."""
|
||||
import asyncio
|
||||
import logging
|
||||
from unittest.mock import AsyncMock, Mock
|
||||
|
||||
from refoss_ha.discovery import Listener
|
||||
|
||||
from homeassistant.components.refoss.const import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FakeDiscovery:
|
||||
"""Mock class replacing refoss device discovery."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the class."""
|
||||
self.mock_devices = {"abc": build_device_mock()}
|
||||
self.last_mock_infos = {}
|
||||
self._listeners = []
|
||||
|
||||
def add_listener(self, listener: Listener) -> None:
|
||||
"""Add an event listener."""
|
||||
self._listeners.append(listener)
|
||||
|
||||
async def initialize(self) -> None:
|
||||
"""Initialize socket server."""
|
||||
self.sock = Mock()
|
||||
|
||||
async def broadcast_msg(self, wait_for: int = 0):
|
||||
"""Search for devices, return mocked data."""
|
||||
|
||||
mock_infos = self.mock_devices
|
||||
last_mock_infos = self.last_mock_infos
|
||||
|
||||
new_infos = []
|
||||
updated_infos = []
|
||||
|
||||
for info in mock_infos.values():
|
||||
uuid = info.uuid
|
||||
if uuid not in last_mock_infos:
|
||||
new_infos.append(info)
|
||||
else:
|
||||
last_info = self.last_mock_infos[uuid]
|
||||
if info.inner_ip != last_info.inner_ip:
|
||||
updated_infos.append(info)
|
||||
|
||||
self.last_mock_infos = mock_infos
|
||||
for listener in self._listeners:
|
||||
[await listener.device_found(x) for x in new_infos]
|
||||
[await listener.device_update(x) for x in updated_infos]
|
||||
|
||||
if wait_for:
|
||||
await asyncio.sleep(wait_for)
|
||||
|
||||
return new_infos
|
||||
|
||||
|
||||
def build_device_mock(name="r10", ip="1.1.1.1", mac="aabbcc112233"):
|
||||
"""Build mock device object."""
|
||||
mock = Mock(
|
||||
uuid="abc",
|
||||
dev_name=name,
|
||||
device_type="r10",
|
||||
fmware_version="1.1.1",
|
||||
hdware_version="1.1.2",
|
||||
inner_ip=ip,
|
||||
port="80",
|
||||
mac=mac,
|
||||
sub_type="eu",
|
||||
channels=[0],
|
||||
)
|
||||
return mock
|
||||
|
||||
|
||||
def build_base_device_mock(name="r10", ip="1.1.1.1", mac="aabbcc112233"):
|
||||
"""Build mock base device object."""
|
||||
mock = Mock(
|
||||
device_info=build_device_mock(name=name, ip=ip, mac=mac),
|
||||
uuid="abc",
|
||||
dev_name=name,
|
||||
device_type="r10",
|
||||
fmware_version="1.1.1",
|
||||
hdware_version="1.1.2",
|
||||
inner_ip=ip,
|
||||
port="80",
|
||||
mac=mac,
|
||||
sub_type="eu",
|
||||
channels=[0],
|
||||
async_handle_update=AsyncMock(),
|
||||
async_turn_on=AsyncMock(),
|
||||
async_turn_off=AsyncMock(),
|
||||
async_toggle=AsyncMock(),
|
||||
)
|
||||
mock.status = {0: True}
|
||||
return mock
|
||||
|
||||
|
||||
async def async_setup_refoss(hass: HomeAssistant) -> MockConfigEntry:
|
||||
"""Set up the refoss platform."""
|
||||
entry = MockConfigEntry(domain=DOMAIN)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
return entry
|
14
tests/components/refoss/conftest.py
Normal file
14
tests/components/refoss/conftest.py
Normal file
@ -0,0 +1,14 @@
|
||||
"""Pytest module configuration."""
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry() -> Generator[AsyncMock, None, None]:
|
||||
"""Override async_setup_entry."""
|
||||
with patch(
|
||||
"homeassistant.components.refoss.async_setup_entry", return_value=True
|
||||
) as mock_setup_entry:
|
||||
yield mock_setup_entry
|
65
tests/components/refoss/test_config_flow.py
Normal file
65
tests/components/refoss/test_config_flow.py
Normal file
@ -0,0 +1,65 @@
|
||||
"""Tests for the refoss Integration."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
from homeassistant.components.refoss.const import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import FakeDiscovery, build_base_device_mock
|
||||
|
||||
|
||||
@patch("homeassistant.components.refoss.config_flow.DISCOVERY_TIMEOUT", 0)
|
||||
async def test_creating_entry_sets_up(
|
||||
hass: HomeAssistant, mock_setup_entry: AsyncMock
|
||||
) -> None:
|
||||
"""Test setting up refoss."""
|
||||
with patch(
|
||||
"homeassistant.components.refoss.util.Discovery",
|
||||
return_value=FakeDiscovery(),
|
||||
), patch(
|
||||
"homeassistant.components.refoss.bridge.async_build_base_device",
|
||||
return_value=build_base_device_mock(),
|
||||
), patch(
|
||||
"homeassistant.components.refoss.switch.isinstance",
|
||||
return_value=True,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
# Confirmation form
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
@patch("homeassistant.components.refoss.config_flow.DISCOVERY_TIMEOUT", 0)
|
||||
async def test_creating_entry_has_no_devices(
|
||||
hass: HomeAssistant, mock_setup_entry: AsyncMock
|
||||
) -> None:
|
||||
"""Test setting up Refoss no devices."""
|
||||
with patch(
|
||||
"homeassistant.components.refoss.util.Discovery",
|
||||
return_value=FakeDiscovery(),
|
||||
) as discovery:
|
||||
discovery.return_value.mock_devices = {}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
# Confirmation form
|
||||
assert result["type"] == data_entry_flow.FlowResultType.FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 0
|
Loading…
x
Reference in New Issue
Block a user