Contributing¶
Contributions of any sort are more than welcome, so we hope this short introduction will help you to get started! Shortly put: we use black to format our code, isort to sort our imports, pytest to test our code, flake8 to do its checks, and doc8 for documentation checks.
See Development environment for setting up a development environment, and Improving device support for some helpful tips for adding support for new devices.
Contents
Development environment¶
This section will shortly go through how to get you started with a working development environment. We use poetry for managing the dependencies and packaging, so simply execute:
poetry install
If you were not already inside a virtual environment during the install,
poetry will create one for you.
You can execute commands inside this environment by using poetry run <command>
,
or alternatively,
enter the virtual environment shell by executing poetry shell
to avoid repeating poetry run
.
To verify the installation, you can launch tox to run all the checks:
tox
In order to make feedback loops faster, we automate our code checks by using precommit hooks. Therefore the first step after setting up the development environment is to install them:
pre-commit install
You can always execute the checks also without doing a commit.
Code checks¶
Instead of running all available checks during development, it is also possible to execute only the code checks by calling. This will execute the same checks that would be done automatically by precommit when you make a commit:
tox -e lint
Tests¶
We prefer to have tests for our code, so we use pytest you can also use by executing:
pytest miio
When adding support for a new device or extending an already existing one, please do not forget to create tests for your code.
Generating documentation¶
You can compile the documentation and open it locally in your browser:
sphinx-build docs/ generated_docs
$BROWSER generated_docs/index.html
Replace $BROWSER with your preferred browser, if the environment variable is not set.
Improving device support¶
Whether adding support for a new device or improving an existing one, the journey begins by finding out the commands used to control the device. This usually involves capturing packet traces between the device and the official app, and analyzing those packet traces afterwards. The process is as follows:
Install Android emulator (BlueStacks emulator has been reported to work on Windows).
Install the official Mi Home app in the emulator and set it up to use your device.
Install WireShark (or use
tcpdump
on Linux) to capture the device traffic.Use the app to control the device and save the resulting PCAP file for later analyses.
Obtain the device token in order to decrypt the traffic.
Use
devtools/parse_pcap.py
script to parse the captured PCAP files.
python devtools/parse_pcap.py <pcap file> --token <token>
MiOT devices¶
For MiOT devices it is possible to obtain the available commands from the cloud.
The git repository contains a script, devtools/miottemplate.py
, that allows both
downloading the description files and parsing them into more understandable form.
Development checklist¶
All device classes are derived from either
miio.device.Device
(for MiIO) ormiio.miot_device.MiotDevice
(for MiOT) (Minimal example).All commands and their arguments should be decorated with @command decorator, which will make them accessible to miiocli (miiocli integration).
All implementations must either include a model-keyed
_mappings
list (for MiOT), or defineDevice._supported_models
variable in the class (for MiIO). listing the known models (as reported by info()).Status containers is derived from DeviceStatus class and all properties should have type annotations for their return values.
Creating tests (Adding tests).
Updating documentation is generally not needed as the API documentation will be generated automatically.
Minimal example¶
Todo
Add or link to an example.
miiocli integration¶
All user-exposed methods of the device class should be decorated with
miio.click_common.command()
to provide console interface.
The decorated methods will be exposed as click commands for the given module.
For example, the following definition:
@command(
click.argument("string_argument", type=str),
click.argument("int_argument", type=int, required=False)
)
def command(string_argument: str, int_argument: int):
click.echo(f"Got {string_argument} and {int_argument}")
Produces a command miiocli example
command requiring an argument
that is passed to the method as string, and an optional integer argument.
Status containers¶
The status container (returned by status() method of the device class)
is the main way for library users to access properties exposed by the device.
The status container should inherit miio.device.DeviceStatus
to ensure a generic __repr__()
.
Adding tests¶
Todo
Describe how to create tests. This part of documentation needs your help! Please consider submitting a pull request to update this.
Documentation¶
Todo
Describe how to write documentation. This part of documentation needs your help! Please consider submitting a pull request to update this.