fizista / micropython-umqtt.simple2

MIT License
76 stars 36 forks source link

.. role:: bash(code) :language: bash

.. role:: python(code) :language: python

umqtt.simple2

umqtt.simple2_ is a MQTT client for MicroPython. (Note that it uses some MicroPython shortcuts and doesn't work with CPython).

Support MQTT Version 3.1.1 only.

It certainly works with micropython ports: esp8266 and esp32. It should also work with other ports, but the library was not tested under other ports.

======== =========== ======== =========== Micropython Port Version Normal SSL ======== =========== ======== =========== esp8266 1.9.1 OK Test fails esp32 1.9.1 OK OK ======== =========== ======== ===========

MQTT client with more features

There's a separate umqtt.robust2 module which builds on umqtt.simple2 adds the ability to reconnect. It is able to send unsent messages itself. And many more...

Differences between umqtt.simple and umqtt.simple2

Problems and solutions

.. code-block:: python

import sys
sys.path.reverse()

How and where to install this code?

You can install using the upip:

.. code-block:: python

import upip
upip.install("micropython-umqtt.simple2")

or

.. code-block:: bash

micropython -m upip install -p modules micropython-umqtt.simple2

You can also clone this repository, and install it manually:

.. code-block:: bash

git clone https://github.com/fizista/micropython-umqtt.simple2.git

Manual installation gives you more possibilities:

Please note that the PyPi repositories contain optimized code (no comments).

Design requirements

API design

Based on the requirements above, there are following API traits:

API reference

Taking into account API traits described above, umqtt pretty closely follows MQTT control operations, and maps them to class methods:

wait_msg() and check_msg() are "main loop iteration" methods, blocking and non-blocking version. They should be called periodically in a loop, wait_msg() if you don't have any other foreground tasks to perform (i.e. your app just reacts to subscribed MQTT messages), check_msg() if you process other foreground tasks too.

Note that you don't need to call wait_msg()/check_msg() if you only publish messages with QoS==0, never subscribe to them.

If you are using a subscription and/or sending QoS>0 messages, you must run one of these commands ( wait_msg() or check_msg() ).

For more detailed information about API please see the source code (which is quite short and easy to review) and provided examples.

Supported MQTT features

QoS 0 and 1 are supported for both publish and subscribe. QoS2 isn't supported to keep code size small. Besides ClientID, only "clean session" parameter is supported for connect as of now.

Simple library testing

The current tests are not only to test the code, but also to check it in a real environment. Therefore, a good idea, before we use this library in our own project, is to test its operation with the MQTT broker.

To test if the library works well with your device and MQTT broker, use the TestMQTT class from the tests.py module.

If you don't have your own MQTT broker yet, you can use the free MQTT test broker (test.mosquitto.org).

There is also a sample file main.py(example_test_main.py), In this file we add only network configuration. Upload this file to your device with umqtt.simple2_ library and tests.py module. Then reset the device and watch the results in the console.

How to get tests up and running quickly:

.. code-block:: bash

cp example_test_main.py main.py

In the main.py file, assign the appropriate values from your WiFi network to the WIFI_SSID and WIFI_PASSWORD variables.

.. code-block:: bash

./upload_to_device.sh

or

.. code-block:: bash

./upload_to_device.sh yes # A compiled version that takes up less memory on devices.

Launching the tests:

.. code-block:: bash

screen /dev/ttyUSB0  115200 # or screen /dev/ttyACM0  115200
# Ctrl+D - to restart device

Configuring an encrypted connection with test.mosquitto.org:

.. code-block:: bash

openssl genrsa -out client.key
openssl req -out client.csr -key client.key -new
cat client.csr # Copy and paste on the page: https://test.mosquitto.org/ssl/ , click "submit"
# Save the certificate to the same directory as client.crt
# Dowlnoad mosquitto.org.crt
# Change key formats:
openssl x509 -in client.crt -out client.crt.der -outform DER
openssl rsa -in client.key -out client.key.der -outform DER
openssl x509 -in mosquitto.org.crt -out mosquitto.org.crt.der -outform DER
# Upload to device
ampy -d1 --baud 115200 --port /dev/ttyACM0 put ./client.key.der
ampy -d1 --baud 115200 --port /dev/ttyACM0 put ./client.crt.der
ampy -d1 --baud 115200 --port /dev/ttyACM0 put ./mosquitto.org.crt.der

Configuring keys for MQTT server(eg. mosquitto):

.. code-block:: bash

openssl req -new -x509 -days 365 -extensions v3_ca -keyout ca.key -out ca.crt -subj "/C=XX/ST=Home/L=Home/O=MyCA/OU=MyCA/CN=myca"

openssl genrsa -out server.key 2048
openssl req -new -out server.csr -key server.key -subj "/C=XX/ST=Home/L=Home/O=MQTT Broker/OU=MQTT Broker/CN=YourMQTTserver"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365
openssl rsa -in server.key -out server.key
openssl rsa -inform pem -in server.pem -outform der -out key.der

Configuring keys for MQTT server(eg. mosquitto):

.. code-block:: bash

openssl genrsa -out client.key 2048
openssl req -new -out client.csr -key client.key -subj "/C=XX/ST=Home/L=Home/O=MQTT Client/OU=MQTT Client/CN=YourDeviceHostName"
openssl x509 -req -in client.csr -CA ../ca.crt -CAkey ../ca.key -CAcreateserial -out client.crt -days 365
openssl rsa -in client.key -out client.key
openssl x509 -in client.crt -out client.crt.der -outform DER
openssl rsa -in client.key -out client.key.der -outform DER
ampy -d1 --baud 115200 --port /dev/ttyACM0 put ./client.key.der
ampy -d1 --baud 115200 --port /dev/ttyACM0 put ./client.crt.der

Configuring mosquitto:

.. code-block:: bash

mosquitto_passwd -c /etc/mosquitto/passwd
touch /etc/mosquitto/acl

mosquitto.conf

.. code-block::

per_listener_settings true

persistence true
persistence_location /var/lib/mosquitto/
persistent_client_expiration 4m

log_dest file /var/log/mosquitto/mosquitto.log
log_type all

include_dir /etc/mosquitto/conf.d

# MQTT, unencrypted, unauthenticated=anonymous
listener 1883 0.0.0.0
socket_domain ipv4
allow_anonymous true
set_tcp_nodelay true
#keepalive_interval 0
max_keepalive 0

# MQTT, unencrypted, authenticated=password
listener 1884 0.0.0.0
socket_domain ipv4
password_file /etc/mosquitto/passwd
#acl_file /etc/mosquitto/acl
set_tcp_nodelay true
#keepalive 0

# MQTT, encrypted, unauthenticated
listener 8883 0.0.0.0
socket_domain ipv4
allow_anonymous true
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

# MQTT, encrypted, client certificate required
listener 8884 0.0.0.0
socket_domain ipv4
allow_anonymous true
cafile /etc/mosquitto/certs/ca.crt
capath /etc/mosquitto/certs/certs
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate true
use_identity_as_username true # When set to true it tells mosquitto not to use the password file

# MQTT, encrypted, authenticated
listener 8885 0.0.0.0
socket_domain ipv4
password_file /etc/mosquitto/passwd
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

.. code-block:: bash

chown -R mosquitto:mosquitto /etc/mosquitto/certs/

Different problems

Additional resources

.. _umqtt.simple2: https://github.com/fizista/micropython-umqtt.simple2 .. _umqtt.robust2: https://github.com/fizista/micropython-umqtt.robust2