Exemplo n.º 1
0
        async def assertRemaining(duration, remaining, last_power, result):
            getter = LightMessages.GetHevCycle()
            state = LightMessages.StateHevCycle(
                duration_s=duration, remaining_s=remaining, last_power=last_power
            )
            await assertResponse(getter, [state])

            getter = LightMessages.GetLastHevCycleResult()
            state = LightMessages.StateLastHevCycleResult(result=result)
            await assertResponse(getter, [state])
Exemplo n.º 2
0
 async def gen(reference, sender, **kwargs):
     get_power = DeviceMessages.GetPower()
     async for pkt in sender(get_power, reference, **kwargs):
         if pkt | DeviceMessages.StatePower:
             if pkt.level == 0:
                 yield LightMessages.SetLightPower(level=65535,
                                                   res_required=False,
                                                   duration=duration,
                                                   target=pkt.serial)
             else:
                 yield LightMessages.SetLightPower(level=0,
                                                   res_required=False,
                                                   duration=duration,
                                                   target=pkt.serial)
Exemplo n.º 3
0
class InfoPoints(enum.Enum):
    """
    Enum used to determine what information is required for what keys
    """

    # We need to know what kind of product the device is to get the label correctly
    VERSION = Point(DeviceMessages.GetVersion(), ["label", "product_id", "cap"], None)

    # We get Label from LIGHT_STATE for lights and from STATE_LABEL for non lights
    LIGHT_STATE = Point(
        LightMessages.GetColor(),
        ["label", "power", "hue", "saturation", "brightness", "kelvin"],
        10,
        # Non lights are unimportant enough at this time to risk sending too many messages to them
        condition=lambda device: device.product_type is not DeviceType.NON_LIGHT,
    )
    LABEL = Point(
        DeviceMessages.GetLabel(),
        ["label"],
        10,
        condition=lambda device: device.product_type is DeviceType.NON_LIGHT,
    )

    FIRMWARE = Point(DeviceMessages.GetHostFirmware(), ["firmware_version"], 300)
    GROUP = Point(DeviceMessages.GetGroup(), ["group_id", "group_name"], 60)
    LOCATION = Point(DeviceMessages.GetLocation(), ["location_id", "location_name"], 60)
Exemplo n.º 4
0
async def apply_zone(applier, target, afr, serial, theme, overrides):
    length = None
    msg = MultiZoneMessages.GetColorZones(start_index=0, end_index=255)
    async for pkt, _, _ in target.script(msg).run_with(serial, afr):
        if pkt | MultiZoneMessages.StateMultiZone:
            length = pkt.zones_count

    if length is None:
        log.warning(
            hp.lc("Couldn't work out how many zones the light had",
                  serial=serial))
        return

    messages = []
    for (start_index, end_index), hsbk in applier(length).apply_theme(theme):
        messages.append(
            MultiZoneMessages.SetColorZones(start_index=start_index,
                                            end_index=end_index,
                                            hue=hsbk.hue,
                                            saturation=hsbk.saturation,
                                            brightness=hsbk.brightness,
                                            kelvin=hsbk.kelvin,
                                            duration=overrides.get(
                                                "duration", 1),
                                            res_required=False,
                                            ack_required=True))

    set_power = LightMessages.SetLightPower(level=65535,
                                            duration=overrides.get(
                                                "duration", 1))
    pipeline = Pipeline(*messages, spread=0.005)
    await target.script([set_power, pipeline]).run_with_all(serial, afr)
Exemplo n.º 5
0
def ChangeCleanCycle(*, enable, duration_s=0, duration=None, **kwargs):
    """
    Returns a valid message that will either start or stop the cleaning (HEV)
    cycle of devices used against it.

    When a cycle is started, if the duration_s=0 or is not provided, the default
    duration will be used.

    For example:

    .. code-block:: python

        await target.send(ChangeCleanCycle(enable=True), ["d073d5000001", "d073d5000001"])

    Options are:

        enable - boolean (required)
            Pass True to start a cleaning cycle or False to stop a cycle in progress

        duration_s - integer (optional)
            Only used if enable=True. Specifies the duration (in seconds) for
            the cleaning cycle. If not specified, the default duration will be
            used. Default duration can be set using target:set_clean_config and
            returned using target_get_clean_config
    """
    if duration is not None:
        raise ProgrammerError("Duration needs to be specified as duration_s")

    return ForCapability(hev=LightMessages.SetHevCycle(
        enable=enable,
        duration_s=duration_s,
        ack_required=True,
        res_required=False,
    ))
Exemplo n.º 6
0
def SetCleanConfig(*, indication, duration_s, duration=None, **kwargs):
    """
    Returns a valid message that will set the default clean cycle configuration
    for the device.

    For example:

    .. code-block:: python

        await target.send(SetCleanConfig(indication=True), ["d073d5000001", "d073d5000001"])

    The options are:

    indication - boolean - default False
        whether to run a short flashing indication at the end of the HEV cycle.

    duration_s - seconds - default 7200 seconds
        duration in seconds for a cleaning cycle, if no duration provided.
    """
    if duration is not None:
        raise ProgrammerError("Duration needs to be specified as duration_s")

    return ForCapability(hev=LightMessages.SetHevCycleConfiguration(
        indication=bool(indication),
        duration_s=duration_s,
        ack_required=True,
        res_required=False,
    ))
Exemplo n.º 7
0
            def power_message(self, overrides):
                power = overrides.get("power", self.power)
                duration = overrides.get("duration", self.duration) or 0

                if power is not None:
                    level = 0 if power not in (True, "on") else 65535
                    return LightMessages.SetLightPower(level=level, duration=duration)
Exemplo n.º 8
0
class StatePlan(Plan):
    """
    Return in a dictionary:

    * hue
    * saturation
    * brightness
    * kelvin
    * label
    * power
    """

    messages = [LightMessages.GetColor()]
    default_refresh = 1

    class Instance(Plan.Instance):
        def process(self, pkt):
            if pkt | LightMessages.LightState:
                dct = pkt.payload.as_dict()

                result = {}
                for k in ("hue", "saturation", "brightness", "kelvin", "label", "power"):
                    result[k] = dct[k]
                self.dct = result

                return True

        async def info(self):
            return self.dct
Exemplo n.º 9
0
    async def execute(self):
        fltr = chp.filter_from_matcher(self.matcher, self.refresh)
        details = await self.finder.info_for(filtr=fltr)

        msgs = []
        for serial, info in details.items():
            msgs.append(DeviceMessages.GetPower(target=serial))

            if "multizone" in info["cap"]:
                msgs.append(
                    MultiZoneMessages.GetColorZones(start_index=0, end_index=255, target=serial)
                )
            elif "chain" in info["cap"]:
                msgs.append(
                    TileMessages.Get64(tile_index=0, length=5, x=0, y=0, width=8, target=serial)
                )
            else:
                msgs.append(LightMessages.GetColor(target=serial))

        state = defaultdict(dict)
        afr = await self.finder.args_for_run()
        async for pkt, _, _ in self.target.script(msgs).run_with(
            None, afr, multiple_replies=True, first_wait=0.5
        ):
            if pkt | DeviceMessages.StatePower:
                state[pkt.serial]["power"] = pkt.level != 0
            elif pkt | LightMessages.LightState:
                hsbk = f"kelvin:{pkt.kelvin} saturation:{pkt.saturation} brightness:{pkt.brightness} hue:{pkt.hue}"
                state[pkt.serial]["color"] = hsbk
            elif pkt | MultiZoneMessages.StateMultiZone:
                if "zones" not in state[pkt.serial]:
                    state[pkt.serial]["zones"] = {}
                for i, zi in enumerate(range(pkt.zone_index, pkt.zone_index + 8)):
                    c = pkt.colors[i]
                    state[pkt.serial]["zones"][zi] = [c.hue, c.saturation, c.brightness, c.kelvin]
            elif pkt | TileMessages.State64:
                if "chain" not in state[pkt.serial]:
                    state[pkt.serial]["chain"] = {}
                colors = [[c.hue, c.saturation, c.brightness, c.kelvin] for c in pkt.colors]
                state[pkt.serial]["chain"][pkt.tile_index] = colors

        scene = []
        for serial, info in sorted(state.items()):
            if "zones" in info:
                info["zones"] = [hsbk for _, hsbk in sorted(info["zones"].items())]
            if "chain" in info:
                info["chain"] = [hsbks for _, hsbks in sorted(info["chain"].items())]

            scene.append({"matcher": {"serial": serial}, **info})

        if self.just_return:
            return scene

        args = {
            "uuid": self.uuid,
            "scene": scene,
            "label": self.label,
            "description": self.description,
        }
        return await self.executor.execute(self.path, {"command": "scene_change", "args": args})
Exemplo n.º 10
0
async def doit():
    msg = LightMessages.GetColor()
    async for pkt, _, _ in lan_target.script(msg).run_with(FoundSerials()):
        hsbk = " ".join("{0}={1}".format(key, pkt.payload[key])
                        for key in ("hue", "saturation", "brightness",
                                    "kelvin"))
        print("{0}: {1}".format(pkt.serial, hsbk))
Exemplo n.º 11
0
        async def gen(reference, sender, **kwargs):
            get_color = LightMessages.GetColor(ack_required=False,
                                               res_required=True)

            async for pkt in sender(get_color, reference, **kwargs):
                if pkt | LightMessages.LightState:
                    yield receiver(pkt.serial, pkt.payload)
Exemplo n.º 12
0
    def transition(self, state, keep_brightness=False):
        def receiver(reference, *states):
            if not states:
                return

            current_state = states[0].as_dict()["payload"]
            power_message = None if "power" not in state else self.power_message(
                state)

            msg_dict = dict(state)
            h, s, b, k = Parser.hsbk(state.get("color", None), overrides=state)
            msg_dict.update({
                "hue": h,
                "saturation": s,
                "brightness": b,
                "kelvin": k
            })

            final_overrides = dict(msg_dict)

            pipeline = []

            reset = False

            now_off = current_state["power"] in (None, 0)

            if now_off:
                overrides = dict(msg_dict)
                overrides["brightness"] = 0
                if "duration" in overrides:
                    del overrides["duration"]
                msg = Parser.color_to_msg(None, overrides=overrides)
                msg.target = reference
                msg.ack_required = True
                msg.res_required = False
                reset = True
                pipeline.append(msg)

            if power_message is not None:
                want_off = power_message.level == 0

                if now_off ^ want_off:
                    power_message.target = reference
                    pipeline.append(power_message)

            if keep_brightness or (reset and "brightness" not in state):
                final_overrides["brightness"] = current_state["brightness"]

            msg = Parser.color_to_msg(None, overrides=final_overrides)
            msg.target = reference
            msg.ack_required = True
            msg.res_required = False
            pipeline.append(msg)

            yield Pipeline(*pipeline)

        getter = LightMessages.GetColor(ack_required=False, res_required=True)
        return Decider(getter, receiver, [LightMessages.LightState])
Exemplo n.º 13
0
async def doit(collector):
    lan_target = collector.resolve_target("lan")

    msg = LightMessages.GetColor()
    async for pkt in lan_target.send(msg, FoundSerials()):
        hsbk = " ".join("{0}={1}".format(key, pkt.payload[key])
                        for key in ("hue", "saturation", "brightness",
                                    "kelvin"))
        print("{0}: {1}".format(pkt.serial, hsbk))
Exemplo n.º 14
0
async def apply_light(applier, target, afr, serial, theme, overrides):
    color = applier().apply_theme(theme)
    s = "kelvin:{} hue:{} saturation:{} brightness:{}".format(
        color.kelvin, color.hue, color.saturation, color.brightness)
    set_power = LightMessages.SetLightPower(level=65535,
                                            duration=overrides.get(
                                                "duration", 1))
    await target.script([
        set_power, Parser.color_to_msg(s, overrides=overrides)
    ]).run_with_all(serial, afr)
Exemplo n.º 15
0
    def power_message(self, state):
        power_level = 65535 if state["power"] == "on" else 0

        if state.get("duration") in (sb.NotSpecified, "", 0, None):
            return DeviceMessages.SetPower(level=power_level,
                                           res_required=False)
        else:
            return LightMessages.SetLightPower(level=power_level,
                                               duration=state["duration"],
                                               res_required=False)
Exemplo n.º 16
0
    def make_response(self, pkt, protocol):
        self.received.append(pkt)

        if pkt | LightMessages.GetInfrared:
            return LightMessages.StateInfrared(brightness=self.infrared)

        if pkt | LightMessages.GetColor:
            return LightMessages.LightState(
                  hue = self.hue
                , saturation = self.saturation
                , brightness = self.brightness
                , kelvin = self.kelvin
                , label = self.label
                , power = self.power
                )

        elif pkt | DeviceMessages.GetVersion:
            return DeviceMessages.StateVersion(
                  vendor = self.vendor_id
                , product = self.product_id
                , version = 0
                )

        elif pkt | DeviceMessages.GetHostFirmware:
            return DeviceMessages.StateHostFirmware(
                  version = self.firmware_version
                , build = self.firmware_build_time
                )

        elif pkt | DeviceMessages.GetGroup:
            return DeviceMessages.StateGroup(
                  group = self.group
                , label = self.group_label
                , updated_at = self.group_updated_at
                )

        elif pkt | DeviceMessages.GetLocation:
            return DeviceMessages.StateLocation(
                  location = self.location
                , label = self.location_label
                , updated_at = self.location_updated_at
                )
Exemplo n.º 17
0
        async def gen(reference, sender, **kwargs):
            instance = kls(reference, sender, kwargs, aps, theme, options)

            # Turn on the device
            yield LightMessages.SetLightPower(level=65535, duration=options.duration)

            # Yield messages to turn on the theme for this device
            plans = sender.make_plans("capability")
            async for serial, _, info in sender.gatherer.gather(plans, reference):
                async for m in instance.apply(info["cap"]):
                    yield m
Exemplo n.º 18
0
        async def gen(reference, sender, **kwargs):
            plans = sender.make_plans("capability")
            async for serial, _, info in sender.gatherer.gather(plans, reference):
                print(f"Turning off effects for {serial}")

                yield LightMessages.SetWaveformOptional(res_required=False, target=serial)

                if info["cap"].has_multizone:
                    yield SetZonesEffect("OFF", power_on=False)
                elif info["cap"].has_matrix:
                    yield SetTileEffect("OFF", power_on=False)
Exemplo n.º 19
0
async def apply_tile(applier, target, afr, serial, theme, overrides):
    from photons_tile_paint.orientation import Orientation as O, reorient
    from photons_tile_paint.animation import orientations_from

    chain = []
    orientations = {}
    async for pkt, _, _ in target.script(
            TileMessages.GetDeviceChain()).run_with(serial, afr):
        if pkt | TileMessages.StateDeviceChain:
            for tile in tiles_from(pkt):
                chain.append(tile)
            orientations = orientations_from(pkt)

    if chain is None:
        log.warning(
            hp.lc("Couldn't work out how many tiles the light had",
                  serial=serial))
        return

    coords_and_sizes = [((t.user_x, t.user_y), (t.width, t.height))
                        for t in chain]

    messages = []
    for i, (hsbks, coords_and_size) in enumerate(
            zip(
                applier.from_user_coords(coords_and_sizes).apply_theme(theme),
                coords_and_sizes)):
        colors = [{
            "hue": overrides.get("hue", hsbk.hue),
            "saturation": overrides.get("saturation", hsbk.saturation),
            "brightness": overrides.get("brightness", hsbk.brightness),
            "kelvin": overrides.get("kelvin", hsbk.kelvin)
        } for hsbk in hsbks]

        colors = reorient(colors, orientations.get(i, O.RightSideUp))

        messages.append(
            TileMessages.SetState64(tile_index=i,
                                    length=1,
                                    x=0,
                                    y=0,
                                    width=coords_and_size[1][0],
                                    duration=overrides.get("duration", 1),
                                    colors=colors,
                                    res_required=False,
                                    ack_required=True))

    set_power = LightMessages.SetLightPower(level=65535,
                                            duration=overrides.get(
                                                "duration", 1))
    pipeline = Pipeline(*messages, spread=0.005)
    await target.script([set_power, pipeline]).run_with_all(serial, afr)
Exemplo n.º 20
0
class InfoPoints(enum.Enum):
    """
    Enum used to determine what information is required for what keys
    """
    LIGHT_STATE = Point(
        LightMessages.GetColor(),
        ["label", "power", "hue", "saturation", "brightness", "kelvin"])
    VERSION = Point(DeviceMessages.GetVersion(),
                    ["product_id", "product_identifier", "cap"])
    FIRMWARE = Point(DeviceMessages.GetHostFirmware(), ["firmware_version"])
    GROUP = Point(DeviceMessages.GetGroup(), ["group_id", "group_name"])
    LOCATION = Point(DeviceMessages.GetLocation(),
                     ["location_id", "location_name"])
Exemplo n.º 21
0
        def messages(self):
            if not self.is_light:
                return Skip

            if self.zones is Zones.SINGLE:
                return [LightMessages.GetColor()]

            elif self.zones is Zones.MATRIX:
                return [
                    TileMessages.Get64(
                        x=0, y=0, tile_index=0, length=255, width=self.deps["chain"]["width"]
                    )
                ]

            else:
                return []
Exemplo n.º 22
0
    async def gen(ref, sender, **kwargs):
        r = ref if reference is None else reference

        plans = {"set_zones": SetZonesPlan(colors, **options)}
        async for serial, _, messages in sender.gatherer.gather(
                plans, r, **kwargs):
            if messages is not Skip:
                if power_on:
                    yield LightMessages.SetLightPower(
                        level=65535,
                        target=serial,
                        duration=options.get("duration", 1),
                        ack_required=True,
                        res_required=False,
                    )

                yield messages
Exemplo n.º 23
0
async def doit(collector):
    lan_target = collector.resolve_target("lan")

    getter = [DeviceMessages.GetLabel(), LightMessages.GetColor()]

    info = defaultdict(dict)
    async for pkt in lan_target.send(getter, FoundSerials()):
        if pkt | DeviceMessages.StateLabel:
            info[pkt.serial]["label"] = pkt.label
        elif pkt | LightMessages.LightState:
            hsbk = " ".join("{0}={1}".format(key, pkt[key])
                            for key in ("hue", "saturation", "brightness",
                                        "kelvin"))
            info[pkt.serial]["hsbk"] = hsbk

    for serial, details in info.items():
        print(f"{serial}: {details['label']}: {details['hsbk']}")
Exemplo n.º 24
0
async def doit():
    getter = [DeviceMessages.GetLabel(), LightMessages.GetColor()]

    def found(serial, *states):
        info = {"label": "", "hsbk": ""}
        for s in states:
            if s | DeviceMessages.StateLabel:
                info["label"] = s.label
            elif s | LightMessages.LightState:
                info["hsbk"] = " ".join("{0}={1}".format(key, s.payload[key])
                                        for key in ("hue", "saturation",
                                                    "brightness", "kelvin"))
        print("{0}: {1}: {2}".format(serial, info["label"], info["hsbk"]))
        return []

    msg = Decider(getter, found,
                  [DeviceMessages.StateLabel, LightMessages.LightState])
    await lan_target.script(msg).run_with_all(FoundSerials())
Exemplo n.º 25
0
    async def gen(ref, sender, **kwargs):
        r = ref if reference is None else reference

        ps = sender.make_plans("capability")
        async for serial, _, info in sender.gatherer.gather(ps, r, **kwargs):
            if info["cap"].has_matrix:
                if power_on:
                    yield LightMessages.SetLightPower(
                        level=65535,
                        target=serial,
                        duration=power_on_duration,
                        ack_required=True,
                        res_required=False,
                    )

                msg = set_effect.clone()
                msg.target = serial
                yield msg
Exemplo n.º 26
0
        async def gen(reference, sender, **kwargs):
            serials = []
            canvases = []
            combined_canvas = Canvas()

            plans = sender.make_plans("parts")
            async for serial, _, info in sender.gatherer.gather(plans, reference, **kwargs):
                serials.append(serial)
                for part in info:
                    if part.device.cap.has_chain:
                        combined_canvas.add_parts(part)
                    else:
                        nxt = Canvas()
                        nxt.add_parts(part)
                        canvases.append(nxt)

            if combined_canvas:
                canvases.append(combined_canvas)

            msgs = []

            if options.power_on:
                for serial in serials:
                    msgs.append(
                        LightMessages.SetLightPower(
                            level=65535,
                            duration=options.duration,
                            target=serial,
                            res_required=False,
                        )
                    )

            for canvas in canvases:
                Applier(canvas, options.colors).apply()

                for msg in canvas.msgs(
                    options.override_layer, duration=options.duration, acks=True
                ):
                    msgs.append(msg)

            yield msgs
Exemplo n.º 27
0
    def _msgs(self, colors, acks=False, duration=1, randomize=False):
        if self.device.cap.has_matrix:
            colors = [
                c if c is not None else None
                for c in self.reorient(colors, randomize=randomize)
            ]

            kwargs = {"colors": colors}
            if duration != 0:
                kwargs["duration"] = duration
            if acks:
                kwargs["acks"] = acks

            msg = self._set_64.clone()
            msg.update(kwargs)
            return (msg, )

        elif self.device.cap.has_multizone:
            return MultizoneMessagesMaker(self.device.serial,
                                          self.device.cap,
                                          colors,
                                          duration=duration).msgs

        elif colors:
            if isinstance(colors[0], tuple):
                h, s, b, k = colors[0]
                info = {
                    "hue": h,
                    "saturation": s,
                    "brightness": b,
                    "kelvin": k,
                }
            else:
                info = colors[0].as_dict()

            info["duration"] = duration
            return (LightMessages.SetColor(target=self.device.serial,
                                           res_required=False,
                                           **info), )
Exemplo n.º 28
0
    async def animate(self, reference, final_future, pauser=None):
        if pauser is None:
            pauser = asyncio.Condition()

        def errors(e):
            log.error(e)

        serials = await tile_serials_from_reference(self.target, reference,
                                                    self.afr)
        state = TileStateGetter(self.target,
                                self.afr,
                                serials,
                                self.options.background,
                                coords=self.coords)
        await state.fill(random_orientations=self.random_orientations)

        by_serial = {}
        for serial in serials:
            by_serial[serial] = {
                "state": None,
                "coords": tuple(state.info_by_serial[serial].coords)
            }

        log.info("Starting!")

        await self.target.script(
            LightMessages.SetLightPower(level=65535, duration=1)
        ).run_with_all(serials, self.afr)

        combined_coords = []
        for info in by_serial.values():
            combined_coords.extend(info["coords"])
        combined_info = {"state": None}

        while True:
            start = time.time()

            combined_canvas = None
            if getattr(self.options, "combine_tiles", False):
                combined_state = combined_info["state"] = self.next_state(
                    combined_info["state"], combined_coords)
                combined_canvas = self.make_canvas(combined_state,
                                                   combined_coords)

            msgs = []
            for serial, info in by_serial.items():
                coords = info["coords"]

                canvas = combined_canvas
                if canvas is None:
                    info["state"] = self.next_state(info["state"], coords)
                    canvas = self.make_canvas(info["state"], coords)

                canvas.set_default_color_func(
                    state.info_by_serial[serial].default_color_func)
                orientations = state.info_by_serial[serial].orientations
                for msg in canvas_to_msgs(canvas,
                                          coords,
                                          duration=self.duration,
                                          acks=self.acks,
                                          orientations=orientations):
                    msg.target = serial
                    msgs.append(msg)

            async with pauser:
                if final_future.done():
                    break
                await self.target.script(msgs).run_with_all(
                    None, self.afr, error_catcher=errors)

            if final_future.done():
                break

            diff = time.time() - start
            if diff < self.every:
                await asyncio.sleep(self.every - diff)
Exemplo n.º 29
0
            ack = CoreMessages.Acknowledgement(source=20, sequence=2, target="d073d5001111")
            self.assertLines(ack, f"Ack(source={ack.source},sequence=2,target=d073d5001111)(empty)")

        it "can format simple messages":
            pkt = DeviceMessages.GetPower(source=21, sequence=3, target="d073d5002222")
            self.assertLines(
                pkt,
                f"GetPower(ack=True,res=True,source={pkt.source},sequence=3,target=d073d5002222)(empty)",
            )

        it "can format messages with fields":
            pkt = LightMessages.SetColor(
                res_required=False,
                source=22,
                sequence=4,
                target="d073d5003333",
                hue=200,
                saturation=1,
                brightness=0.5,
                kelvin=9000,
            )
            self.assertLines(
                pkt,
                f"SetColor(ack=True,res=False,source={pkt.source},sequence=4,target=d073d5003333)",
                mock.ANY,
                "  hue: 200.0",
                "  saturation: 1.0",
                "  brightness: 0.5",
                "  kelvin: 9000",
                "  duration: 0.0",
            )
Exemplo n.º 30
0
        async it "can power on devices and set zones effect", sender:
            msg = SetZonesEffect("move")
            got = await sender(msg, devices.serials)
            assert got == []

            for strip in strips:
                assert strip.attrs.zones_effect is MultiZoneEffectType.MOVE

            self.compare_received(
                {
                    light1: [DeviceMessages.GetHostFirmware(), DeviceMessages.GetVersion()],
                    light2: [DeviceMessages.GetHostFirmware(), DeviceMessages.GetVersion()],
                    striplcm1: [
                        DeviceMessages.GetHostFirmware(),
                        DeviceMessages.GetVersion(),
                        LightMessages.SetLightPower(level=65535, duration=1),
                        MultiZoneMessages.SetMultiZoneEffect.create(type=MultiZoneEffectType.MOVE),
                    ],
                    striplcm2noextended: [
                        DeviceMessages.GetHostFirmware(),
                        DeviceMessages.GetVersion(),
                        LightMessages.SetLightPower(level=65535, duration=1),
                        MultiZoneMessages.SetMultiZoneEffect.create(type=MultiZoneEffectType.MOVE),
                    ],
                    striplcm2extended: [
                        DeviceMessages.GetHostFirmware(),
                        DeviceMessages.GetVersion(),
                        LightMessages.SetLightPower(level=65535, duration=1),
                        MultiZoneMessages.SetMultiZoneEffect.create(type=MultiZoneEffectType.MOVE),
                    ],
                }