Пример #1
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})
Пример #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 DeviceMessages.SetPower(level=65535, target=pkt.serial)
                    else:
                        yield DeviceMessages.SetPower(level=0, target=pkt.serial)
Пример #3
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)
Пример #4
0
class PowerPlan(Plan):
    """
    Return in a dictionary:

    * level: The current power level on the device
    * on: ``False`` if the level is 0, otherwise ``True``
    """

    messages = [DeviceMessages.GetPower()]
    default_refresh = 1

    class Instance(Plan.Instance):
        def process(self, pkt):
            if pkt | DeviceMessages.StatePower:
                self.level = pkt.level
                self.on = pkt.level > 0
                return True

        async def info(self):
            return {"level": self.level, "on": self.on}
Пример #5
0
        async def gen(reference, sender, **kwargs):
            async def inner_gen(level, reference, sender2, **kwargs2):
                assert sender is sender2
                del kwargs2["error_catcher"]
                kwargs1 = dict(kwargs)
                del kwargs1["error_catcher"]
                assert kwargs1 == kwargs2
                assert reference in devices.serials
                yield DeviceMessages.SetPower(level=level)

            get_power = DeviceMessages.GetPower()
            async for pkt in sender(get_power, reference, **kwargs):
                if pkt.serial == light1.serial:
                    level = 1
                elif pkt.serial == light2.serial:
                    level = 2
                elif pkt.serial == light3.serial:
                    level = 3
                else:
                    assert False, f"Unknown serial: {pkt.serial}"

                yield FromGenerator(partial(inner_gen, level), reference_override=pkt.serial)
Пример #6
0
 async def gen(serial, sender, **kwargs):
     yield Pipeline([DeviceMessages.GetPower(), DeviceMessages.SetLabel(label="wat")])
Пример #7
0
        for device, msgs in expected.items():
            assert device in devices
            devices.store(device).assertIncoming(*msgs, ignore=[DiscoveryMessages.GetService])
            devices.store(device).clear()

    async it "is able to do a FromGenerator per serial", sender:

        async def gen(serial, sender, **kwargs):
            assert serial in (light1.serial, light2.serial)
            yield Pipeline([DeviceMessages.GetPower(), DeviceMessages.SetLabel(label="wat")])

        msg = FromGeneratorPerSerial(gen)

        expected = {
            light1: [DeviceMessages.GetPower(), DeviceMessages.SetLabel(label="wat")],
            light2: [DeviceMessages.GetPower(), DeviceMessages.SetLabel(label="wat")],
            light3: [],
        }

        errors = []

        got = defaultdict(list)
        try:
            async with light3.offline():
                async for pkt in sender(msg, devices.serials, error_catcher=errors):
                    got[pkt.serial].append(pkt)
        finally:
            assert errors == [FailedToFindDevice(serial=light3.serial)]

        assert len(devices) > 0
Пример #8
0
                "line2",
                "explosion = True",
                "help_us = please",
            )

    describe "lines_from_a_packet":

        def assertLines(self, pkt, *lines):
            assertLines(ConsoleFormat.lines_from_packet, pkt, *lines)

        it "can format acknowledgements":
            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,
Пример #9
0
    def assertResponse(self, device, **attrs):
        return makeAssertResponse(device, **attrs)

    async it "responds to label messages", device, assertResponse:
        await assertResponse(DeviceMessages.GetLabel(), [DeviceMessages.StateLabel(label="")])
        await assertResponse(
            DeviceMessages.SetLabel(label="sam"),
            [DeviceMessages.StateLabel(label="sam")],
            label="sam",
        )
        await assertResponse(
            DeviceMessages.GetLabel(), [DeviceMessages.StateLabel(label="sam")], label="sam"
        )

    async it "responds to power messages", device, assertResponse:
        await assertResponse(DeviceMessages.GetPower(), [DeviceMessages.StatePower(level=0)])
        await assertResponse(
            DeviceMessages.SetPower(level=200), [DeviceMessages.StatePower(level=0)], power=200
        )
        await assertResponse(
            DeviceMessages.GetPower(), [DeviceMessages.StatePower(level=200)], power=200
        )


describe "SwitchDevice":

    @pytest.fixture()
    def device(self):
        device = devices["switch"]
        devices.store(device).assertAttrs(label="")
        return device
Пример #10
0
 async def gen(serial, sender, **kwargs):
     assert serial in (light1.serial, light2.serial)
     yield Pipeline([DeviceMessages.GetPower(), DeviceMessages.SetLabel(label="wat")])
Пример #11
0
 async def gen(reference, sender, **kwargs):
     assert await (yield DeviceMessages.GetPower(target=light1.serial))
     assert not await (yield DeviceMessages.GetPower(target=light2.serial))
     assert await (yield DeviceMessages.GetPower(target=light3.serial))
Пример #12
0
 async def gen(reference, sender, **kwargs):
     t = yield DeviceMessages.GetPower()
     assert not (await t)
Пример #13
0
            yield device

    @pytest.fixture()
    async def sender(self, final_future, device):
        configuration = {"final_future": final_future, "protocol_register": protocol_register}
        async with MemoryTarget.create(configuration, {"devices": [device]}).session() as sender:
            yield sender

    async it "can send and receive messages using memory target", sender, device:
        pkts = await sender(DeviceMessages.SetPower(level=65535), device.serial)
        assert len(pkts) == 1
        pkt = pkts[0]
        assert pkt | DeviceMessages.StatePower
        assert pkt.level == 0

        pkts = await sender(DeviceMessages.GetPower(), device.serial)
        assert len(pkts) == 1
        pkt = pkts[0]
        assert pkt | DeviceMessages.StatePower
        assert pkt.level == 65535

        pkts = await sender(DeviceMessages.SetPower(level=0, res_required=False), device.serial)
        assert len(pkts) == 0

        pkts = await sender(DeviceMessages.GetPower(), device.serial)
        assert len(pkts) == 1
        pkt = pkts[0]
        assert pkt | DeviceMessages.StatePower
        assert pkt.level == 0

    async it "times out if the device is offline", sender, device, FakeTime, MockedCallLater:
Пример #14
0
def incoming_event(device, io):
    return Events.INCOMING(
        device, io, pkt=DeviceMessages.GetPower(source=20, sequence=34, target=device.serial)
    )
Пример #15
0
def item():
    return Item([DeviceMessages.GetPower(), DeviceMessages.GetLabel()])
Пример #16
0
        async it "responds to label messages", device:
            await device.assertResponse(
                DeviceMessages.GetLabel(), [DeviceMessages.StateLabel(label="")]
            )
            await device.assertResponse(
                DeviceMessages.SetLabel(label="sam"),
                [DeviceMessages.StateLabel(label="sam")],
                label="sam",
            )
            await device.assertResponse(
                DeviceMessages.GetLabel(), [DeviceMessages.StateLabel(label="sam")], label="sam"
            )

        async it "responds to power messages", device:
            await device.assertResponse(
                DeviceMessages.GetPower(), [DeviceMessages.StatePower(level=0)]
            )
            await device.assertResponse(
                DeviceMessages.SetPower(level=200), [DeviceMessages.StatePower(level=0)], power=200
            )
            await device.assertResponse(
                DeviceMessages.GetPower(), [DeviceMessages.StatePower(level=200)], power=200
            )

        async it "responds to light power messages", device:
            await device.assertResponse(
                DeviceMessages.GetPower(), [DeviceMessages.StatePower(level=0)]
            )
            await device.assertResponse(
                LightMessages.SetLightPower(level=200),
                [LightMessages.StateLightPower(level=0)],
Пример #17
0
 async def gen(reference, sender, **kwargs):
     raise error
     yield DeviceMessages.GetPower()
Пример #18
0
    @pytest.fixture()
    def assertResponse(self, device, **attrs):
        return makeAssertResponse(device, **attrs)

    @pytest.fixture()
    def assertState(self, device, **attrs):
        return makeAssertState(device, **attrs)

    @pytest.fixture()
    def assertEvent(self, device, **attrs):
        return makeAssertEvent(device, **attrs)

    async it "can change the power of all the relays", device, assertResponse, assertEvent:
        await assertResponse(
            DeviceMessages.GetPower(),
            [DeviceMessages.StatePower(level=0)],
        )

        await assertResponse(
            DeviceMessages.SetPower(level=65535),
            [DeviceMessages.StatePower(level=0)],
            relays=[
                Relay.create(power=65535),
                Relay.create(power=65535),
                Relay.create(power=65535),
                Relay.create(power=65535),
            ],
            power=65535,
        )
Пример #19
0
                io_source = "TEST"

                async def _send_reply(s, send, give_reply, addr, *, replying_to):
                    got.append(("sent", send, give_reply, addr, replying_to))

            addr = mock.Mock(name="addr")
            give_reply = mock.Mock(name="give_reply")

            given1 = mock.Mock(name="given1")
            given2 = mock.Mock(name="given2")
            filtered1 = mock.Mock(name="filtered1")
            filtered2 = mock.Mock(name="filtered2")
            filtered3 = mock.Mock(name="filtered3")

            async with wrap_io(MyIO(device)) as io:
                pkt = DeviceMessages.GetPower()
                event = Events.INCOMING(device, io, pkt=pkt, addr=addr)

                class Instruction:
                    def __init__(s):
                        s.event = event

                    async def process(s):
                        got.append(("process", given1))
                        yield given1
                        got.append(("process", given2))
                        yield given2

                instruction = Instruction()

                async def outgoing(r, e):
Пример #20
0
    async def run_and_compare(self, runner, msg, *, expected):
        await runner.sender(msg, runner.serials)

        assert len(runner.devices) > 0

        for device in runner.devices:
            if device not in expected:
                assert False, f"No expectation for {device.serial}"

            device.compare_received(expected[device])

    async it "toggles the power", runner:
        expected = {
            light1: [
                DeviceMessages.GetPower(),
                LightMessages.SetLightPower(level=65535, duration=1),
            ],
            light2: [DeviceMessages.GetPower(), LightMessages.SetLightPower(level=0, duration=1)],
            light3: [DeviceMessages.GetPower(), LightMessages.SetLightPower(level=0, duration=1)],
        }
        await self.run_and_compare(runner, PowerToggle(), expected=expected)

        for device in runner.devices:
            device.received = []

        expected = {
            light1: [DeviceMessages.GetPower(), LightMessages.SetLightPower(level=0, duration=2)],
            light2: [
                DeviceMessages.GetPower(),
                LightMessages.SetLightPower(level=65535, duration=2),
Пример #21
0
 async def gen(reference, sender, **kwargs):
     yield FailedToFindDevice(serial=light1.serial)
     yield DeviceMessages.GetPower(target=light2.serial)
     yield DeviceMessages.GetPower(target=light3.serial)
Пример #22
0
    async def gather(self, sender, reference, *by_label, **kwargs):
        plan_args = []
        plan_kwargs = {}
        for thing in by_label:
            if isinstance(thing, str):
                plan_args.append(thing)
            else:
                plan_kwargs.update(thing)
        plans = sender.make_plans(*plan_args, **plan_kwargs)
        return dict(await sender.gatherer.gather_all(plans, reference, **kwargs))

    describe "PacketPlan":

        async it "gets the packet", sender:
            plan = PacketPlan(DeviceMessages.GetPower(), DeviceMessages.StatePower)
            got = await self.gather(sender, two_lights, {"result": plan})
            assert got == {
                light1.serial: (True, {"result": mock.ANY}),
                light2.serial: (True, {"result": mock.ANY}),
            }

            pytest.helpers.print_packet_difference(
                got[light1.serial][1]["result"], DeviceMessages.StatePower(level=0)
            )
            pytest.helpers.print_packet_difference(
                got[light2.serial][1]["result"], DeviceMessages.StatePower(level=65535)
            )

        async it "fails if we can't get the correct response", sender:
            plan = PacketPlan(DeviceMessages.GetPower(), DeviceMessages.StateLabel)
Пример #23
0
    describe "retry_gaps":
        async it "returns the retry gaps", V:
            kwargs = {"host": "192.168.0.3", "port": 56700}
            transport = await V.session.make_transport("d073d5", Services.UDP, kwargs)
            assert isinstance(transport, UDP)

            packet = mock.NonCallableMock(name="packet", spec=[])

            uro1 = V.session.retry_gaps(packet, transport)
            assert uro1 is V.transport_target.gaps

    describe "determine_needed_transport":
        async it "says udp", V:
            services = mock.NonCallableMock(name="services", spec=[])
            packets = [DeviceMessages.GetPower(), DeviceMessages.StateLabel()]

            for packet in packets:
                got = await V.session.determine_needed_transport(packet, services)
                assert got == [Services.UDP]

    describe "choose_transport":
        async it "complains if we can't determined need transport", V:
            determine_needed_transport = pytest.helpers.AsyncMock(name="determine_needed_transport")
            determine_needed_transport.return_value = []

            packet = mock.Mock(name="packet", protocol=9001, pkt_type=89)
            services = mock.Mock(name="services")

            msg = "Unable to determine what service to send packet to"
            kwargs = {"protocol": 9001, "pkt_type": 89}
Пример #24
0
        info = PlanInfo(V.plan, V.plankey, V.instance, None)
        assert info.completed is None
        assert not info.done

    it "can be marked done", V:
        info = PlanInfo(V.plan, V.plankey, V.instance, None)
        assert not info.done

        info.mark_done()
        assert info.done

    describe "messages":
        it "memoizes the messages and cares about instance messages before plan messages":
            called = []

            get_power = DeviceMessages.GetPower()
            get_label = DeviceMessages.GetLabel()

            class P(Plan):
                @property
                def messages(s):
                    called.append("shouldn't be called")
                    return [get_label]

                class Instance(Plan.Instance):
                    @property
                    def messages(s):
                        called.append(1)
                        return [get_power]

            plan = P()