async def test_setup_recovers_when_setup_raises(opp): """Test the setup if exceptions are happening.""" platform1_setup = Mock(side_effect=Exception("Broken")) platform2_setup = Mock(return_value=None) mock_entity_platform(opp, "test_domain.mod1", MockPlatform(platform1_setup)) mock_entity_platform(opp, "test_domain.mod2", MockPlatform(platform2_setup)) component = EntityComponent(_LOGGER, DOMAIN, opp) assert not platform1_setup.called assert not platform2_setup.called component.setup( OrderedDict( [ (DOMAIN, {"platform": "mod1"}), (f"{DOMAIN} 2", {"platform": "non_exist"}), (f"{DOMAIN} 3", {"platform": "mod2"}), ] ) ) await opp.async_block_till_done() assert platform1_setup.called assert platform2_setup.called
async def async_setup(opp: OpenPeerPowerType, config: ConfigType) -> bool: """Set up an input text.""" component = EntityComponent(_LOGGER, DOMAIN, opp) id_manager = collection.IDManager() yaml_collection = collection.YamlCollection( logging.getLogger(f"{__name__}.yaml_collection"), id_manager) collection.attach_entity_component_collection(component, yaml_collection, InputText.from_yaml) storage_collection = InputTextStorageCollection( Store(opp, STORAGE_VERSION, STORAGE_KEY), logging.getLogger(f"{__name__}.storage_collection"), id_manager, ) collection.attach_entity_component_collection(component, storage_collection, InputText) await yaml_collection.async_load([{ CONF_ID: id_, **(conf or {}) } for id_, conf in config.get(DOMAIN, {}).items()]) await storage_collection.async_load() collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS).async_setup(opp) collection.attach_entity_registry_cleaner(opp, DOMAIN, DOMAIN, yaml_collection) collection.attach_entity_registry_cleaner(opp, DOMAIN, DOMAIN, storage_collection) async def reload_service_handler(service_call: ServiceCallType) -> None: """Reload yaml entities.""" conf = await component.async_prepare_reload(skip_reset=True) if conf is None: conf = {DOMAIN: {}} await yaml_collection.async_load([{ CONF_ID: id_, **(cfg or {}) } for id_, cfg in conf.get(DOMAIN, {}).items()]) openpeerpower.helpers.service.async_register_admin_service( opp, DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=RELOAD_SERVICE_SCHEMA, ) component.async_register_entity_service( SERVICE_SET_VALUE, {vol.Required(ATTR_VALUE): cv.string}, "async_set_value") return True
async def test_setup_does_discovery(mock_setup_component, mock_setup, opp): """Test setup for discovery.""" component = EntityComponent(_LOGGER, DOMAIN, opp) component.setup({}) discovery.load_platform( opp, DOMAIN, "platform_test", {"msg": "discovery_info"}, {DOMAIN: {}} ) await opp.async_block_till_done() assert mock_setup.called assert ("platform_test", {}, {"msg": "discovery_info"}) == mock_setup.call_args[0]
async def async_setup(opp: OpenPeerPower, config: ConfigType) -> bool: """Set up an input slider.""" component = EntityComponent(_LOGGER, DOMAIN, opp) id_manager = collection.IDManager() yaml_collection = collection.YamlCollection( logging.getLogger(f"{__name__}.yaml_collection"), id_manager) collection.sync_entity_lifecycle(opp, DOMAIN, DOMAIN, component, yaml_collection, InputNumber.from_yaml) storage_collection = NumberStorageCollection( Store(opp, STORAGE_VERSION, STORAGE_KEY), logging.getLogger(f"{__name__}.storage_collection"), id_manager, ) collection.sync_entity_lifecycle(opp, DOMAIN, DOMAIN, component, storage_collection, InputNumber) await yaml_collection.async_load([{ CONF_ID: id_, **(conf or {}) } for id_, conf in config.get(DOMAIN, {}).items()]) await storage_collection.async_load() collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS).async_setup(opp) async def reload_service_handler(service_call: ServiceCall) -> None: """Reload yaml entities.""" conf = await component.async_prepare_reload(skip_reset=True) if conf is None: conf = {DOMAIN: {}} await yaml_collection.async_load([{ CONF_ID: id_, **conf } for id_, conf in conf.get(DOMAIN, {}).items()]) openpeerpower.helpers.service.async_register_admin_service( opp, DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=RELOAD_SERVICE_SCHEMA, ) component.async_register_entity_service( SERVICE_SET_VALUE, {vol.Required(ATTR_VALUE): vol.Coerce(float)}, "async_set_value", ) component.async_register_entity_service(SERVICE_INCREMENT, {}, "async_increment") component.async_register_entity_service(SERVICE_DECREMENT, {}, "async_decrement") return True
async def test_update_state_adds_entities(opp): """Test if updating poll entities cause an entity to be added works.""" component = EntityComponent(_LOGGER, DOMAIN, opp) ent1 = MockEntity() ent2 = MockEntity(should_poll=True) await component.async_add_entities([ent2]) assert len(opp.states.async_entity_ids()) == 1 ent2.update = lambda *_: component.add_entities([ent1]) async_fire_time_changed(opp, dt_util.utcnow() + DEFAULT_SCAN_INTERVAL) await opp.async_block_till_done() assert len(opp.states.async_entity_ids()) == 2
async def test_register_entity_service(opp): """Test not expanding a group.""" entity = MockEntity(entity_id=f"{DOMAIN}.entity") calls = [] @ha.callback def appender(**kwargs): calls.append(kwargs) entity.async_called_by_service = appender component = EntityComponent(_LOGGER, DOMAIN, opp) await component.async_add_entities([entity]) component.async_register_entity_service( "hello", {"some": str}, "async_called_by_service" ) with pytest.raises(vol.Invalid): await opp.services.async_call( DOMAIN, "hello", {"entity_id": entity.entity_id, "invalid": "data"}, blocking=True, ) assert len(calls) == 0 await opp.services.async_call( DOMAIN, "hello", {"entity_id": entity.entity_id, "some": "data"}, blocking=True ) assert len(calls) == 1 assert calls[0] == {"some": "data"} await opp.services.async_call( DOMAIN, "hello", {"entity_id": ENTITY_MATCH_ALL, "some": "data"}, blocking=True ) assert len(calls) == 2 assert calls[1] == {"some": "data"} await opp.services.async_call( DOMAIN, "hello", {"entity_id": ENTITY_MATCH_NONE, "some": "data"}, blocking=True ) assert len(calls) == 2 await opp.services.async_call( DOMAIN, "hello", {"area_id": ENTITY_MATCH_NONE, "some": "data"}, blocking=True ) assert len(calls) == 2
async def async_setup(opp: OpenPeerPower, config: ConfigType) -> bool: """Set up an input select.""" component = EntityComponent(_LOGGER, DOMAIN, opp) id_manager = collection.IDManager() yaml_collection = collection.YamlCollection( logging.getLogger(f"{__name__}.yaml_collection"), id_manager) collection.sync_entity_lifecycle(opp, DOMAIN, DOMAIN, component, yaml_collection, Timer.from_yaml) storage_collection = TimerStorageCollection( Store(opp, STORAGE_VERSION, STORAGE_KEY), logging.getLogger(f"{__name__}.storage_collection"), id_manager, ) collection.sync_entity_lifecycle(opp, DOMAIN, DOMAIN, component, storage_collection, Timer) await yaml_collection.async_load([{ CONF_ID: id_, **cfg } for id_, cfg in config.get(DOMAIN, {}).items()]) await storage_collection.async_load() collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS).async_setup(opp) async def reload_service_handler(service_call: ServiceCall) -> None: """Reload yaml entities.""" conf = await component.async_prepare_reload(skip_reset=True) if conf is None: conf = {DOMAIN: {}} await yaml_collection.async_load([{ CONF_ID: id_, **cfg } for id_, cfg in conf.get(DOMAIN, {}).items()]) openpeerpower.helpers.service.async_register_admin_service( opp, DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=RELOAD_SERVICE_SCHEMA, ) component.async_register_entity_service( SERVICE_START, { vol.Optional(ATTR_DURATION, default=DEFAULT_DURATION): cv.time_period }, "async_start", ) component.async_register_entity_service(SERVICE_PAUSE, {}, "async_pause") component.async_register_entity_service(SERVICE_CANCEL, {}, "async_cancel") component.async_register_entity_service(SERVICE_FINISH, {}, "async_finish") return True
async def async_setup(opp, config): """Set up an Utility Meter.""" component = EntityComponent(_LOGGER, DOMAIN, opp) opp.data[DATA_UTILITY] = {} register_services = False for meter, conf in config.get(DOMAIN).items(): _LOGGER.debug("Setup %s.%s", DOMAIN, meter) opp.data[DATA_UTILITY][meter] = conf if not conf[CONF_TARIFFS]: # only one entity is required opp.async_create_task( discovery.async_load_platform( opp, SENSOR_DOMAIN, DOMAIN, [{ CONF_METER: meter, CONF_NAME: meter }], config, )) else: # create tariff selection await component.async_add_entities( [TariffSelect(meter, list(conf[CONF_TARIFFS]))]) opp.data[DATA_UTILITY][meter][CONF_TARIFF_ENTITY] = "{}.{}".format( DOMAIN, meter) # add one meter for each tariff tariff_confs = [] for tariff in conf[CONF_TARIFFS]: tariff_confs.append({ CONF_METER: meter, CONF_NAME: f"{meter} {tariff}", CONF_TARIFF: tariff, }) opp.async_create_task( discovery.async_load_platform(opp, SENSOR_DOMAIN, DOMAIN, tariff_confs, config)) register_services = True if register_services: component.async_register_entity_service(SERVICE_RESET, {}, "async_reset_meters") component.async_register_entity_service( SERVICE_SELECT_TARIFF, {vol.Required(ATTR_TARIFF): cv.string}, "async_select_tariff", ) component.async_register_entity_service(SERVICE_SELECT_NEXT_TARIFF, {}, "async_next_tariff") return True
async def async_setup(opp, config): """Set up the image processing.""" component = EntityComponent(_LOGGER, DOMAIN, opp, SCAN_INTERVAL) await component.async_setup(config) async def async_scan_service(service): """Service handler for scan.""" image_entities = await component.async_extract_from_service(service) update_tasks = [] for entity in image_entities: entity.async_set_context(service.context) update_tasks.append( asyncio.create_task(entity.async_update_op_state(True))) if update_tasks: await asyncio.wait(update_tasks) opp.services.async_register(DOMAIN, SERVICE_SCAN, async_scan_service, schema=make_entity_service_schema({})) return True
def setup(opp, config): """Set up the Remember the milk component.""" component = EntityComponent(_LOGGER, DOMAIN, opp) stored_rtm_config = RememberTheMilkConfiguration(opp) for rtm_config in config[DOMAIN]: account_name = rtm_config[CONF_NAME] _LOGGER.info("Adding Remember the milk account %s", account_name) api_key = rtm_config[CONF_API_KEY] shared_secret = rtm_config[CONF_SHARED_SECRET] token = stored_rtm_config.get_token(account_name) if token: _LOGGER.debug("found token for account %s", account_name) _create_instance( opp, account_name, api_key, shared_secret, token, stored_rtm_config, component, ) else: _register_new_account(opp, account_name, api_key, shared_secret, stored_rtm_config, component) _LOGGER.debug("Finished adding all Remember the milk accounts") return True
async def test_not_fails_with_adding_empty_entities_(opp): """Test for not fails on empty entities list.""" component = EntityComponent(_LOGGER, DOMAIN, opp) await component.async_add_entities([]) assert len(opp.states.async_entity_ids()) == 0
async def test_polling_updates_entities_with_exception(opp): """Test the updated entities that not break with an exception.""" component = EntityComponent(_LOGGER, DOMAIN, opp, timedelta(seconds=20)) update_ok = [] update_err = [] def update_mock(): """Mock normal update.""" update_ok.append(None) def update_mock_err(): """Mock error update.""" update_err.append(None) raise AssertionError("Fake error update") ent1 = MockEntity(should_poll=True) ent1.update = update_mock_err ent2 = MockEntity(should_poll=True) ent2.update = update_mock ent3 = MockEntity(should_poll=True) ent3.update = update_mock ent4 = MockEntity(should_poll=True) ent4.update = update_mock await component.async_add_entities([ent1, ent2, ent3, ent4]) update_ok.clear() update_err.clear() async_fire_time_changed(opp, dt_util.utcnow() + timedelta(seconds=20)) await opp.async_block_till_done() assert len(update_ok) == 3 assert len(update_err) == 1
async def test_entity_with_name_and_entity_id_getting_registered(opp): """Ensure that entity ID is used for registration.""" component = EntityComponent(_LOGGER, DOMAIN, opp) await component.async_add_entities([ MockEntity(unique_id="1234", name="bla", entity_id="test_domain.world") ]) assert "test_domain.world" in opp.states.async_entity_ids()
async def test_not_adding_duplicate_entities_with_unique_id(opp, caplog): """Test for not adding duplicate entities.""" caplog.set_level(logging.ERROR) component = EntityComponent(_LOGGER, DOMAIN, opp) await component.async_add_entities( [MockEntity(name="test1", unique_id="not_very_unique")]) assert len(opp.states.async_entity_ids()) == 1 assert not caplog.text ent2 = MockEntity(name="test2", unique_id="not_very_unique") await component.async_add_entities([ent2]) assert "test1" in caplog.text assert DOMAIN in caplog.text ent3 = MockEntity(name="test2", entity_id="test_domain.test3", unique_id="not_very_unique") await component.async_add_entities([ent3]) assert "test1" in caplog.text assert "test3" in caplog.text assert DOMAIN in caplog.text assert ent2.opp is None assert ent2.platform is None assert len(opp.states.async_entity_ids()) == 1
async def async_setup(opp: OpenPeerPower, config: ConfigType) -> bool: """Set up humidifier devices.""" component = opp.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, opp, SCAN_INTERVAL) await component.async_setup(config) component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_turn_on") component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off") component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle") component.async_register_entity_service( SERVICE_SET_MODE, {vol.Required(ATTR_MODE): cv.string}, "async_set_mode", [SUPPORT_MODES], ) component.async_register_entity_service( SERVICE_SET_HUMIDITY, { vol.Required(ATTR_HUMIDITY): vol.All( vol.Coerce(int), vol.Range(min=0, max=100) ) }, "async_set_humidity", ) return True
async def async_setup(opp, config: dict): """Expose fan control via statemachine and services.""" component = opp.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, opp, SCAN_INTERVAL) await component.async_setup(config) component.async_register_entity_service( SERVICE_TURN_ON, {vol.Optional(ATTR_SPEED): cv.string}, "async_turn_on") component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off") component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle") component.async_register_entity_service( SERVICE_SET_SPEED, {vol.Required(ATTR_SPEED): cv.string}, "async_set_speed", [SUPPORT_SET_SPEED], ) component.async_register_entity_service( SERVICE_OSCILLATE, {vol.Required(ATTR_OSCILLATING): cv.boolean}, "async_oscillate", [SUPPORT_OSCILLATE], ) component.async_register_entity_service( SERVICE_SET_DIRECTION, {vol.Optional(ATTR_DIRECTION): cv.string}, "async_set_direction", [SUPPORT_DIRECTION], ) return True
async def test_extract_from_service_available_device(opp): """Test the extraction of entity from service and device is available.""" component = EntityComponent(_LOGGER, DOMAIN, opp) await component.async_add_entities( [ MockEntity(name="test_1"), MockEntity(name="test_2", available=False), MockEntity(name="test_3"), MockEntity(name="test_4", available=False), ] ) call_1 = ha.ServiceCall("test", "service", data={"entity_id": ENTITY_MATCH_ALL}) assert ["test_domain.test_1", "test_domain.test_3"] == sorted( ent.entity_id for ent in (await component.async_extract_from_service(call_1)) ) call_2 = ha.ServiceCall( "test", "service", data={"entity_id": ["test_domain.test_3", "test_domain.test_4"]}, ) assert ["test_domain.test_3"] == sorted( ent.entity_id for ent in (await component.async_extract_from_service(call_2)) )
async def async_setup(opp, config): """Track states and offer events for binary sensors.""" component = opp.data[DOMAIN] = EntityComponent(logging.getLogger(__name__), DOMAIN, opp, SCAN_INTERVAL) await component.async_setup(config) return True
async def test_unload_entry_fails_if_never_loaded(opp): """.""" component = EntityComponent(_LOGGER, DOMAIN, opp) entry = MockConfigEntry(domain="entry_domain") with pytest.raises(ValueError): await component.async_unload_entry(entry)
async def async_setup(opp, config): """Set up the vacuum component.""" component = opp.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, opp, SCAN_INTERVAL) await component.async_setup(config) component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_turn_on") component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off") component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle") component.async_register_entity_service( SERVICE_START_PAUSE, {}, "async_start_pause" ) component.async_register_entity_service(SERVICE_START, {}, "async_start") component.async_register_entity_service(SERVICE_PAUSE, {}, "async_pause") component.async_register_entity_service( SERVICE_RETURN_TO_BASE, {}, "async_return_to_base" ) component.async_register_entity_service(SERVICE_CLEAN_SPOT, {}, "async_clean_spot") component.async_register_entity_service(SERVICE_LOCATE, {}, "async_locate") component.async_register_entity_service(SERVICE_STOP, {}, "async_stop") component.async_register_entity_service( SERVICE_SET_FAN_SPEED, {vol.Required(ATTR_FAN_SPEED): cv.string}, "async_set_fan_speed", ) component.async_register_entity_service( SERVICE_SEND_COMMAND, { vol.Required(ATTR_COMMAND): cv.string, vol.Optional(ATTR_PARAMS): vol.Any(dict, cv.ensure_list), }, "async_send_command", ) return True
async def async_setup(opp, config): """Track states and offer events for covers.""" component = opp.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, opp, SCAN_INTERVAL) await component.async_setup(config) component.async_register_entity_service(SERVICE_OPEN_COVER, {}, "async_open_cover", [SUPPORT_OPEN]) component.async_register_entity_service(SERVICE_CLOSE_COVER, {}, "async_close_cover", [SUPPORT_CLOSE]) component.async_register_entity_service( SERVICE_SET_COVER_POSITION, { vol.Required(ATTR_POSITION): vol.All(vol.Coerce(int), vol.Range(min=0, max=100)) }, "async_set_cover_position", [SUPPORT_SET_POSITION], ) component.async_register_entity_service(SERVICE_STOP_COVER, {}, "async_stop_cover", [SUPPORT_STOP]) component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle", [SUPPORT_OPEN | SUPPORT_CLOSE]) component.async_register_entity_service(SERVICE_OPEN_COVER_TILT, {}, "async_open_cover_tilt", [SUPPORT_OPEN_TILT]) component.async_register_entity_service(SERVICE_CLOSE_COVER_TILT, {}, "async_close_cover_tilt", [SUPPORT_CLOSE_TILT]) component.async_register_entity_service(SERVICE_STOP_COVER_TILT, {}, "async_stop_cover_tilt", [SUPPORT_STOP_TILT]) component.async_register_entity_service( SERVICE_SET_COVER_TILT_POSITION, { vol.Required(ATTR_TILT_POSITION): vol.All(vol.Coerce(int), vol.Range(min=0, max=100)) }, "async_set_cover_tilt_position", [SUPPORT_SET_TILT_POSITION], ) component.async_register_entity_service( SERVICE_TOGGLE_COVER_TILT, {}, "async_toggle_tilt", [SUPPORT_OPEN_TILT | SUPPORT_CLOSE_TILT], ) return True
async def async_setup_entry(opp, entry): """Set up an entry.""" component: Optional[EntityComponent] = opp.data.get(DOMAIN) if component is None: component = opp.data[DOMAIN] = EntityComponent(LOGGER, DOMAIN, opp) return await component.async_setup_entry(entry)
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up an entry.""" component: EntityComponent | None = opp.data.get(DOMAIN) if component is None: component = opp.data[DOMAIN] = EntityComponent(LOGGER, DOMAIN, opp) return await component.async_setup_entry(entry)
async def test_async_remove_with_platform(opp): """Remove an entity from a platform.""" component = EntityComponent(_LOGGER, DOMAIN, opp) entity1 = MockEntity(name="test_1") await component.async_add_entities([entity1]) assert len(opp.states.async_entity_ids()) == 1 await entity1.async_remove() assert len(opp.states.async_entity_ids()) == 0
async def async_setup(opp, config): """Load the scripts from the configuration.""" opp.data[DOMAIN] = component = EntityComponent(_LOGGER, DOMAIN, opp) await _async_process_config(opp, config, component) async def reload_service(service): """Call a service to reload scripts.""" conf = await component.async_prepare_reload() if conf is None: return await _async_process_config(opp, conf, component) async def turn_on_service(service): """Call a service to turn script on.""" # We could turn on script directly here, but we only want to offer # one way to do it. Otherwise no easy way to detect invocations. var = service.data.get(ATTR_VARIABLES) for script in await component.async_extract_from_service(service): await opp.services.async_call(DOMAIN, script.object_id, var, context=service.context) async def turn_off_service(service): """Cancel a script.""" # Stopping a script is ok to be done in parallel scripts = await component.async_extract_from_service(service) if not scripts: return await asyncio.wait([script.async_turn_off() for script in scripts]) async def toggle_service(service): """Toggle a script.""" for script in await component.async_extract_from_service(service): await script.async_toggle(context=service.context) opp.services.async_register(DOMAIN, SERVICE_RELOAD, reload_service, schema=RELOAD_SERVICE_SCHEMA) opp.services.async_register(DOMAIN, SERVICE_TURN_ON, turn_on_service, schema=SCRIPT_TURN_ONOFF_SCHEMA) opp.services.async_register(DOMAIN, SERVICE_TURN_OFF, turn_off_service, schema=SCRIPT_TURN_ONOFF_SCHEMA) opp.services.async_register(DOMAIN, SERVICE_TOGGLE, toggle_service, schema=SCRIPT_TURN_ONOFF_SCHEMA) return True
async def async_setup(opp: OpenPeerPower, config: ConfigType) -> bool: """Set up an input boolean.""" component = EntityComponent(_LOGGER, DOMAIN, opp) id_manager = collection.IDManager() yaml_collection = collection.YamlCollection( logging.getLogger(f"{__name__}.yaml_collection"), id_manager) collection.sync_entity_lifecycle(opp, DOMAIN, DOMAIN, component, yaml_collection, InputBoolean.from_yaml) storage_collection = InputBooleanStorageCollection( Store(opp, STORAGE_VERSION, STORAGE_KEY), logging.getLogger(f"{__name__}.storage_collection"), id_manager, ) collection.sync_entity_lifecycle(opp, DOMAIN, DOMAIN, component, storage_collection, InputBoolean) await yaml_collection.async_load([{ CONF_ID: id_, **(conf or {}) } for id_, conf in config.get(DOMAIN, {}).items()]) await storage_collection.async_load() collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS).async_setup(opp) async def reload_service_handler(service_call: ServiceCall) -> None: """Remove all input booleans and load new ones from config.""" conf = await component.async_prepare_reload(skip_reset=True) if conf is None: return await yaml_collection.async_load([{ CONF_ID: id_, **(conf or {}) } for id_, conf in conf.get(DOMAIN, {}).items()]) openpeerpower.helpers.service.async_register_admin_service( opp, DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=RELOAD_SERVICE_SCHEMA, ) component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_turn_on") component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off") component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle") return True
async def async_setup(opp: OpenPeerPower, config: ConfigType) -> bool: """Track states and offer events for remotes.""" component = opp.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, opp, SCAN_INTERVAL) await component.async_setup(config) component.async_register_entity_service(SERVICE_TURN_OFF, REMOTE_SERVICE_ACTIVITY_SCHEMA, "async_turn_off") component.async_register_entity_service(SERVICE_TURN_ON, REMOTE_SERVICE_ACTIVITY_SCHEMA, "async_turn_on") component.async_register_entity_service(SERVICE_TOGGLE, REMOTE_SERVICE_ACTIVITY_SCHEMA, "async_toggle") component.async_register_entity_service( SERVICE_SEND_COMMAND, { vol.Required(ATTR_COMMAND): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_DEVICE): cv.string, vol.Optional(ATTR_NUM_REPEATS, default=DEFAULT_NUM_REPEATS): cv.positive_int, vol.Optional(ATTR_DELAY_SECS): vol.Coerce(float), vol.Optional(ATTR_HOLD_SECS, default=DEFAULT_HOLD_SECS): vol.Coerce(float), }, "async_send_command", ) component.async_register_entity_service( SERVICE_LEARN_COMMAND, { vol.Optional(ATTR_DEVICE): cv.string, vol.Optional(ATTR_COMMAND): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_COMMAND_TYPE): cv.string, vol.Optional(ATTR_ALTERNATIVE): cv.boolean, vol.Optional(ATTR_TIMEOUT): cv.positive_int, }, "async_learn_command", ) component.async_register_entity_service( SERVICE_DELETE_COMMAND, { vol.Required(ATTR_COMMAND): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_DEVICE): cv.string, }, "async_delete_command", ) return True
async def test_set_scan_interval_via_config(mock_track, opp): """Test the setting of the scan interval via configuration.""" def platform_setup(opp, config, add_entities, discovery_info=None): """Test the platform setup.""" add_entities([MockEntity(should_poll=True)]) mock_entity_platform(opp, "test_domain.platform", MockPlatform(platform_setup)) component = EntityComponent(_LOGGER, DOMAIN, opp) component.setup( {DOMAIN: {"platform": "platform", "scan_interval": timedelta(seconds=30)}} ) await opp.async_block_till_done() assert mock_track.called assert timedelta(seconds=30) == mock_track.call_args[0][2]
async def async_setup(opp: OpenPeerPowerType, config: ConfigType): """Set up the person component.""" entity_component = EntityComponent(_LOGGER, DOMAIN, opp) id_manager = collection.IDManager() yaml_collection = collection.YamlCollection( logging.getLogger(f"{__name__}.yaml_collection"), id_manager) storage_collection = PersonStorageCollection( PersonStore(opp, STORAGE_VERSION, STORAGE_KEY), logging.getLogger(f"{__name__}.storage_collection"), id_manager, yaml_collection, ) collection.attach_entity_component_collection( entity_component, yaml_collection, lambda conf: Person(conf, False)) collection.attach_entity_component_collection( entity_component, storage_collection, lambda conf: Person(conf, True)) collection.attach_entity_registry_cleaner(opp, DOMAIN, DOMAIN, yaml_collection) collection.attach_entity_registry_cleaner(opp, DOMAIN, DOMAIN, storage_collection) await yaml_collection.async_load(await filter_yaml_data(opp, config.get(DOMAIN, []))) await storage_collection.async_load() opp.data[DOMAIN] = (yaml_collection, storage_collection) collection.StorageCollectionWebsocket( storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS).async_setup(opp, create_list=False) websocket_api.async_register_command(opp, ws_list_person) async def _handle_user_removed(event: Event) -> None: """Handle a user being removed.""" user_id = event.data[ATTR_USER_ID] for person in storage_collection.async_items(): if person[CONF_USER_ID] == user_id: await storage_collection.async_update_item( person[CONF_ID], {CONF_USER_ID: None}) opp.bus.async_listen(EVENT_USER_REMOVED, _handle_user_removed) async def async_reload_yaml(call: ServiceCall): """Reload YAML.""" conf = await entity_component.async_prepare_reload(skip_reset=True) if conf is None: return await yaml_collection.async_load(await filter_yaml_data( opp, conf.get(DOMAIN, []))) service.async_register_admin_service(opp, DOMAIN, SERVICE_RELOAD, async_reload_yaml) return True
async def test_set_service_race(opp): """Test race condition on setting service.""" exception = False def async_loop_exception_handler(_, _2) -> None: """Handle all exception inside the core loop.""" nonlocal exception exception = True opp.loop.set_exception_handler(async_loop_exception_handler) await async_setup_component(opp, "group", {}) component = EntityComponent(_LOGGER, DOMAIN, opp) for _ in range(2): opp.async_create_task(component.async_add_entities([MockEntity()])) await opp.async_block_till_done() assert not exception