Skip to content

Commit

Permalink
Add discover command to miiocli (#1013)
Browse files Browse the repository at this point in the history
* Add discover command to miiocli

* update discovery docs
  • Loading branch information
rytilahti authored Apr 16, 2021
1 parent 56bfbda commit 3053562
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 47 deletions.
50 changes: 6 additions & 44 deletions docs/discovery.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ do this on Debian-based systems (like Rasperry Pi) with
Device discovery
================
Devices already connected on the same network where the command-line tool
is run are automatically detected when ``mirobo discover`` is invoked.
Devices already connected to the same network where the command-line tool
is run are automatically detected when ``miiocli discover`` is invoked.
This command will execute two types of discovery: discovery by handshake and discovery by mDNS.
mDNS discovery returns information that can be used to detect the device type which does not work with all devices.
The handshake method works on all MiIO devices and may expose the token needed to communicate
with the device, but does not provide device type information.

To be able to communicate with devices their IP address and a device-specific
encryption token must be known.
Expand All @@ -29,48 +33,6 @@ it is likely a valid token which can be used directly for communication.
If not, the token needs to be extracted from the Mi Home Application,
see :ref:`logged_tokens` for information how to do this.

.. IMPORTANT::

For some devices (e.g. the vacuum cleaner) the automatic discovery works only before the device has been connected over the app to your local wifi.
This does not work starting from firmware version 3.3.9\_003077 onwards, in which case the procedure shown in :ref:`creating_backup` has to be used
to obtain the token.

.. NOTE::

Some devices also do not announce themselves via mDNS (e.g. Philips' bulbs,
and the vacuum when not connected to the Internet),
but are nevertheless discoverable by using a miIO discovery.
See :ref:`handshake_discovery` for more information about the topic.

.. _handshake_discovery:

Discovery by a handshake
------------------------

The devices supporting miIO protocol answer to a broadcasted handshake packet,
which also sometime contain the required token.

Executing ``mirobo discover`` with ``--handshake 1`` option will send
a broadcast handshake.
Devices supporting the protocol will response with a message
potentially containing a valid token.

.. code-block:: bash
$ mirobo discover --handshake 1
INFO:miio.device: IP 192.168.8.1: Xiaomi Mi Robot Vacuum - token: b'ffffffffffffffffffffffffffffffff'
.. NOTE::
This method can also be useful for devices not yet connected to any network.
In those cases the device trying to do the discovery has to connect to the
network advertised by the corresponding device (e.g. rockrobo-XXXX for vacuum)


Tokens full of ``0``\ s or ``f``\ s (as above) are either already paired
with the mobile app or will not yield a token through this method.
In those cases the procedure shown in :ref:`logged_tokens` has to be used.

.. _logged_tokens:

Tokens from Mi Home logs
Expand Down
18 changes: 18 additions & 0 deletions miio/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import click

from miio import Discovery
from miio.click_common import (
DeviceGroupMeta,
ExceptionHandlerGroup,
GlobalContextObject,
json_output,
)
from miio.miioprotocol import MiIOProtocol

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -41,6 +43,22 @@ def cli(ctx, debug: int, output: str):
cli.add_command(device_class.get_device_group())


@click.command()
@click.option("--mdns/--no-mdns", default=True, is_flag=True)
@click.option("--handshake/--no-handshake", default=True, is_flag=True)
@click.option("--network", default=None)
@click.option("--timeout", type=int, default=5)
def discover(mdns, handshake, network, timeout):
"""Discover devices using both handshake and mdns methods."""
if handshake:
MiIOProtocol.discover(addr=network, timeout=timeout)
if mdns:
Discovery.discover_mdns(timeout=timeout)


cli.add_command(discover)


def create_cli():
return cli(auto_envvar_prefix="MIIO")

Expand Down
7 changes: 4 additions & 3 deletions miio/discovery.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import codecs
import inspect
import logging
import time
from functools import partial
from ipaddress import ip_address
from typing import Callable, Dict, Optional, Union # noqa: F401
Expand Down Expand Up @@ -287,16 +288,16 @@ class Discovery:
"""

@staticmethod
def discover_mdns() -> Dict[str, Device]:
def discover_mdns(*, timeout=5) -> Dict[str, Device]:
"""Discover devices with mdns until any keyboard input."""
_LOGGER.info("Discovering devices with mDNS, press any key to quit...")
_LOGGER.info("Discovering devices with mDNS for %s seconds...", timeout)

listener = Listener()
browser = zeroconf.ServiceBrowser(
zeroconf.Zeroconf(), "_miio._udp.local.", listener
)

input() # to keep execution running until a key is pressed
time.sleep(timeout)
browser.cancel()

return listener.found_devices

0 comments on commit 3053562

Please sign in to comment.