示例#1
0
def execute_action(message):
	logging.debug(str(message))
	bulb = Bulb(message['dest'], 55443, 'smooth', 500, True,type=message['model'])
	command_list= message['command'].split(' ')
	if command_list[0] == 'turn':
		if command_list[1] == 'on':
			bulb.turn_on()
		else:
			bulb.turn_off()
	elif command_list[0] == 'stop':
		bulb.stop_flow()
	elif command_list[0] == 'rgb':
		red, green, blue = utils.hex_color_to_rgb(message['option'])
		bulb.set_rgb(red, green, blue)
	elif command_list[0] == 'toggle':
		bulb.toggle()
	elif command_list[0] == 'brightness':
		bulb.set_brightness(int(message['option']))
	elif command_list[0] == 'temperature':
		if len(command_list)>1:
			bulb.set_color_temp(int(command_list[1]))
		else:
			bulb.set_color_temp(int(message['option']))
	elif command_list[0] == 'flow':
		flow_params = message['option'].split(' ')
		translist = flow_params[2].split('-')
		list =[]
		for transition in translist:
			elements = transition.split(',')
			if elements[0] in globals.DICT_MAPPING_YEELIGHT:
				effect = globals.DICT_MAPPING_YEELIGHT[elements[0]]
				if elements[0] == 'hsv':
					list.append(effect(int(elements[1]),int(elements[2]),int(elements[3]),int(elements[4])))
				elif elements[0] == 'rgb' :
					list.append(effect(int(elements[1]),int(elements[2]),int(elements[3]),int(elements[4]),int(elements[5])))
				elif elements[0] == 'temp' :
					list.append(effect(int(elements[1]),int(elements[2]),int(elements[3])))
				else:
					list.append(effect(int(elements[1])))
			else:
				logging.debug("Not an effect")
			if flow_params[1] == 'recover':
				flow = Flow(int(flow_params[0]),Flow.actions.recover,list)
			elif flow_params[1] == 'stay' :
				flow = Flow(int(flow_params[0]),Flow.actions.stay,list)
			else:
				flow = Flow(int(flow_params[0]),Flow.actions.off,list)
			bulb.start_flow(flow)
	elif command_list[0] == 'cron':
		bulb.cron_add(enums.CronType.off, int(message['option']))
	elif command_list[0] == 'hsv':
		hsv_option = message['option'].split(' ')
		bulb.set_hsv(int(hsv_option[0]), int(hsv_option[1]))
	t = threading.Timer(2, refresh,args=(message,))
	t.start()
	return
示例#2
0
def strobe():
    """
    Rapid flashing on and off.

    :returns: An infinite Flow consisting of 2 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.strobe())
示例#3
0
def temp():
    """
    Slowly-changing color temperature.

    :returns: An infinite Flow consisting of 2 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.temp())
示例#4
0
def disco(bpm=120):
    """
    Color changes to the beat.

    :param int bpm: The beats per minute to pulse to.

    :returns: An infinite Flow consisting of 8 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.disco(bpm))
示例#5
0
def alarm(duration=250):
    """
    Red alarm; flashing bright red to dark red.

    :param int duration: The duration between hi/lo brightness,in milliseconds.

    :returns: An infinite Flow consisting of 2 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.alarm(duration))
示例#6
0
def strobe_color(brightness=100):
    """
    Rapid flashing colors.

    :param int brightness: The brightness of the transition.

    :returns: An infinite Flow consisting of 6 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.strobe_color(brightness))
示例#7
0
def lsd(duration=3000, brightness=100):
    """
    Gradual changes to a pleasing, trippy palette.

    :param int duration: The duration to fade to next color, in milliseconds.
    :param int brightness: The brightness of the transition.

    :returns: An infinite Flow consisting of 5 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.lsd(duration, brightness))
示例#8
0
def police2(duration=250, brightness=100):
    """
    Color flashes red and then blue, like urgent police lights.

    :param int duration: The duration to fade to next color, in milliseconds.
    :param int brightness: The brightness of the transition.

    :returns: An infinite Flow consisting of 8 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.police2(duration, brightness))
示例#9
0
def police(duration=300, brightness=100):
    """
    Color changes from red to blue, like police lights.

    :param int duration: The duration between red and blue, in milliseconds.
    :param int brightness: The brightness of the transition.

    :returns: An infinite Flow consisting of 2 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.police(duration, brightness))
示例#10
0
def night_mode(duration=500, brightness=1):
    """
    Dim the lights to a dark red, pleasant for the eyes at night.

    :param int duration: The duration to fade to next color, in milliseconds.
    :param int brightness: The brightness of the transition.

    :returns: An infinite Flow consisting of 1 transition.
    :rtype: Flow
    """
    transition = [RGBTransition(0xFF, 0x99, 0x00, duration=duration, brightness=brightness)]
    return Flow(count=0, action=Action.recover, transitions=transition)
示例#11
0
def christmas(duration=250, brightness=100, sleep=3000):
    """
    Color changes from red to green, like christmas lights.

    :param int duration: The duration between red and green, in milliseconds.
    :param int brightness: The brightness of the transition.
    :param int sleep: The time to sleep between colors, in milliseconds.

    :returns: An infinite Flow consisting of 4 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.christmas(duration, brightness, sleep))
示例#12
0
def rgb(duration=250, brightness=100, sleep=3000):
    """
    Color changes from red to green to blue.

    :param int duration: The duration to fade to next color, in milliseconds.
    :param int brightness: The brightness of the transition.
    :param int sleep: The time to sleep between colors, in milliseconds

    :returns: An infinite Flow consisting of 6 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.rgb(duration, brightness, sleep))
示例#13
0
def romance():
    """
    Romantic lights.

    :returns: An infinite Flow consisting of 2 transitions.
    :rtype: Flow
    """
    transitions = [
        RGBTransition(red=0x59, green=0x15, blue=0x6D, duration=4000, brightness=1),
        RGBTransition(red=0x66, green=0x14, blue=0x2A, duration=4000, brightness=1),
    ]
    return Flow(count=0, action=Action.stay, transitions=transitions)
示例#14
0
def random_loop(duration=750, brightness=100, count=9):
    """
    Color changes between `count` randomly chosen colors.

    :param int duration: The duration to fade to next color, in milliseconds.
    :param int brightness: The brightness of the transition.
    :param int count: The number of random chosen colors in transition.

    :returns: An infinite Flow consisting of up to 9 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.random_loop(duration, brightness, count))
示例#15
0
def movie(duration=500, brightness=50):
    """
    Dim the lights to a comfy purple.

    :param int duration: The duration to fade to next color, in milliseconds.
    :param int brightness: The brightness of the transition.

    :returns: An infinite Flow consisting of 1 transition.
    :rtype: Flow
    """
    transition = [RGBTransition(red=0x14, green=0x14, blue=0x32, duration=duration, brightness=brightness)]
    return Flow(count=0, action=Action.recover, transitions=transition)
示例#16
0
def date_night(duration=500, brightness=50):
    """
    Dim the lights to a cozy orange.

    :param int duration: The duration to fade to next color, in milliseconds.
    :param int brightness: The brightness of the transition.

    :returns: An infinite Flow consisting of 1 transition.
    :rtype: Flow
    """
    transition = [RGBTransition(0xFF, 0x66, 0x00, duration=duration, brightness=brightness)]
    return Flow(count=0, action=Action.recover, transitions=transition)
示例#17
0
def slowdown(duration=2000, brightness=100, count=8):
    """
    Changes between `count` random chosen colors with increasing transition time.

    :param int duration: The duration to fade to next color, in milliseconds.
    :param int brightness: The brightness of the transition.
    :param int count: The number of random chosen colors in transition.

    :returns: An infinite Flow consisting of up to 8 transitions.
    :rtype: Flow
    """
    return Flow(count=0, action=Action.recover, transitions=transitions.slowdown(duration, brightness, count))
示例#18
0
def home(duration=500, brightness=80):
    """
    Simulate daylight.

    :param int duration: The duration to fade to next color, in milliseconds.
    :param int brightness: The brightness of the transition.

    :returns: An infinite Flow consisting of 1 transition.
    :rtype: Flow
    """
    transition = [TemperatureTransition(degrees=3200, duration=duration, brightness=brightness)]
    return Flow(count=0, action=Action.recover, transitions=transition)
示例#19
0
def happy_birthday():
    """
    Happy Birthday lights.

    :returns: An infinite Flow consisting of 3 transitions.
    :rtype: Flow
    """
    transitions = [
        RGBTransition(red=0xDC, green=0x50, blue=0x19, duration=1996, brightness=80),
        RGBTransition(red=0xDC, green=0x78, blue=0x1E, duration=1996, brightness=80),
        RGBTransition(red=0xAA, green=0x32, blue=0x14, duration=1996, brightness=80),
    ]
    return Flow(count=0, action=Action.stay, transitions=transitions)
示例#20
0
def sunrise():
    """
    Simulate a natural and gentle sunrise in 15 minutes.

    :returns: A Flow consisting of 3 transitions, after which the bulb stays on.
    :rtype: Flow
    """
    transitions = [
        RGBTransition(red=0xFF, green=0x4D, blue=0x00, duration=50, brightness=1),
        TemperatureTransition(degrees=1700, duration=360000, brightness=10),
        TemperatureTransition(degrees=2700, duration=540000, brightness=100),
    ]
    return Flow(count=1, action=Action.stay, transitions=transitions)
示例#21
0
def sunset():
    """
    Simulate a natural sunset and offering relaxing dimming to help you sleep in 10 minutes.

    :returns: A Flow consisting of 3 transitions, after which the bulb turns off.
    :rtype: Flow
    """
    transitions = [
        TemperatureTransition(degrees=2700, duration=50, brightness=10),
        TemperatureTransition(degrees=1700, duration=180000, brightness=5),
        RGBTransition(red=0xFF, green=0x4C, blue=0x00, duration=420000, brightness=1),
    ]
    return Flow(count=1, action=Action.off, transitions=transitions)
示例#22
0
def pulse(red, green, blue, duration=250, brightness=100):
    """
    Pulse a single color once (mainly to be used for notifications).

    :param int red: The red color component to pulse (0-255).
    :param int green: The green color component to pulse (0-255).
    :param int blue: The blue color component to pulse (0-255).
    :param int duration: The duration to pulse for, in milliseconds.
    :param int brightness: The brightness to pulse at (1-100).

    :returns: A Flow consisting of 2 transitions, after which the bulb returns to its previous state.
    :rtype: Flow
    """
    return Flow(count=1, action=Action.recover, transitions=transitions.pulse(red, green, blue, duration, brightness))
示例#23
0
def candle_flicker():
    """
    Simulate candle flicker.

    :returns: An infinite Flow consisting of 9 transitions.
    :rtype: Flow
    """
    transitions = [
        TemperatureTransition(degrees=2700, duration=800, brightness=50),
        TemperatureTransition(degrees=2700, duration=800, brightness=30),
        TemperatureTransition(degrees=2700, duration=1200, brightness=80),
        TemperatureTransition(degrees=2700, duration=800, brightness=60),
        TemperatureTransition(degrees=2700, duration=1200, brightness=90),
        TemperatureTransition(degrees=2700, duration=2400, brightness=50),
        TemperatureTransition(degrees=2700, duration=1200, brightness=80),
        TemperatureTransition(degrees=2700, duration=800, brightness=60),
        TemperatureTransition(degrees=2700, duration=400, brightness=70),
    ]
    return Flow(count=0, action=Action.recover, transitions=transitions)
示例#24
0
async def test_effects(hass: HomeAssistant):
    """Test effects."""
    assert await async_setup_component(
        hass,
        DOMAIN,
        {
            DOMAIN: {
                CONF_CUSTOM_EFFECTS: [
                    {
                        CONF_NAME: "mock_effect",
                        CONF_FLOW_PARAMS: {
                            ATTR_COUNT: 3,
                            ATTR_TRANSITIONS: [
                                {YEELIGHT_HSV_TRANSACTION: [300, 50, 500, 50]},
                                {YEELIGHT_RGB_TRANSITION: [100, 100, 100, 300, 30]},
                                {YEELIGHT_TEMPERATURE_TRANSACTION: [3000, 200, 20]},
                                {YEELIGHT_SLEEP_TRANSACTION: [800]},
                            ],
                        },
                    }
                ]
            }
        },
    )

    config_entry = MockConfigEntry(domain=DOMAIN, data=CONFIG_ENTRY_DATA)
    config_entry.add_to_hass(hass)

    mocked_bulb = _mocked_bulb()
    with _patch_discovery(), _patch_discovery_interval(), patch(
        f"{MODULE}.AsyncBulb", return_value=mocked_bulb
    ):
        assert await hass.config_entries.async_setup(config_entry.entry_id)
        await hass.async_block_till_done()

    assert hass.states.get(ENTITY_LIGHT).attributes.get(
        "effect_list"
    ) == YEELIGHT_COLOR_EFFECT_LIST + ["mock_effect"]

    async def _async_test_effect(name, target=None, called=True):
        async_mocked_start_flow = AsyncMock()
        mocked_bulb.async_start_flow = async_mocked_start_flow
        await hass.services.async_call(
            "light",
            SERVICE_TURN_ON,
            {ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_EFFECT: name},
            blocking=True,
        )
        if not called:
            return
        async_mocked_start_flow.assert_called_once()
        if target is None:
            return
        args, _ = async_mocked_start_flow.call_args
        flow = args[0]
        assert flow.count == target.count
        assert flow.action == target.action
        assert str(flow.transitions) == str(target.transitions)

    effects = {
        "mock_effect": Flow(
            count=3,
            transitions=[
                HSVTransition(300, 50, 500, 50),
                RGBTransition(100, 100, 100, 300, 30),
                TemperatureTransition(3000, 200, 20),
                SleepTransition(800),
            ],
        ),
        EFFECT_DISCO: Flow(transitions=transitions.disco()),
        EFFECT_FAST_RANDOM_LOOP: None,
        EFFECT_WHATSAPP: Flow(count=2, transitions=transitions.pulse(37, 211, 102)),
        EFFECT_FACEBOOK: Flow(count=2, transitions=transitions.pulse(59, 89, 152)),
        EFFECT_TWITTER: Flow(count=2, transitions=transitions.pulse(0, 172, 237)),
        EFFECT_HOME: Flow(
            count=0,
            action=Action.recover,
            transitions=[
                TemperatureTransition(degrees=3200, duration=500, brightness=80)
            ],
        ),
        EFFECT_NIGHT_MODE: Flow(
            count=0,
            action=Action.recover,
            transitions=[RGBTransition(0xFF, 0x99, 0x00, duration=500, brightness=1)],
        ),
        EFFECT_DATE_NIGHT: Flow(
            count=0,
            action=Action.recover,
            transitions=[RGBTransition(0xFF, 0x66, 0x00, duration=500, brightness=50)],
        ),
        EFFECT_MOVIE: Flow(
            count=0,
            action=Action.recover,
            transitions=[
                RGBTransition(
                    red=0x14, green=0x14, blue=0x32, duration=500, brightness=50
                )
            ],
        ),
        EFFECT_SUNRISE: Flow(
            count=1,
            action=Action.stay,
            transitions=[
                RGBTransition(
                    red=0xFF, green=0x4D, blue=0x00, duration=50, brightness=1
                ),
                TemperatureTransition(degrees=1700, duration=360000, brightness=10),
                TemperatureTransition(degrees=2700, duration=540000, brightness=100),
            ],
        ),
        EFFECT_SUNSET: Flow(
            count=1,
            action=Action.off,
            transitions=[
                TemperatureTransition(degrees=2700, duration=50, brightness=10),
                TemperatureTransition(degrees=1700, duration=180000, brightness=5),
                RGBTransition(
                    red=0xFF, green=0x4C, blue=0x00, duration=420000, brightness=1
                ),
            ],
        ),
        EFFECT_ROMANCE: Flow(
            count=0,
            action=Action.stay,
            transitions=[
                RGBTransition(
                    red=0x59, green=0x15, blue=0x6D, duration=4000, brightness=1
                ),
                RGBTransition(
                    red=0x66, green=0x14, blue=0x2A, duration=4000, brightness=1
                ),
            ],
        ),
        EFFECT_HAPPY_BIRTHDAY: Flow(
            count=0,
            action=Action.stay,
            transitions=[
                RGBTransition(
                    red=0xDC, green=0x50, blue=0x19, duration=1996, brightness=80
                ),
                RGBTransition(
                    red=0xDC, green=0x78, blue=0x1E, duration=1996, brightness=80
                ),
                RGBTransition(
                    red=0xAA, green=0x32, blue=0x14, duration=1996, brightness=80
                ),
            ],
        ),
        EFFECT_CANDLE_FLICKER: Flow(
            count=0,
            action=Action.recover,
            transitions=[
                TemperatureTransition(degrees=2700, duration=800, brightness=50),
                TemperatureTransition(degrees=2700, duration=800, brightness=30),
                TemperatureTransition(degrees=2700, duration=1200, brightness=80),
                TemperatureTransition(degrees=2700, duration=800, brightness=60),
                TemperatureTransition(degrees=2700, duration=1200, brightness=90),
                TemperatureTransition(degrees=2700, duration=2400, brightness=50),
                TemperatureTransition(degrees=2700, duration=1200, brightness=80),
                TemperatureTransition(degrees=2700, duration=800, brightness=60),
                TemperatureTransition(degrees=2700, duration=400, brightness=70),
            ],
        ),
    }

    for name, target in effects.items():
        await _async_test_effect(name, target)
    await _async_test_effect("not_existed", called=False)
示例#25
0
文件: test_light.py 项目: 1e1/core-1
async def test_effects(hass: HomeAssistant):
    """Test effects."""
    yaml_configuration = {
        DOMAIN: {
            CONF_DEVICES:
            YAML_CONFIGURATION[DOMAIN][CONF_DEVICES],
            CONF_CUSTOM_EFFECTS: [
                {
                    CONF_NAME: "mock_effect",
                    CONF_FLOW_PARAMS: {
                        ATTR_COUNT:
                        3,
                        ATTR_TRANSITIONS: [
                            {
                                YEELIGHT_HSV_TRANSACTION: [300, 50, 500, 50]
                            },
                            {
                                YEELIGHT_RGB_TRANSITION:
                                [100, 100, 100, 300, 30]
                            },
                            {
                                YEELIGHT_TEMPERATURE_TRANSACTION:
                                [3000, 200, 20]
                            },
                            {
                                YEELIGHT_SLEEP_TRANSACTION: [800]
                            },
                        ],
                    },
                },
            ],
        }
    }

    mocked_bulb = _mocked_bulb()
    with patch(f"{MODULE}.Bulb", return_value=mocked_bulb):
        assert await async_setup_component(hass, DOMAIN, yaml_configuration)
        await hass.async_block_till_done()

    assert hass.states.get(ENTITY_LIGHT).attributes.get(
        "effect_list") == YEELIGHT_COLOR_EFFECT_LIST + ["mock_effect"]

    async def _async_test_effect(name, target=None, called=True):
        mocked_start_flow = MagicMock()
        type(mocked_bulb).start_flow = mocked_start_flow
        await hass.services.async_call(
            "light",
            SERVICE_TURN_ON,
            {
                ATTR_ENTITY_ID: ENTITY_LIGHT,
                ATTR_EFFECT: name
            },
            blocking=True,
        )
        if not called:
            return
        mocked_start_flow.assert_called_once()
        if target is None:
            return
        args, _ = mocked_start_flow.call_args
        flow = args[0]
        assert flow.count == target.count
        assert flow.action == target.action
        assert str(flow.transitions) == str(target.transitions)

    effects = {
        "mock_effect":
        Flow(
            count=3,
            transitions=[
                HSVTransition(300, 50, 500, 50),
                RGBTransition(100, 100, 100, 300, 30),
                TemperatureTransition(3000, 200, 20),
                SleepTransition(800),
            ],
        ),
        EFFECT_DISCO:
        Flow(transitions=transitions.disco()),
        EFFECT_FAST_RANDOM_LOOP:
        None,
        EFFECT_WHATSAPP:
        Flow(count=2, transitions=transitions.pulse(37, 211, 102)),
        EFFECT_FACEBOOK:
        Flow(count=2, transitions=transitions.pulse(59, 89, 152)),
        EFFECT_TWITTER:
        Flow(count=2, transitions=transitions.pulse(0, 172, 237)),
    }

    for name, target in effects.items():
        await _async_test_effect(name, target)
    await _async_test_effect("not_existed", called=False)
示例#26
0
async def test_effects(hass: HomeAssistant):
    """Test effects."""
    assert await async_setup_component(
        hass,
        DOMAIN,
        {
            DOMAIN: {
                CONF_CUSTOM_EFFECTS: [
                    {
                        CONF_NAME: "mock_effect",
                        CONF_FLOW_PARAMS: {
                            ATTR_COUNT:
                            3,
                            ATTR_TRANSITIONS: [
                                {
                                    YEELIGHT_HSV_TRANSACTION:
                                    [300, 50, 500, 50]
                                },
                                {
                                    YEELIGHT_RGB_TRANSITION:
                                    [100, 100, 100, 300, 30]
                                },
                                {
                                    YEELIGHT_TEMPERATURE_TRANSACTION:
                                    [3000, 200, 20]
                                },
                                {
                                    YEELIGHT_SLEEP_TRANSACTION: [800]
                                },
                            ],
                        },
                    },
                ],
            },
        },
    )

    config_entry = MockConfigEntry(
        domain=DOMAIN,
        data={
            CONF_ID: "",
            CONF_HOST: IP_ADDRESS,
            CONF_TRANSITION: DEFAULT_TRANSITION,
            CONF_MODE_MUSIC: DEFAULT_MODE_MUSIC,
            CONF_SAVE_ON_CHANGE: DEFAULT_SAVE_ON_CHANGE,
            CONF_NIGHTLIGHT_SWITCH: DEFAULT_NIGHTLIGHT_SWITCH,
        },
    )
    config_entry.add_to_hass(hass)

    mocked_bulb = _mocked_bulb()
    with _patch_discovery(MODULE), patch(f"{MODULE}.Bulb",
                                         return_value=mocked_bulb):
        assert await hass.config_entries.async_setup(config_entry.entry_id)
        await hass.async_block_till_done()

    assert hass.states.get(ENTITY_LIGHT).attributes.get(
        "effect_list") == YEELIGHT_COLOR_EFFECT_LIST + ["mock_effect"]

    async def _async_test_effect(name, target=None, called=True):
        mocked_start_flow = MagicMock()
        type(mocked_bulb).start_flow = mocked_start_flow
        await hass.services.async_call(
            "light",
            SERVICE_TURN_ON,
            {
                ATTR_ENTITY_ID: ENTITY_LIGHT,
                ATTR_EFFECT: name
            },
            blocking=True,
        )
        if not called:
            return
        mocked_start_flow.assert_called_once()
        if target is None:
            return
        args, _ = mocked_start_flow.call_args
        flow = args[0]
        assert flow.count == target.count
        assert flow.action == target.action
        assert str(flow.transitions) == str(target.transitions)

    effects = {
        "mock_effect":
        Flow(
            count=3,
            transitions=[
                HSVTransition(300, 50, 500, 50),
                RGBTransition(100, 100, 100, 300, 30),
                TemperatureTransition(3000, 200, 20),
                SleepTransition(800),
            ],
        ),
        EFFECT_DISCO:
        Flow(transitions=transitions.disco()),
        EFFECT_FAST_RANDOM_LOOP:
        None,
        EFFECT_WHATSAPP:
        Flow(count=2, transitions=transitions.pulse(37, 211, 102)),
        EFFECT_FACEBOOK:
        Flow(count=2, transitions=transitions.pulse(59, 89, 152)),
        EFFECT_TWITTER:
        Flow(count=2, transitions=transitions.pulse(0, 172, 237)),
    }

    for name, target in effects.items():
        await _async_test_effect(name, target)
    await _async_test_effect("not_existed", called=False)