Esempio n. 1
0
class DiscoveryService(Listener):
    """Discovery event handler for gree devices."""

    def __init__(self, hass) -> None:
        """Initialize discovery service."""
        super().__init__()
        self.hass = hass

        self.discovery = Discovery(DISCOVERY_TIMEOUT)
        self.discovery.add_listener(self)

        hass.data[DOMAIN].setdefault(COORDINATORS, [])

    async def device_found(self, device_info: DeviceInfo) -> None:
        """Handle new device found on the network."""

        device = Device(device_info)
        try:
            await device.bind()
        except DeviceNotBoundError:
            _LOGGER.error("Unable to bind to gree device: %s", device_info)
        except DeviceTimeoutError:
            _LOGGER.error("Timeout trying to bind to gree device: %s", device_info)

        _LOGGER.info(
            "Adding Gree device %s at %s:%i",
            device.device_info.name,
            device.device_info.ip,
            device.device_info.port,
        )
        coordo = DeviceDataUpdateCoordinator(self.hass, device)
        self.hass.data[DOMAIN][COORDINATORS].append(coordo)
        await coordo.async_refresh()

        async_dispatcher_send(self.hass, DISPATCH_DEVICE_DISCOVERED, coordo)
Esempio n. 2
0
    def __init__(self, hass) -> None:
        """Initialize discovery service."""
        super().__init__()
        self.hass = hass

        self.discovery = Discovery(DISCOVERY_TIMEOUT)
        self.discovery.add_listener(self)

        hass.data[DOMAIN].setdefault(COORDINATORS, [])
Esempio n. 3
0
async def run_discovery(bind=False):
    """Run the device discovery process."""
    _LOGGER.debug("Scanning network for Gree devices")

    discovery = Discovery()
    listener = DiscoveryListener(bind)
    discovery.add_listener(listener)

    await discovery.scan(wait_for=10)

    _LOGGER.info("Done discovering devices")
Esempio n. 4
0
async def test_add_new_listener():
    """Register a listener, test that is registered."""

    listener = MagicMock(spec_set=Listener)
    discovery = Discovery()

    result = discovery.add_listener(listener)
    assert result is not None

    result = discovery.add_listener(listener)
    assert result is None
Esempio n. 5
0
async def test_remove_listener():
    """Register, remove listener, test results."""

    listener = MagicMock(spec_set=Listener)
    discovery = Discovery()

    result = discovery.add_listener(listener)
    assert result is not None

    result = discovery.remove_listener(listener)
    assert result is True

    result = discovery.remove_listener(listener)
    assert result is False
Esempio n. 6
0
async def test_add_new_listener_with_devices():
    """Register a listener, test that is registered."""

    with patch.object(Discovery, "devices", new_callable=PropertyMock) as mock:
        mock.return_value = [get_mock_device_info()]
        listener = MagicMock(spec_set=Listener)
        discovery = Discovery()

        result = discovery.add_listener(listener)
        await asyncio.gather(*discovery.tasks)

        assert result is not None
        assert len(result) == 1
        assert listener.device_found.call_count == 1
Esempio n. 7
0
async def _async_has_devices(hass: HomeAssistant) -> bool:
    """Return if there are devices that can be discovered."""
    gree_discovery = Discovery(DISCOVERY_TIMEOUT)
    bcast_addr = list(await async_get_ipv4_broadcast_addresses(hass))
    devices = await gree_discovery.scan(wait_for=DISCOVERY_TIMEOUT,
                                        bcast_ifaces=bcast_addr)
    return len(devices) > 0
Esempio n. 8
0
async def test_discover_devices_bad_data(netifaces, addr, bcast, family):
    """Create a socket broadcast responder, an async broadcast listener,
    test discovery responses.
    """
    netifaces.return_value = {
        2: [{
            "addr": addr[0],
            "netmask": "255.0.0.0",
            "peer": bcast
        }]
    }

    with Responder(family, addr[1]) as sock:

        def responder(s):
            (d, addr) = s.recvfrom(2048)
            p = json.loads(d)
            assert p == DISCOVERY_REQUEST

            s.sendto("garbage data".encode(), addr)

        serv = Thread(target=responder, args=(sock, ))
        serv.start()

        # Run the listener portion now
        discovery = Discovery(allow_loopback=True)
        response = await discovery.scan(wait_for=DEFAULT_TIMEOUT)

        assert response is not None
        assert len(response) == 0

        sock.close()
        serv.join(timeout=DEFAULT_TIMEOUT)
Esempio n. 9
0
async def test_discovery_events(netifaces, addr, bcast, family):
    netifaces.return_value = {
        2: [{
            "addr": addr[0],
            "netmask": "255.0.0.0",
            "peer": bcast
        }]
    }

    with Responder(family, addr[1]) as sock:

        def responder(s):
            (d, addr) = s.recvfrom(2048)
            p = json.loads(d)
            assert p == DISCOVERY_REQUEST

            p = json.dumps(encrypt_payload(DISCOVERY_RESPONSE))
            s.sendto(p.encode(), addr)

        serv = Thread(target=responder, args=(sock, ))
        serv.start()

        with patch.object(Discovery, "packet_received",
                          return_value=None) as mock:
            discovery = Discovery(allow_loopback=True)
            await discovery.scan()
            await asyncio.sleep(DEFAULT_TIMEOUT)

            assert mock.call_count == 1

        sock.close()
        serv.join(timeout=DEFAULT_TIMEOUT)
Esempio n. 10
0
async def test_discover_deduplicate_multiple_discoveries(
        netifaces, addr, bcast, family):
    netifaces.return_value = {
        2: [{
            "addr": addr[0],
            "netmask": "255.0.0.0",
            "peer": bcast
        }]
    }

    devices = [
        {
            "cid": "aabbcc001122",
            "mac": "aabbcc001122",
            "name": "MockDevice1"
        },
        {
            "cid": "aabbcc001123",
            "mac": "aabbcc001123",
            "name": "MockDevice2"
        },
        {
            "cid": "aabbcc001123",
            "mac": "aabbcc001123",
            "name": "MockDevice2"
        },
    ]

    with Responder(family, addr[1]) as sock:

        def responder(s):
            (d, addr) = s.recvfrom(2048)
            p = json.loads(d)
            assert p == DISCOVERY_REQUEST

            for d in devices:
                r = DISCOVERY_RESPONSE.copy()
                r["pack"].update(d)
                p = json.dumps(encrypt_payload(r))
                s.sendto(p.encode(), addr)

        serv = Thread(target=responder, args=(sock, ))
        serv.start()

        discovery = Discovery(allow_loopback=True)
        devices = await discovery.scan(wait_for=DEFAULT_TIMEOUT)
        assert devices is not None
        assert len(devices) == 2

        sock.close()
        serv.join(timeout=DEFAULT_TIMEOUT)
Esempio n. 11
0
async def test_discover_no_devices(netifaces):
    netifaces.return_value = {
        2: [{
            "addr": "127.0.0.1",
            "netmask": "255.0.0.0",
            "peer": "127.255.255.255"
        }]
    }

    discovery = Discovery(allow_loopback=True)
    devices = await discovery.scan(wait_for=DEFAULT_TIMEOUT)

    assert devices is not None
    assert len(devices) == 0
Esempio n. 12
0
async def _async_has_devices(opp) -> bool:
    """Return if there are devices that can be discovered."""
    gree_discovery = Discovery(DISCOVERY_TIMEOUT)
    devices = await gree_discovery.scan(wait_for=DISCOVERY_TIMEOUT)
    return len(devices) > 0