From 1a64108eeaeb6f7bdcb3d0a812d7001af7ea5dff Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Mon, 13 Jul 2020 23:24:28 +0200 Subject: [PATCH] Switch rfxtrx to config entries (#37794) * Switch to config flow setup * Add minimal test for config flow * Add myself as codeowner and address some review concerns * Address some further review comments --- CODEOWNERS | 2 +- homeassistant/components/rfxtrx/__init__.py | 69 ++++++++++++++----- .../components/rfxtrx/binary_sensor.py | 47 +++++++++---- .../components/rfxtrx/config_flow.py | 22 ++++++ homeassistant/components/rfxtrx/const.py | 1 + homeassistant/components/rfxtrx/cover.py | 23 ++++--- homeassistant/components/rfxtrx/light.py | 23 ++++--- homeassistant/components/rfxtrx/manifest.json | 5 +- homeassistant/components/rfxtrx/sensor.py | 32 ++++++--- homeassistant/components/rfxtrx/strings.json | 2 + homeassistant/components/rfxtrx/switch.py | 23 ++++--- .../components/rfxtrx/translations/en.json | 3 + tests/components/rfxtrx/test_config_flow.py | 47 +++++++++++++ 13 files changed, 228 insertions(+), 71 deletions(-) create mode 100644 homeassistant/components/rfxtrx/config_flow.py create mode 100644 homeassistant/components/rfxtrx/strings.json create mode 100644 homeassistant/components/rfxtrx/translations/en.json create mode 100644 tests/components/rfxtrx/test_config_flow.py diff --git a/CODEOWNERS b/CODEOWNERS index 69e622b373d..2d76eec1511 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -334,7 +334,7 @@ homeassistant/components/rainforest_eagle/* @gtdiehl @jcalbert homeassistant/components/rainmachine/* @bachya homeassistant/components/random/* @fabaff homeassistant/components/repetier/* @MTrab -homeassistant/components/rfxtrx/* @danielhiversen +homeassistant/components/rfxtrx/* @danielhiversen @elupus homeassistant/components/ring/* @balloob homeassistant/components/rmvtransport/* @cgtobi homeassistant/components/roku/* @ctalkington diff --git a/homeassistant/components/rfxtrx/__init__.py b/homeassistant/components/rfxtrx/__init__.py index 0185a21feb7..e4b565cd5d9 100644 --- a/homeassistant/components/rfxtrx/__init__.py +++ b/homeassistant/components/rfxtrx/__init__.py @@ -6,6 +6,7 @@ import logging import RFXtrx as rfxtrxmod import voluptuous as vol +from homeassistant import config_entries from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA from homeassistant.const import ( CONF_COMMAND_OFF, @@ -23,11 +24,11 @@ from homeassistant.const import ( UV_INDEX, ) import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.discovery import load_platform from homeassistant.helpers.entity import Entity from .const import ( ATTR_EVENT, + DATA_RFXTRX_CONFIG, DEVICE_PACKET_TYPE_LIGHTING4, EVENT_RFXTRX_EVENT, SERVICE_SEND, @@ -124,13 +125,48 @@ CONFIG_SCHEMA = vol.Schema( ) -def setup(hass, config): +async def async_setup(hass, config): + """Set up the RFXtrx component.""" + if DOMAIN not in config: + hass.data[DATA_RFXTRX_CONFIG] = BASE_SCHEMA({}) + return True + + hass.data[DATA_RFXTRX_CONFIG] = config[DOMAIN] + + hass.async_create_task( + hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_IMPORT}, + data={ + CONF_HOST: config[DOMAIN].get(CONF_HOST), + CONF_PORT: config[DOMAIN].get(CONF_PORT), + CONF_DEVICE: config[DOMAIN].get(CONF_DEVICE), + CONF_DEBUG: config[DOMAIN][CONF_DEBUG], + }, + ) + ) + return True + + +async def async_setup_entry(hass, entry: config_entries.ConfigEntry): + """Set up the RFXtrx component.""" + await hass.async_add_executor_job(setup_internal, hass, entry.data) + + for domain in ["switch", "sensor", "light", "binary_sensor", "cover"]: + hass.async_create_task( + hass.config_entries.async_forward_entry_setup(entry, domain) + ) + + return True + + +def setup_internal(hass, config): """Set up the RFXtrx component.""" # Setup some per device config device_events = set() device_bits = {} - for event_code, event_config in config[DOMAIN][CONF_DEVICES].items(): + for event_code, event_config in hass.data[DATA_RFXTRX_CONFIG][CONF_DEVICES].items(): event = get_rfx_object(event_code) device_id = get_device_id( event.device, data_bits=event_config.get(CONF_DATA_BITS) @@ -167,10 +203,10 @@ def setup(hass, config): if device_id in device_events: hass.bus.fire(EVENT_RFXTRX_EVENT, event_data) - device = config[DOMAIN].get(CONF_DEVICE) - host = config[DOMAIN].get(CONF_HOST) - port = config[DOMAIN].get(CONF_PORT) - debug = config[DOMAIN][CONF_DEBUG] + device = config[CONF_DEVICE] + host = config[CONF_HOST] + port = config[CONF_PORT] + debug = config[CONF_DEBUG] if port is not None: # If port is set then we create a TCP connection @@ -196,19 +232,11 @@ def setup(hass, config): hass.data[DATA_RFXOBJECT] = rfx_object - load_platform(hass, "switch", DOMAIN, config[DOMAIN], config) - load_platform(hass, "light", DOMAIN, config[DOMAIN], config) - load_platform(hass, "cover", DOMAIN, config[DOMAIN], config) - load_platform(hass, "binary_sensor", DOMAIN, config[DOMAIN], config) - load_platform(hass, "sensor", DOMAIN, config[DOMAIN], config) - def send(call): event = call.data[ATTR_EVENT] rfx_object.transport.send(event) - hass.services.async_register(DOMAIN, SERVICE_SEND, send, schema=SERVICE_SEND_SCHEMA) - - return True + hass.services.register(DOMAIN, SERVICE_SEND, send, schema=SERVICE_SEND_SCHEMA) def get_rfx_object(packetid): @@ -352,6 +380,15 @@ class RfxtrxDevice(Entity): """Return unique identifier of remote device.""" return self._unique_id + @property + def device_info(self): + """Return the device info.""" + return { + "identifiers": {(DOMAIN, *self._device_id)}, + "name": f"{self._device.type_string} {self._device.id_string}", + "model": self._device.type_string, + } + def _apply_event(self, event): """Apply a received event.""" diff --git a/homeassistant/components/rfxtrx/binary_sensor.py b/homeassistant/components/rfxtrx/binary_sensor.py index 2b02a4b748d..8ec67d4a902 100644 --- a/homeassistant/components/rfxtrx/binary_sensor.py +++ b/homeassistant/components/rfxtrx/binary_sensor.py @@ -10,34 +10,41 @@ from homeassistant.const import ( CONF_DEVICE_CLASS, CONF_DEVICES, ) +from homeassistant.core import callback from homeassistant.helpers import event as evt from . import ( CONF_AUTOMATIC_ADD, CONF_DATA_BITS, CONF_OFF_DELAY, + DOMAIN, SIGNAL_EVENT, find_possible_pt2262_device, get_device_id, get_pt2262_cmd, get_rfx_object, ) -from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DEVICE_PACKET_TYPE_LIGHTING4 +from .const import ( + COMMAND_OFF_LIST, + COMMAND_ON_LIST, + DATA_RFXTRX_CONFIG, + DEVICE_PACKET_TYPE_LIGHTING4, +) _LOGGER = logging.getLogger(__name__) -def setup_platform(hass, config, add_entities, discovery_info=None): - """Set up the Binary Sensor platform to RFXtrx.""" - if discovery_info is None: - return - +async def async_setup_entry( + hass, config_entry, async_add_entities, +): + """Set up platform.""" sensors = [] device_ids = set() - pt2262_devices = [] + discovery_info = hass.data[DATA_RFXTRX_CONFIG] + def supported(event): return isinstance(event, rfxtrxmod.ControlEvent) @@ -69,8 +76,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): ) sensors.append(device) - add_entities(sensors) + async_add_entities(sensors) + @callback def binary_sensor_update(event, device_id): """Call for control updates from the RFXtrx gateway.""" if not supported(event): @@ -88,11 +96,13 @@ def setup_platform(hass, config, add_entities, discovery_info=None): "".join(f"{x:02x}" for x in event.data), ) sensor = RfxtrxBinarySensor(event.device, device_id, event=event) - add_entities([sensor]) + async_add_entities([sensor]) # Subscribe to main RFXtrx events if discovery_info[CONF_AUTOMATIC_ADD]: - hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, binary_sensor_update) + hass.helpers.dispatcher.async_dispatcher_connect( + SIGNAL_EVENT, binary_sensor_update + ) class RfxtrxBinarySensor(BinarySensorEntity): @@ -182,6 +192,15 @@ class RfxtrxBinarySensor(BinarySensorEntity): """Return unique identifier of remote device.""" return self._unique_id + @property + def device_info(self): + """Return the device info.""" + return { + "identifiers": {(DOMAIN, *self._device_id)}, + "name": f"{self._device.type_string} {self._device.id_string}", + "model": self._device.type_string, + } + def _apply_event_lighting4(self, event): """Apply event for a lighting 4 device.""" if self.data_bits is not None: @@ -207,6 +226,7 @@ class RfxtrxBinarySensor(BinarySensorEntity): else: self._apply_event_standard(event) + @callback def _handle_event(self, event, device_id): """Check if event applies to me and update.""" if device_id != self._device_id: @@ -221,16 +241,17 @@ class RfxtrxBinarySensor(BinarySensorEntity): self._apply_event(event) - self.schedule_update_ha_state() + self.async_write_ha_state() if self.is_on and self.off_delay is not None and self.delay_listener is None: + @callback def off_delay_listener(now): """Switch device off after a delay.""" self.delay_listener = None self._state = False - self.schedule_update_ha_state() + self.async_write_ha_state() - self.delay_listener = evt.call_later( + self.delay_listener = evt.async_call_later( self.hass, self.off_delay.total_seconds(), off_delay_listener ) diff --git a/homeassistant/components/rfxtrx/config_flow.py b/homeassistant/components/rfxtrx/config_flow.py new file mode 100644 index 00000000000..0bd8854ca41 --- /dev/null +++ b/homeassistant/components/rfxtrx/config_flow.py @@ -0,0 +1,22 @@ +"""Config flow for RFXCOM RFXtrx integration.""" +import logging + +from homeassistant import config_entries + +from . import DOMAIN + +_LOGGER = logging.getLogger(__name__) + + +class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): + """Handle a config flow for RFXCOM RFXtrx.""" + + VERSION = 1 + CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH + + async def async_step_import(self, import_config=None): + """Handle the initial step.""" + + await self.async_set_unique_id(DOMAIN) + self._abort_if_unique_id_configured(import_config) + return self.async_create_entry(title="RFXTRX", data=import_config) diff --git a/homeassistant/components/rfxtrx/const.py b/homeassistant/components/rfxtrx/const.py index cd3c4b9a62e..7626c082f45 100644 --- a/homeassistant/components/rfxtrx/const.py +++ b/homeassistant/components/rfxtrx/const.py @@ -21,4 +21,5 @@ SERVICE_SEND = "send" DEVICE_PACKET_TYPE_LIGHTING4 = 0x13 +DATA_RFXTRX_CONFIG = "rfxtrx_config" EVENT_RFXTRX_EVENT = "rfxtrx_event" diff --git a/homeassistant/components/rfxtrx/cover.py b/homeassistant/components/rfxtrx/cover.py index a9bbe224b26..829ff9c8110 100644 --- a/homeassistant/components/rfxtrx/cover.py +++ b/homeassistant/components/rfxtrx/cover.py @@ -3,6 +3,7 @@ import logging from homeassistant.components.cover import CoverEntity from homeassistant.const import CONF_DEVICES, STATE_OPEN +from homeassistant.core import callback from homeassistant.helpers.restore_state import RestoreEntity from . import ( @@ -14,16 +15,16 @@ from . import ( get_device_id, get_rfx_object, ) -from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST +from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DATA_RFXTRX_CONFIG _LOGGER = logging.getLogger(__name__) -def setup_platform(hass, config, add_entities, discovery_info=None): - """Set up the RFXtrx cover.""" - if discovery_info is None: - return - +async def async_setup_entry( + hass, config_entry, async_add_entities, +): + """Set up config entry.""" + discovery_info = hass.data[DATA_RFXTRX_CONFIG] device_ids = set() def supported(event): @@ -48,8 +49,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): ) entities.append(entity) - add_entities(entities) + async_add_entities(entities) + @callback def cover_update(event, device_id): """Handle cover updates from the RFXtrx gateway.""" if not supported(event): @@ -70,11 +72,11 @@ def setup_platform(hass, config, add_entities, discovery_info=None): entity = RfxtrxCover( event.device, device_id, DEFAULT_SIGNAL_REPETITIONS, event=event ) - add_entities([entity]) + async_add_entities([entity]) # Subscribe to main RFXtrx events if discovery_info[CONF_AUTOMATIC_ADD]: - hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, cover_update) + hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, cover_update) class RfxtrxCover(RfxtrxDevice, CoverEntity, RestoreEntity): @@ -123,6 +125,7 @@ class RfxtrxCover(RfxtrxDevice, CoverEntity, RestoreEntity): elif event.values["Command"] in COMMAND_OFF_LIST: self._state = False + @callback def _handle_event(self, event, device_id): """Check if event applies to me and update.""" if device_id != self._device_id: @@ -130,4 +133,4 @@ class RfxtrxCover(RfxtrxDevice, CoverEntity, RestoreEntity): self._apply_event(event) - self.schedule_update_ha_state() + self.async_write_ha_state() diff --git a/homeassistant/components/rfxtrx/light.py b/homeassistant/components/rfxtrx/light.py index e54cc82a86e..c248d8b8307 100644 --- a/homeassistant/components/rfxtrx/light.py +++ b/homeassistant/components/rfxtrx/light.py @@ -9,6 +9,7 @@ from homeassistant.components.light import ( LightEntity, ) from homeassistant.const import CONF_DEVICES, STATE_ON +from homeassistant.core import callback from homeassistant.helpers.restore_state import RestoreEntity from . import ( @@ -20,18 +21,18 @@ from . import ( get_device_id, get_rfx_object, ) -from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST +from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DATA_RFXTRX_CONFIG _LOGGER = logging.getLogger(__name__) SUPPORT_RFXTRX = SUPPORT_BRIGHTNESS -def setup_platform(hass, config, add_entities, discovery_info=None): - """Set up the RFXtrx platform.""" - if discovery_info is None: - return - +async def async_setup_entry( + hass, config_entry, async_add_entities, +): + """Set up config entry.""" + discovery_info = hass.data[DATA_RFXTRX_CONFIG] device_ids = set() def supported(event): @@ -61,8 +62,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): entities.append(entity) - add_entities(entities) + async_add_entities(entities) + @callback def light_update(event, device_id): """Handle light updates from the RFXtrx gateway.""" if not supported(event): @@ -84,11 +86,11 @@ def setup_platform(hass, config, add_entities, discovery_info=None): event.device, device_id, DEFAULT_SIGNAL_REPETITIONS, event=event ) - add_entities([entity]) + async_add_entities([entity]) # Subscribe to main RFXtrx events if discovery_info[CONF_AUTOMATIC_ADD]: - hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, light_update) + hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, light_update) class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity): @@ -153,6 +155,7 @@ class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity): self._brightness = event.values["Dim level"] * 255 // 100 self._state = self._brightness > 0 + @callback def _handle_event(self, event, device_id): """Check if event applies to me and update.""" if device_id != self._device_id: @@ -160,4 +163,4 @@ class RfxtrxLight(RfxtrxDevice, LightEntity, RestoreEntity): self._apply_event(event) - self.schedule_update_ha_state() + self.async_write_ha_state() diff --git a/homeassistant/components/rfxtrx/manifest.json b/homeassistant/components/rfxtrx/manifest.json index 3b5790ad4ee..44b53ed0dac 100644 --- a/homeassistant/components/rfxtrx/manifest.json +++ b/homeassistant/components/rfxtrx/manifest.json @@ -3,5 +3,6 @@ "name": "RFXCOM RFXtrx", "documentation": "https://www.home-assistant.io/integrations/rfxtrx", "requirements": ["pyRFXtrx==0.25"], - "codeowners": ["@danielhiversen"] -} + "codeowners": ["@danielhiversen", "@elupus"], + "config_flow": false +} \ No newline at end of file diff --git a/homeassistant/components/rfxtrx/sensor.py b/homeassistant/components/rfxtrx/sensor.py index 97004231994..7c540672c9a 100644 --- a/homeassistant/components/rfxtrx/sensor.py +++ b/homeassistant/components/rfxtrx/sensor.py @@ -10,15 +10,18 @@ from homeassistant.components.sensor import ( DEVICE_CLASS_TEMPERATURE, ) from homeassistant.const import CONF_DEVICES +from homeassistant.core import callback from homeassistant.helpers.entity import Entity from . import ( CONF_AUTOMATIC_ADD, DATA_TYPES, + DOMAIN, SIGNAL_EVENT, get_device_id, get_rfx_object, ) +from .const import DATA_RFXTRX_CONFIG _LOGGER = logging.getLogger(__name__) @@ -51,11 +54,11 @@ CONVERT_FUNCTIONS = { } -def setup_platform(hass, config, add_entities, discovery_info=None): - """Set up the RFXtrx platform.""" - if discovery_info is None: - return - +async def async_setup_entry( + hass, config_entry, async_add_entities, +): + """Set up platform.""" + discovery_info = hass.data[DATA_RFXTRX_CONFIG] data_ids = set() def supported(event): @@ -80,8 +83,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): entity = RfxtrxSensor(event.device, device_id, data_type) entities.append(entity) - add_entities(entities) + async_add_entities(entities) + @callback def sensor_update(event, device_id): """Handle sensor updates from the RFXtrx gateway.""" if not supported(event): @@ -102,11 +106,11 @@ def setup_platform(hass, config, add_entities, discovery_info=None): ) entity = RfxtrxSensor(event.device, device_id, data_type, event=event) - add_entities([entity]) + async_add_entities([entity]) # Subscribe to main RFXtrx events if discovery_info[CONF_AUTOMATIC_ADD]: - hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, sensor_update) + hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, sensor_update) class RfxtrxSensor(Entity): @@ -177,10 +181,20 @@ class RfxtrxSensor(Entity): """Return unique identifier of remote device.""" return self._unique_id + @property + def device_info(self): + """Return the device info.""" + return { + "identifiers": {(DOMAIN, *self._device_id)}, + "name": f"{self._device.type_string} {self._device.id_string}", + "model": self._device.type_string, + } + def _apply_event(self, event): """Apply command from rfxtrx.""" self.event = event + @callback def _handle_event(self, event, device_id): """Check if event applies to me and update.""" if not isinstance(event, SensorEvent): @@ -201,4 +215,4 @@ class RfxtrxSensor(Entity): self._apply_event(event) - self.schedule_update_ha_state() + self.async_write_ha_state() diff --git a/homeassistant/components/rfxtrx/strings.json b/homeassistant/components/rfxtrx/strings.json new file mode 100644 index 00000000000..7a73a41bfdf --- /dev/null +++ b/homeassistant/components/rfxtrx/strings.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/homeassistant/components/rfxtrx/switch.py b/homeassistant/components/rfxtrx/switch.py index 9a822034ab8..c890e162b2c 100644 --- a/homeassistant/components/rfxtrx/switch.py +++ b/homeassistant/components/rfxtrx/switch.py @@ -5,6 +5,7 @@ import RFXtrx as rfxtrxmod from homeassistant.components.switch import SwitchEntity from homeassistant.const import CONF_DEVICES, STATE_ON +from homeassistant.core import callback from homeassistant.helpers.restore_state import RestoreEntity from . import ( @@ -17,18 +18,18 @@ from . import ( get_device_id, get_rfx_object, ) -from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST +from .const import COMMAND_OFF_LIST, COMMAND_ON_LIST, DATA_RFXTRX_CONFIG DATA_SWITCH = f"{DOMAIN}_switch" _LOGGER = logging.getLogger(__name__) -def setup_platform(hass, config, add_entities_callback, discovery_info=None): - """Set up the RFXtrx platform.""" - if discovery_info is None: - return - +async def async_setup_entry( + hass, config_entry, async_add_entities, +): + """Set up config entry.""" + discovery_info = hass.data[DATA_RFXTRX_CONFIG] device_ids = set() def supported(event): @@ -58,8 +59,9 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None): ) entities.append(entity) - add_entities_callback(entities) + async_add_entities(entities) + @callback def switch_update(event, device_id): """Handle sensor updates from the RFXtrx gateway.""" if not supported(event): @@ -80,11 +82,11 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None): entity = RfxtrxSwitch( event.device, device_id, DEFAULT_SIGNAL_REPETITIONS, event=event ) - add_entities_callback([entity]) + async_add_entities([entity]) # Subscribe to main RFXtrx events if discovery_info[CONF_AUTOMATIC_ADD]: - hass.helpers.dispatcher.dispatcher_connect(SIGNAL_EVENT, switch_update) + hass.helpers.dispatcher.async_dispatcher_connect(SIGNAL_EVENT, switch_update) class RfxtrxSwitch(RfxtrxDevice, SwitchEntity, RestoreEntity): @@ -111,6 +113,7 @@ class RfxtrxSwitch(RfxtrxDevice, SwitchEntity, RestoreEntity): elif event.values["Command"] in COMMAND_OFF_LIST: self._state = False + @callback def _handle_event(self, event, device_id): """Check if event applies to me and update.""" if device_id != self._device_id: @@ -118,7 +121,7 @@ class RfxtrxSwitch(RfxtrxDevice, SwitchEntity, RestoreEntity): self._apply_event(event) - self.schedule_update_ha_state() + self.async_write_ha_state() def turn_on(self, **kwargs): """Turn the device on.""" diff --git a/homeassistant/components/rfxtrx/translations/en.json b/homeassistant/components/rfxtrx/translations/en.json new file mode 100644 index 00000000000..eacf69468b0 --- /dev/null +++ b/homeassistant/components/rfxtrx/translations/en.json @@ -0,0 +1,3 @@ +{ + "title": "RFXCOM RFXtrx" +} \ No newline at end of file diff --git a/tests/components/rfxtrx/test_config_flow.py b/tests/components/rfxtrx/test_config_flow.py new file mode 100644 index 00000000000..53f3b317d53 --- /dev/null +++ b/tests/components/rfxtrx/test_config_flow.py @@ -0,0 +1,47 @@ +"""Test the Tado config flow.""" +from homeassistant import config_entries, setup +from homeassistant.components.rfxtrx import DOMAIN + +from tests.common import MockConfigEntry + + +async def test_import(hass): + """Test we can import.""" + await setup.async_setup_component(hass, "persistent_notification", {}) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_IMPORT}, + data={"host": None, "port": None, "device": "/dev/tty123", "debug": False}, + ) + + assert result["type"] == "create_entry" + assert result["title"] == "RFXTRX" + assert result["data"] == { + "host": None, + "port": None, + "device": "/dev/tty123", + "debug": False, + } + + +async def test_import_update(hass): + """Test we can import.""" + await setup.async_setup_component(hass, "persistent_notification", {}) + + entry = MockConfigEntry( + domain=DOMAIN, + data={"host": None, "port": None, "device": "/dev/tty123", "debug": False}, + unique_id=DOMAIN, + ) + entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_IMPORT}, + data={"host": None, "port": None, "device": "/dev/tty123", "debug": True}, + ) + + assert result["type"] == "abort" + assert result["reason"] == "already_configured" + assert entry.data["debug"]