Beispiel #1
0
 async def run(*args, **kwargs):
     s1 = DiscoveryMessages.StateService(
         service=Services.UDP, port=56, target="d073d5000001"
     )
     s1.Information.update(
         remote_addr=("192.168.0.3", 56700),
         sender_message=DiscoveryMessages.GetService(),
     )
     yield s1
Beispiel #2
0
    async def _do_search(self, serials, timeout, **kwargs):
        found_now = set()
        discovery_options = self.transport_target.discovery_options

        if discovery_options.has_hardcoded_discovery:
            log.info("Using hard coded discovery information")
            return await discovery_options.discover(self.add_service)

        get_service = DiscoveryMessages.GetService(
            target=None, tagged=True, addressable=True, res_required=True, ack_required=False
        )

        kwargs["no_retry"] = True
        kwargs["broadcast"] = kwargs.get("broadcast", True) or True
        kwargs["accept_found"] = True
        kwargs["error_catcher"] = []

        async for time_left, time_till_next in self._search_retry_iterator(timeout):
            kwargs["message_timeout"] = time_till_next

            async for pkt in self(get_service, **kwargs):
                if discovery_options.want(pkt.serial):
                    addr = pkt.Information.remote_addr
                    found_now.add(pkt.target[:6])
                    await self.add_service(pkt.serial, pkt.service, host=addr[0], port=pkt.port)

            if serials is None:
                if found_now:
                    break
            elif all(binascii.unhexlify(serial)[:6] in found_now for serial in serials):
                break

        return list(found_now)
Beispiel #3
0
 async def respond(s, event):
     if event | DeviceMessages.GetPower:
         event.set_replies(DeviceMessages.StatePower(level=s.device_attrs.power))
     if event | DeviceMessages.GetLabel:
         event.ignore_request()
     elif event | DeviceMessages.SetPower:
         event.set_replies(DeviceMessages.StatePower(level=s.device_attrs.power))
         await s.device_attrs.attrs_apply(
             s.device_attrs.attrs_path("power").changer_to(event.pkt.level),
             event=None,
         )
     elif event | DiscoveryMessages.GetService:
         event.set_replies(
             DiscoveryMessages.StateService(service=Services.UDP, port=56700),
             DiscoveryMessages.StateService(service=Services.UDP, port=76500),
         )
Beispiel #4
0
 async def respond(self, event):
     if event | DiscoveryMessages.GetService and event.io is self:
         port = self.options.get("state_service_port", self.options.port)
         state_service_port = 0 if port is None else port
         event.add_replies(
             DiscoveryMessages.StateService(
                 service=self.options.state_service,
                 port=state_service_port))
Beispiel #5
0
            async def run(*args, **kwargs):
                called.append("run")

                if len(called) > 0:
                    s1 = DiscoveryMessages.StateService(
                        service=Services.UDP, port=56, target="d073d5000001"
                    )
                    s1.Information.update(
                        remote_addr=("192.168.0.3", 56700),
                        sender_message=DiscoveryMessages.GetService(),
                    )
                    yield s1

                if len(called) > 1:
                    s2 = DiscoveryMessages.StateService(
                        service=Services.UDP, port=58, target="d073d5000002"
                    )
                    s2.Information.update(
                        remote_addr=("192.168.0.4", 56700),
                        sender_message=DiscoveryMessages.GetService(),
                    )
                    yield s2

                if len(called) > 2:
                    s3 = DiscoveryMessages.StateService(
                        service=Services.UDP, port=59, target="d073d5000003"
                    )
                    s3.Information.update(
                        remote_addr=("192.168.0.5", 56700),
                        sender_message=DiscoveryMessages.GetService(),
                    )
                    yield s3
Beispiel #6
0
    async def ensure_udp_service(self):
        await self.stop_service(Services.UDP)

        class ServerProtocol(asyncio.Protocol):
            def connection_made(sp, transport):
                sp.udp_transport = transport

            def datagram_received(sp, data, addr):
                if not self.attrs.online:
                    return

                async def received_data(bts, a):
                    sp.udp_transport.sendto(bts, addr)

                self.sync_write("udp", received_data, data)

            def error_received(sp, exc):
                log.error(hp.lc("Error on udp transport", error=exc))

        remote = None

        for i in range(3):
            port = self.port
            if port is None:
                port = self.make_port()

            try:
                remote, _ = await asyncio.get_event_loop(
                ).create_datagram_endpoint(ServerProtocol,
                                           local_addr=("0.0.0.0", port))
                break
            except OSError:
                log.exception("Couldn't make datagram server")
                await asyncio.sleep(0.1)

        if remote is None:
            raise Exception("Failed to bind to a udp socket for fake device")

        async def closer():
            remote.close()

        async def add_service(adder):
            await adder(self.serial, Services.UDP, host="127.0.0.1", port=port)

        def address(source):
            if source == "udp":
                return ("127.0.0.1", port)

        state_service = DiscoveryMessages.StateService(service=Services.UDP,
                                                       port=port)
        self.services.append(
            Service(Services.UDP, closer, add_service, state_service, address))
Beispiel #7
0
        async def doit():
            async with target.session() as afr:
                async with target.with_devices(device1):
                    script = target.script(DiscoveryMessages.GetService())

                    got = []
                    async for pkt, _, _ in script.run_with(device1.serial, afr):
                        got.append((pkt.service.value, pkt.port))

                    self.assertEqual(sorted(got)
                        , [ (Services.UDP.value, device1.port)
                          ]
                        )
Beispiel #8
0
    async def find_devices(self,
                           broadcast,
                           ignore_lost=False,
                           raise_on_none=False,
                           timeout=60,
                           **kwargs):
        """
        Broadcast a Discovery Packet (GetService) and interpret the return
        StateService messages.
        """
        discovery = DiscoveryMessages.GetService(ack_required=False,
                                                 res_required=True,
                                                 target=None,
                                                 addressable=True,
                                                 tagged=True)

        script = self.transport_target.script(discovery)
        found_now = []
        try:
            kwargs["broadcast"] = broadcast
            kwargs["accept_found"] = True
            kwargs["timeout"] = timeout
            async for pkt, addr, broadcast in script.run_with([], self,
                                                              **kwargs):
                target = pkt.target[:6]
                found_now.append(target)
                if target not in self.found:
                    self.found[target] = (set(), broadcast)

                if pkt.protocol == 1024 and pkt.pkt_type == 3:
                    service = pkt.payload.service
                    self.found[target][0].add((service, addr))
        except TimedOut as error:
            if raise_on_none:
                raise FoundNoDevices()
            log.error("Didn't find any devices!\terror=%s", error)

        if not ignore_lost:
            for target in list(self.found):
                if target not in found_now:
                    del self.found[target]

        return self.found
Beispiel #9
0
    async def ensure_memory_service(self):
        await self.stop_service(MemoryService)

        async def closer():
            pass

        async def add_service(adder):
            await adder(self.serial,
                        MemoryService,
                        writer=partial(self.write, "memory"))

        def address(source):
            if source == "memory":
                return (f"fake://{self.serial}/memory", 56700)

        state_service = DiscoveryMessages.StateService(service=Services.UDP,
                                                       port=56700)
        self.services.append(
            Service(MemoryService, closer, add_service, state_service,
                    address))
Beispiel #10
0
            kwargs = {
                "a": a,
                "no_retry": True,
                "broadcast": True,
                "accept_found": True,
                "error_catcher": [],
                "message_timeout": 1,
            }
            script.run.assert_called_once_with(None, V.session, **kwargs)

            V.transport_target.script.assert_called_once_with(
                DiscoveryMessages.GetService(
                    target=None,
                    tagged=True,
                    addressable=True,
                    res_required=True,
                    ack_required=False,
                )
            )

            assert sorted(fn) == sorted(
                [binascii.unhexlify(s) for s in ("d073d5000001", "d073d5000002")]
            )

            assert V.session.found.serials == ["d073d5000001", "d073d5000002"]
            assert V.session.found["d073d5000001"] == {
                Services.UDP: await V.session.make_transport(
                    "d073d5000001", Services.UDP, {"host": "192.168.0.3", "port": 56}
                )
            }
Beispiel #11
0
# coding: spec

from photons_messages import Services, DiscoveryMessages, protocol_register

from photons_app.test_helpers import print_packet_difference

import binascii

describe "DiscoveryMessages":
    it "can unpack":
        hexd = "29000014f7f15496d073d51261e200004c49465856320101000000000000000003000000017cdd0000"

        unpackd = DiscoveryMessages.unpack(hexd, protocol_register=protocol_register)

        expected = DiscoveryMessages.StateService.empty_normalise(
            **{
                "frame_address": {
                    "ack_required": False,
                    "res_required": True,
                    "reserved2": "4c4946585632",
                    "reserved3": "00",
                    "sequence": 1,
                    "target": "d073d51261e20000",
                },
                "frame_header": {
                    "addressable": True,
                    "protocol": 1024,
                    "reserved1": "00",
                    "size": 41,
                    "source": 2522149367,
                    "tagged": False,
Beispiel #12
0
 def make_response(self, pkt, protocol):
     if pkt | DiscoveryMessages.GetService:
         msgs = []
         for service, (_, port) in self.services[0]:
             msgs.append(DiscoveryMessages.StateService(service=service, port=port))
         return msgs
Beispiel #13
0
                ),
            )

        v = V()
        async with V.devices.for_test(final_future) as sender:
            v.sender = sender
            yield v

    async it "can get serials and info", V:
        reference = DeviceFinder.empty()
        found, ss = await reference.find(V.sender, timeout=5)
        reference.raise_on_missing(found)
        assert sorted(list(found)) == sorted(binascii.unhexlify(s)[:6] for s in ss)
        assert ss == sorted(V.serials)
        for device in V.devices:
            V.devices.store(device).assertIncoming(DiscoveryMessages.GetService())
            V.devices.store(device).clear()

        reference = DeviceFinder.from_kwargs(label="kitchen")
        found, ss = await reference.find(V.sender, timeout=5)
        reference.raise_on_missing(found)
        assert sorted(list(found)) == sorted(binascii.unhexlify(s)[:6] for s in ss)
        assert ss == []

        for device in V.devices:
            expected = [
                DiscoveryMessages.GetService(),
                DeviceMessages.GetVersion(),
                LightMessages.GetColor(),
            ]
            if device is V.devices["d4"]:
Beispiel #14
0
import asyncio

describe "Fake device":

    async it "works with sockets":
        device = FakeDevice("d073d5000001", [], use_sockets=True)

        options = {"final_future": asyncio.Future(), "protocol_register": protocol_register}
        target = MemoryTarget.create(options, {"devices": device})

        await device.start()
        assert len(device.services) == 1
        device_port = device.services[0].state_service.port

        async with target.session() as sender:
            msg = DiscoveryMessages.GetService()

            got = defaultdict(list)
            async for pkt in sender(msg, device.serial):
                got[pkt.serial].append(pkt.payload.as_dict())

            assert dict(got) == {"d073d5000001": [{"service": Services.UDP, "port": device_port}]}

        lantarget = LanTarget.create(options)
        async with lantarget.session() as sender:
            await sender.add_service(
                device.serial, Services.UDP, host="127.0.0.1", port=device_port
            )

            msg = DeviceMessages.EchoRequest(echoing=b"hi")
Beispiel #15
0
            def datagram_received(sp, data, addr):
                pkt = DiscoveryMessages.unpack(data, protocol_register=protocol_register)
                assert pkt | DiscoveryMessages.GetService

                res = DiscoveryMessages.StateService(target=target, source=pkt.source, sequence=pkt.sequence, service=Services.UDP, port=port)
                self.transport.sendto(res.tobytes(None), addr)
Beispiel #16
0
            def datagram_received(sp, data, addr):
                pkt = DiscoveryMessages.unpack(data, protocol_register=protocol_register)
                assert pkt | DiscoveryMessages.GetService

                res = DiscoveryMessages.StateService(target=target, source=pkt.source, sequence=pkt.sequence, service=Services.UDP, port=port)
                self.transport.sendto(res.tobytes(None), addr)

        remote, _ = await self.loop.create_datagram_endpoint(ServerProtocol, local_addr=("0.0.0.0", port))

        try:
            self.assertEqual(self.bridge.found, {})
            await self.bridge.find_devices(('127.0.0.1', port), timeout=3)

            self.assertEqual(self.bridge.found
                  , { binascii.unhexlify(target)[:6]: (set([(Services.UDP, ("127.0.0.1", port))]), "127.0.0.1")
                  }
                )

            found = []
            script = self.target.script(DiscoveryMessages.GetService(ack_required=False))
            async for pkt, _, _ in script.run_with([target], self.bridge, timeout=3):
                found.append(pkt)

            self.assertEqual(len(found), 1)
            self.assertEqual(pkt.target[:6], binascii.unhexlify(target))
            self.assertEqual(pkt.service, Services.UDP)
            self.assertEqual(pkt.port, port)
        finally:
            remote.close()
Beispiel #17
0
            service1 = mock.Mock(name="service", service=Services.UDP, state_service=state_service1)

            state_service2 = mock.NonCallableMock(name="state_service2", spec=[])
            service2 = mock.Mock(
                name="service", service=AnotherService, state_service=state_service2
            )

            state_service3 = mock.NonCallableMock(name="state_service3", spec=[])
            service3 = mock.Mock(
                name="service", service=MemoryService, state_service=state_service3
            )

            device.services = [service1, service2, service3]

            got = []
            get_service = DiscoveryMessages.GetService()
            async for m in responder.respond(device, get_service, "UDP"):
                got.append(m)

            assert got == [state_service1, state_service2, state_service3]

            got = []
            with ServicesResponder.limited_services(device, Services.UDP, AnotherService):
                async for m in responder.respond(device, get_service, "UDP"):
                    got.append(m)
            assert got == [state_service1, state_service2]

            got = []
            with ServicesResponder.limited_services(device, MemoryService):
                async for m in responder.respond(device, get_service, "UDP"):
                    got.append(m)
Beispiel #18
0
                devices.Events.OUTGOING(
                    device,
                    device.io["MEMORY"],
                    pkt=CoreMessages.Acknowledgement,
                    replying_to=original,
                ),
                *[
                    devices.Events.OUTGOING(
                        device, device.io["MEMORY"], pkt=ex, replying_to=original
                    )
                    for ex in expected
                ],
            ]

        async it "can get unlimited replies", send_single, device, FakeTime, MockedCallLater:
            original = DiscoveryMessages.GetService(ack_required=False)
            with FakeTime() as t:
                async with MockedCallLater(t):
                    result = await send_single(original, timeout=1)

            assert t.time == 0.1

            expected = (
                DiscoveryMessages.StateService,
                {"service": Services.UDP, "port": device.io["MEMORY"].options.port},
            )
            pytest.helpers.assertSamePackets(result, expected)
            assert devices.store(device) == [
                devices.Events.INCOMING(device, device.io["MEMORY"], pkt=original),
                devices.Events.OUTGOING(
                    device, device.io["MEMORY"], pkt=expected, replying_to=original