async def test_initial_state_overrules_restore_state(opp): """Ensure states are restored on startup.""" mock_restore_cache( opp, ( State("input_select.s1", "last option"), State("input_select.s2", "bad option"), ), ) options = { "options": ["first option", "middle option", "last option"], "initial": "middle option", } await async_setup_component(opp, DOMAIN, {DOMAIN: { "s1": options, "s2": options }}) state = opp.states.get("input_select.s1") assert state assert state.state == "middle option" state = opp.states.get("input_select.s2") assert state assert state.state == "middle option"
async def test_initial_state_overrules_restore_state(opp): """Ensure states are restored on startup.""" mock_restore_cache( opp, (State("counter.test1", "11"), State("counter.test2", "-22")) ) opp.state = CoreState.starting await async_setup_component( opp, DOMAIN, { DOMAIN: { "test1": {CONF_RESTORE: False}, "test2": {CONF_INITIAL: 10, CONF_RESTORE: False}, } }, ) state = opp.states.get("counter.test1") assert state assert int(state.state) == 0 state = opp.states.get("counter.test2") assert state assert int(state.state) == 10
async def test_caching_data(opp): """Test that we cache data.""" now = dt_util.utcnow() stored_states = [ StoredState(State("input_boolean.b0", "on"), now), StoredState(State("input_boolean.b1", "on"), now), StoredState(State("input_boolean.b2", "on"), now), ] data = await RestoreStateData.async_get_instance(opp) await opp.async_block_till_done() await data.store.async_save([state.as_dict() for state in stored_states]) # Emulate a fresh load opp.data[DATA_RESTORE_STATE_TASK] = None entity = RestoreEntity() entity.opp = opp entity.entity_id = "input_boolean.b1" # Mock that only b1 is present this run with patch("openpeerpower.helpers.restore_state.Store.async_save" ) as mock_write_data: state = await entity.async_get_last_state() await opp.async_block_till_done() assert state is not None assert state.entity_id == "input_boolean.b1" assert state.state == "on" assert mock_write_data.called
def test_async_match_state(): """Test async_match_state helper.""" state1 = State("light.kitchen", "on") state2 = State("switch.kitchen", "on") state = intent.async_match_state(None, "kitch", [state1, state2]) assert state is state1
async def test_initial_state_overrules_restore_state(opp): """Ensure states are restored on startup.""" mock_restore_cache( opp, (State("input_text.b1", "testing"), State("input_text.b2", "testing too long")), ) opp.state = CoreState.starting await async_setup_component( opp, DOMAIN, { DOMAIN: { "b1": {"initial": "test", "min": 0, "max": 10}, "b2": {"initial": "test", "min": 0, "max": 10}, } }, ) state = opp.states.get("input_text.b1") assert state assert str(state.state) == "test" state = opp.states.get("input_text.b2") assert state assert str(state.state) == "test"
async def test_dump_error(opp): """Test that we cache data.""" states = [ State("input_boolean.b0", "on"), State("input_boolean.b1", "on"), State("input_boolean.b2", "on"), ] entity = Entity() entity.opp = opp entity.entity_id = "input_boolean.b0" await entity.async_internal_added_to_opp() entity = RestoreEntity() entity.opp = opp entity.entity_id = "input_boolean.b1" await entity.async_internal_added_to_opp() data = await RestoreStateData.async_get_instance(opp) with patch( "openpeerpower.helpers.restore_state.Store.async_save", side_effect=OpenPeerPowerError, ) as mock_write_data, patch.object(opp.states, "async_all", return_value=states): await data.async_dump_states() assert mock_write_data.called
async def test_restore_state_climate(opp): """Run test for sensor restore state.""" climate_name = "test_climate" test_temp = 37 entity_id = f"{CLIMATE_DOMAIN}.{climate_name}" test_value = State(entity_id, 35) test_value.attributes = {ATTR_TEMPERATURE: test_temp} config_sensor = { CONF_NAME: climate_name, CONF_TARGET_TEMP: 117, CONF_CURRENT_TEMP: 117, } mock_restore_cache( opp, (test_value, ), ) await base_config_test( opp, config_sensor, climate_name, CLIMATE_DOMAIN, CONF_CLIMATES, None, method_discovery=True, ) state = opp.states.get(entity_id) assert state.state == HVAC_MODE_AUTO assert state.attributes[ATTR_TEMPERATURE] == test_temp
async def test_initial_state_overrules_restore_state(opp): """Ensure states are restored on startup.""" mock_restore_cache( opp, (State("input_number.b1", "70"), State("input_number.b2", "200"))) opp.state = CoreState.starting await async_setup_component( opp, DOMAIN, { DOMAIN: { "b1": { "initial": 50, "min": 0, "max": 100 }, "b2": { "initial": 60, "min": 0, "max": 100 }, } }, ) state = opp.states.get("input_number.b1") assert state assert float(state.state) == 50 state = opp.states.get("input_number.b2") assert state assert float(state.state) == 60
async def test_restore_state_overrules_initial_state(opp): """Ensure states are restored on startup.""" attr = {"initial": 6, "minimum": 1, "maximum": 8, "step": 2} mock_restore_cache( opp, ( State("counter.test1", "11"), State("counter.test2", "-22"), State("counter.test3", "5", attr), ), ) opp.state = CoreState.starting await async_setup_component( opp, DOMAIN, {DOMAIN: {"test1": {}, "test2": {CONF_INITIAL: 10}, "test3": {}}} ) state = opp.states.get("counter.test1") assert state assert int(state.state) == 11 state = opp.states.get("counter.test2") assert state assert int(state.state) == -22 state = opp.states.get("counter.test3") assert state assert int(state.state) == 5 assert state.attributes.get("initial") == 6 assert state.attributes.get("minimum") == 1 assert state.attributes.get("maximum") == 8 assert state.attributes.get("step") == 2
async def test_significant_change_extra(opp, checker): """Test extra significant checker works.""" ent_id = "test_domain.test_entity" attrs = {ATTR_DEVICE_CLASS: DEVICE_CLASS_BATTERY} assert checker.async_is_significant_change(State(ent_id, "100", attrs), extra_arg=1) assert checker.async_is_significant_change(State(ent_id, "200", attrs), extra_arg=1) # Reset the last significiant change to 100 to repeat test but with # extra checker installed. assert checker.async_is_significant_change(State(ent_id, "100", attrs), extra_arg=1) def extra_significant_check( opp, old_state, old_attrs, old_extra_arg, new_state, new_attrs, new_extra_arg ): return old_extra_arg != new_extra_arg checker.extra_significant_check = extra_significant_check # This is normally a significant change (100 -> 200), but the extra arg check marks it # as insignificant. assert not checker.async_is_significant_change( State(ent_id, "200", attrs), extra_arg=1 ) assert checker.async_is_significant_change(State(ent_id, "200", attrs), extra_arg=2)
async def test_restore_state(opp): """Test utility sensor restore state.""" last_reset = "2020-12-21T00:00:00.013073+00:00" config = { "utility_meter": { "energy_bill": { "source": "sensor.energy", "tariffs": ["onpeak", "midpeak", "offpeak"], } } } mock_restore_cache( opp, [ State( "sensor.energy_bill_onpeak", "3", attributes={ ATTR_STATUS: PAUSED, ATTR_LAST_RESET: last_reset, }, ), State( "sensor.energy_bill_offpeak", "6", attributes={ ATTR_STATUS: COLLECTING, ATTR_LAST_RESET: last_reset, }, ), ], ) assert await async_setup_component(opp, DOMAIN, config) await opp.async_block_till_done() # restore from cache state = opp.states.get("sensor.energy_bill_onpeak") assert state.state == "3" assert state.attributes.get("status") == PAUSED assert state.attributes.get("last_reset") == last_reset state = opp.states.get("sensor.energy_bill_offpeak") assert state.state == "6" assert state.attributes.get("status") == COLLECTING assert state.attributes.get("last_reset") == last_reset # utility_meter is loaded, now set sensors according to utility_meter: opp.bus.async_fire(EVENT_OPENPEERPOWER_START) await opp.async_block_till_done() state = opp.states.get("utility_meter.energy_bill") assert state.state == "onpeak" state = opp.states.get("sensor.energy_bill_onpeak") assert state.attributes.get("status") == COLLECTING state = opp.states.get("sensor.energy_bill_offpeak") assert state.attributes.get("status") == PAUSED
async def test_state_changed_event_include_domain_globs_exclude_entity( opp, mqtt_mock): """Test filtering with included domain and glob and excluded entity.""" base_topic = "pub" incl = {"domains": ["fake"], "entity_globs": ["*.included_*"]} excl = {"entities": ["fake.entity2"]} # Add the statestream component for publishing state updates # Set the filter to include with exclude filter assert await add_statestream(opp, base_topic=base_topic, publish_include=incl, publish_exclude=excl) await opp.async_block_till_done() # Reset the mock because it will have already gotten calls for the # mqtt_statestream state change on initialization, etc. mqtt_mock.async_publish.reset_mock() # Set a state of an entity included by domain mock_state_change_event(opp, State("fake.entity", "on")) await opp.async_block_till_done() await opp.async_block_till_done() # Make sure 'on' was published to pub/fake/entity/state mqtt_mock.async_publish.assert_called_with("pub/fake/entity/state", "on", 1, True) assert mqtt_mock.async_publish.called mqtt_mock.async_publish.reset_mock() # Set a state of an entity included by glob mock_state_change_event(opp, State("fake.included_entity", "on")) await opp.async_block_till_done() await opp.async_block_till_done() # Make sure 'on' was published to pub/fake/entity/state mqtt_mock.async_publish.assert_called_with( "pub/fake/included_entity/state", "on", 1, True) assert mqtt_mock.async_publish.called mqtt_mock.async_publish.reset_mock() # Set a state of an entity that shouldn't be included mock_state_change_event(opp, State("fake.entity2", "on")) await opp.async_block_till_done() await opp.async_block_till_done() assert not mqtt_mock.async_publish.called mqtt_mock.async_publish.reset_mock() # Set a state of an entity that doesn't match any filters mock_state_change_event(opp, State("fake2.entity", "on")) await opp.async_block_till_done() await opp.async_block_till_done() assert not mqtt_mock.async_publish.called
def test_closest_with_no_states_with_location(): """Set up the tests.""" state = State("light.test", "on") state2 = State("light.test", "on", { ATTR_LATITUDE: "invalid", ATTR_LONGITUDE: 123.45 }) state3 = State("light.test", "on", {ATTR_LONGITUDE: 123.45}) assert location.closest(123.45, 123.45, [state, state2, state3]) is None
def test_validate_media_player_features(): """Test validate modes for media players.""" config = {} attrs = {ATTR_SUPPORTED_FEATURES: 20873} entity_state = State("media_player.demo", "on", attrs) assert validate_media_player_features(entity_state, config) is True config = {FEATURE_ON_OFF: None} assert validate_media_player_features(entity_state, config) is True entity_state = State("media_player.demo", "on") assert validate_media_player_features(entity_state, config) is False
async def test_automation_restore_state(opp): """Ensure states are restored on startup.""" time = dt_util.utcnow() mock_restore_cache( opp, ( State("automation.hello", STATE_ON), State("automation.bye", STATE_OFF, {"last_triggered": time}), ), ) config = { automation.DOMAIN: [ { "alias": "hello", "trigger": {"platform": "event", "event_type": "test_event_hello"}, "action": {"service": "test.automation"}, }, { "alias": "bye", "trigger": {"platform": "event", "event_type": "test_event_bye"}, "action": {"service": "test.automation"}, }, ] } assert await async_setup_component(opp, automation.DOMAIN, config) state = opp.states.get("automation.hello") assert state assert state.state == STATE_ON assert state.attributes["last_triggered"] is None state = opp.states.get("automation.bye") assert state assert state.state == STATE_OFF assert state.attributes["last_triggered"] == time calls = async_mock_service(opp, "test", "automation") assert automation.is_on(opp, "automation.bye") is False opp.bus.async_fire("test_event_bye") await opp.async_block_till_done() assert len(calls) == 0 assert automation.is_on(opp, "automation.hello") opp.bus.async_fire("test_event_hello") await opp.async_block_till_done() assert len(calls) == 1
def test_closest_returns_closest(): """Test .""" state = State("light.test", "on", { ATTR_LATITUDE: 124.45, ATTR_LONGITUDE: 124.45 }) state2 = State("light.test", "on", { ATTR_LATITUDE: 125.45, ATTR_LONGITUDE: 125.45 }) assert state == location.closest(123.45, 123.45, [state, state2])
async def test_play_media(opp): """Test that no state service call is made with none state.""" calls_1 = async_mock_service(opp, DOMAIN, SERVICE_PLAY_MEDIA) value_1 = "dummy_1" value_2 = "dummy_2" value_3 = "dummy_3" await async_reproduce_states( opp, [ State( ENTITY_1, None, { ATTR_MEDIA_CONTENT_TYPE: value_1, ATTR_MEDIA_CONTENT_ID: value_2 }, ) ], ) await async_reproduce_states( opp, [ State( ENTITY_1, None, { ATTR_MEDIA_CONTENT_TYPE: value_1, ATTR_MEDIA_CONTENT_ID: value_2, ATTR_MEDIA_ENQUEUE: value_3, }, ) ], ) await opp.async_block_till_done() assert len(calls_1) == 2 assert calls_1[0].data == { "entity_id": ENTITY_1, ATTR_MEDIA_CONTENT_TYPE: value_1, ATTR_MEDIA_CONTENT_ID: value_2, } assert calls_1[1].data == { "entity_id": ENTITY_1, ATTR_MEDIA_CONTENT_TYPE: value_1, ATTR_MEDIA_CONTENT_ID: value_2, ATTR_MEDIA_ENQUEUE: value_3, }
async def test_automation_restore_last_triggered_with_initial_state(opp): """Ensure last_triggered is restored, even when initial state is set.""" time = dt_util.utcnow() mock_restore_cache( opp, ( State("automation.hello", STATE_ON), State("automation.bye", STATE_ON, {"last_triggered": time}), State("automation.solong", STATE_OFF, {"last_triggered": time}), ), ) config = { automation.DOMAIN: [ { "alias": "hello", "initial_state": "off", "trigger": {"platform": "event", "event_type": "test_event"}, "action": {"service": "test.automation"}, }, { "alias": "bye", "initial_state": "off", "trigger": {"platform": "event", "event_type": "test_event"}, "action": {"service": "test.automation"}, }, { "alias": "solong", "initial_state": "on", "trigger": {"platform": "event", "event_type": "test_event"}, "action": {"service": "test.automation"}, }, ] } await async_setup_component(opp, automation.DOMAIN, config) state = opp.states.get("automation.hello") assert state assert state.state == STATE_OFF assert state.attributes["last_triggered"] is None state = opp.states.get("automation.bye") assert state assert state.state == STATE_OFF assert state.attributes["last_triggered"] == time state = opp.states.get("automation.solong") assert state assert state.state == STATE_ON assert state.attributes["last_triggered"] == time
async def test_restore_will_turn_off_(opp): """Ensure that restored state is coherent with real situation. Thermostat status must trigger heater event if temp raises the target . """ heater_switch = "input_boolean.test" mock_restore_cache( opp, ( State( "climate.test_thermostat", HVAC_MODE_HEAT, { ATTR_TEMPERATURE: "18", ATTR_PRESET_MODE: PRESET_NONE }, ), State(heater_switch, STATE_ON, {}), ), ) opp.state = CoreState.starting assert await async_setup_component(opp, input_boolean.DOMAIN, {"input_boolean": { "test": None }}) await opp.async_block_till_done() assert opp.states.get(heater_switch).state == STATE_ON _setup_sensor(opp, 22) await async_setup_component( opp, DOMAIN, { "climate": { "platform": "generic_thermostat", "name": "test_thermostat", "heater": heater_switch, "target_sensor": ENT_SENSOR, "target_temp": 20, } }, ) await opp.async_block_till_done() state = opp.states.get("climate.test_thermostat") assert state.attributes[ATTR_TEMPERATURE] == 20 assert state.state == HVAC_MODE_HEAT assert opp.states.get(heater_switch).state == STATE_ON
async def test_restore_state(opp, monkeypatch): """Ensure states are restored on startup.""" config = { "rflink": { "port": "/dev/ttyABC0" }, DOMAIN: { "platform": "rflink", "devices": { "RTS_12345678_0": { "name": "c1" }, "test_restore_2": { "name": "c2" }, "test_restore_3": { "name": "c3" }, "test_restore_4": { "name": "c4" }, }, }, } mock_restore_cache(opp, (State( f"{DOMAIN}.c1", STATE_OPEN), State(f"{DOMAIN}.c2", STATE_CLOSED))) opp.state = CoreState.starting # setup mocking rflink module _, _, _, _ = await mock_rflink(opp, config, DOMAIN, monkeypatch) state = opp.states.get(f"{DOMAIN}.c1") assert state assert state.state == STATE_OPEN state = opp.states.get(f"{DOMAIN}.c2") assert state assert state.state == STATE_CLOSED state = opp.states.get(f"{DOMAIN}.c3") assert state assert state.state == STATE_CLOSED # not cached cover must default values state = opp.states.get(f"{DOMAIN}.c4") assert state assert state.state == STATE_CLOSED assert state.attributes["assumed_state"]
async def test_restore_state(opp): """Test state restoration.""" mock_restore_cache( opp, ( State("switch.s1", STATE_ON), State("switch.s2", STATE_OFF), ), ) opp.state = CoreState.starting mock_component(opp, "recorder") await async_setup_component( opp, "switch", { "switch": { "platform": "template", "switches": { "s1": { "turn_on": { "service": "test.automation" }, "turn_off": { "service": "test.automation" }, }, "s2": { "turn_on": { "service": "test.automation" }, "turn_off": { "service": "test.automation" }, }, }, } }, ) await opp.async_block_till_done() state = opp.states.get("switch.s1") assert state assert state.state == STATE_ON state = opp.states.get("switch.s2") assert state assert state.state == STATE_OFF
async def test_multiple_different_state(opp): """Test that multiple states with different state gets calls.""" calls_1 = async_mock_service(opp, DOMAIN, SERVICE_TURN_ON) calls_2 = async_mock_service(opp, DOMAIN, SERVICE_TURN_OFF) await async_reproduce_states( opp, [State(ENTITY_1, "on"), State(ENTITY_2, "off")]) await opp.async_block_till_done() assert len(calls_1) == 1 assert calls_1[0].data == {"entity_id": "media_player.test1"} assert len(calls_2) == 1 assert calls_2[0].data == {"entity_id": "media_player.test2"}
async def test_multiple_modes(opp): """Test that multiple states gets calls.""" opp.states.async_set(ENTITY_1, STATE_OFF, {}) opp.states.async_set(ENTITY_2, STATE_OFF, {}) turn_on_calls = async_mock_service(opp, DOMAIN, SERVICE_TURN_ON) turn_off_calls = async_mock_service(opp, DOMAIN, SERVICE_TURN_OFF) mode_calls = async_mock_service(opp, DOMAIN, SERVICE_SET_MODE) humidity_calls = async_mock_service(opp, DOMAIN, SERVICE_SET_HUMIDITY) await async_reproduce_states( opp, [ State(ENTITY_1, STATE_ON, { ATTR_MODE: MODE_ECO, ATTR_HUMIDITY: 40 }), State(ENTITY_2, STATE_ON, { ATTR_MODE: MODE_NORMAL, ATTR_HUMIDITY: 50 }), ], ) await opp.async_block_till_done() assert len(turn_on_calls) == 2 assert len(turn_off_calls) == 0 assert len(mode_calls) == 2 # order is not guaranteed assert any(call.data == { "entity_id": ENTITY_1, "mode": MODE_ECO } for call in mode_calls) assert any(call.data == { "entity_id": ENTITY_2, "mode": MODE_NORMAL } for call in mode_calls) assert len(humidity_calls) == 2 # order is not guaranteed assert any(call.data == { "entity_id": ENTITY_1, "humidity": 40 } for call in humidity_calls) assert any(call.data == { "entity_id": ENTITY_2, "humidity": 50 } for call in humidity_calls)
async def create_service(call): """Create a scene.""" snapshot = call.data[CONF_SNAPSHOT] entities = call.data[CONF_ENTITIES] for entity_id in snapshot: state = opp.states.get(entity_id) if state is None: _LOGGER.warning( "Entity %s does not exist and therefore cannot be snapshotted", entity_id, ) continue entities[entity_id] = State(entity_id, state.state, state.attributes) if not entities: _LOGGER.warning("Empty scenes are not allowed") return scene_config = SCENECONFIG(None, call.data[CONF_SCENE_ID], None, entities) entity_id = f"{SCENE_DOMAIN}.{scene_config.name}" old = platform.entities.get(entity_id) if old is not None: if not old.from_service: _LOGGER.warning("The scene %s already exists", entity_id) return await platform.async_remove_entity(entity_id) async_add_entities( [OpenPeerPowerScene(opp, scene_config, from_service=True)])
async def test_restore_state_cover(opp, state): """Run test for cover restore state.""" entity_id = "cover.test" cover_name = "test" config = { CONF_NAME: cover_name, CALL_TYPE_COIL: 1234, CONF_STATE_OPEN: 1, CONF_STATE_CLOSED: 0, CONF_STATE_OPENING: 2, CONF_STATE_CLOSING: 3, CONF_STATUS_REGISTER: 1234, CONF_STATUS_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING, } mock_restore_cache( opp, (State(f"{entity_id}", state), ), ) await base_config_test( opp, config, cover_name, COVER_DOMAIN, CONF_COVERS, None, method_discovery=True, ) assert opp.states.get(entity_id).state == state
def test_supported_features_string(caplog): """Test bad supported features.""" entity = helpers.GoogleEntity( None, None, State("test.entity_id", "on", {"supported_features": "invalid"})) assert entity.is_supported() is False assert "Entity test.entity_id contains invalid supported_features value invalid"
async def test_multiple_attrs(opp): """Test turn on with multiple attributes.""" opp.states.async_set(ENTITY_1, STATE_OFF, {}) turn_on_calls = async_mock_service(opp, DOMAIN, SERVICE_TURN_ON) turn_off_calls = async_mock_service(opp, DOMAIN, SERVICE_TURN_OFF) mode_calls = async_mock_service(opp, DOMAIN, SERVICE_SET_MODE) humidity_calls = async_mock_service(opp, DOMAIN, SERVICE_SET_HUMIDITY) await async_reproduce_states(opp, [ State(ENTITY_1, STATE_ON, { ATTR_MODE: MODE_NORMAL, ATTR_HUMIDITY: 45 }) ]) await opp.async_block_till_done() assert len(turn_on_calls) == 1 assert turn_on_calls[0].data == {"entity_id": ENTITY_1} assert len(turn_off_calls) == 0 assert len(mode_calls) == 1 assert mode_calls[0].data == {"entity_id": ENTITY_1, "mode": "normal"} assert len(humidity_calls) == 1 assert humidity_calls[0].data == {"entity_id": ENTITY_1, "humidity": 45}
def _convert_states(states): """Convert state definitions to State objects.""" result = {} for entity_id in states: entity_id = cv.entity_id(entity_id) if isinstance(states[entity_id], dict): entity_attrs = states[entity_id].copy() state = entity_attrs.pop(ATTR_STATE, None) attributes = entity_attrs else: state = states[entity_id] attributes = {} # YAML translates 'on' to a boolean # http://yaml.org/type/bool.html if isinstance(state, bool): state = STATE_ON if state else STATE_OFF elif not isinstance(state, str): raise vol.Invalid(f"State for {entity_id} should be a string") result[entity_id] = State(entity_id, state, attributes) return result
async def test_state_with_context(opp): """Test that context is forwarded.""" opp.states.async_set(ENTITY_1, STATE_OFF, {}) turn_on_calls = async_mock_service(opp, DOMAIN, SERVICE_TURN_ON) turn_off_calls = async_mock_service(opp, DOMAIN, SERVICE_TURN_OFF) mode_calls = async_mock_service(opp, DOMAIN, SERVICE_SET_MODE) humidity_calls = async_mock_service(opp, DOMAIN, SERVICE_SET_HUMIDITY) context = Context() await async_reproduce_states( opp, [State(ENTITY_1, STATE_ON, { ATTR_MODE: MODE_AWAY, ATTR_HUMIDITY: 45 })], context=context, ) await opp.async_block_till_done() assert len(turn_on_calls) == 1 assert turn_on_calls[0].data == {"entity_id": ENTITY_1} assert turn_on_calls[0].context == context assert len(turn_off_calls) == 0 assert len(mode_calls) == 1 assert mode_calls[0].data == {"entity_id": ENTITY_1, "mode": "away"} assert mode_calls[0].context == context assert len(humidity_calls) == 1 assert humidity_calls[0].data == {"entity_id": ENTITY_1, "humidity": 45} assert humidity_calls[0].context == context
async def async_reproduce_states( opp: OpenPeerPower, states: Iterable[State], *, context: Context | None = None, reproduce_options: dict[str, Any] | None = None, ) -> None: """Reproduce component states.""" states_copy = [] for state in states: members = get_entity_ids(opp, state.entity_id) for member in members: states_copy.append( State( member, state.state, state.attributes, last_changed=state.last_changed, last_updated=state.last_updated, context=state.context, )) await async_reproduce_state(opp, states_copy, context=context, reproduce_options=reproduce_options)