Skip to content

Commit fbc2ce0

Browse files
committed
MQTT tutorial done; move connect() into begin()
adjust the examples to use a lambda for `on_connect` callback. add username and password settings into example's secrets.py module. modify seealso admonition for less ambiguity with generic admonitions. openHAB tutorial started (far from done though).
1 parent 475dd5e commit fbc2ce0

File tree

13 files changed

+340
-40
lines changed

13 files changed

+340
-40
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Introduction
1212
:target: https://codecov.io/gh/2bndy5/CircuitPython_Homie
1313
:alt: Test Code Coverage
1414

15-
Homie specifications for MQTT implemented in CircuitPython
15+
Homie v4 specifications for MQTT implemented in CircuitPython
1616

1717
.. image:: https://homieiot.github.io/img/works-with-homie.svg
1818
:alt: Works with MQTT Homie

circuitpython_homie/__init__.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -323,12 +323,6 @@ def __init__(self, client: MQTT, name: str, device_id: str):
323323

324324
device_id = validate_id(device_id)
325325
self.topic = "/".join([self.base_topic, device_id])
326-
try:
327-
self.client.disconnect()
328-
except MMQTTException: # pragma: no cover
329-
pass # this exception meant the client was disconnected.
330-
self.client.will_set(self.topic + "/$state", "lost")
331-
self.client.connect(keep_alive=5)
332326

333327
def _publish_topic(self, topic: str, value, retain: bool = True):
334328
"""A helper to publish topics arbitrarily."""
@@ -345,9 +339,21 @@ def _publish_topic(self, topic: str, value, retain: bool = True):
345339
pub_val = str(pub_val)
346340
self.client.publish(topic, pub_val, retain=retain, qos=1)
347341

348-
def begin(self):
349-
"""Register this Homie device with the MQTT broker."""
350-
assert self.client.is_connected()
342+
def begin(self, **mqtt_settings):
343+
"""Register this Homie device with the MQTT broker.
344+
345+
:param mqtt_settings: All keyword arguments are used as parameters that get
346+
passed to :meth:`~adafruit_minimqtt.adafruit_minimqtt.MQTT.connect()`.
347+
"""
348+
# set the will and testament (requires being disconnected first)
349+
try:
350+
if self.client.is_connected():
351+
self.client.disconnect()
352+
except MMQTTException: # pragma: no cover
353+
pass # this exception meant the client was disconnected.
354+
self.client.will_set(self.topic + "/$state", "lost")
355+
self.client.connect(**mqtt_settings)
356+
351357
# publish default/required attributes
352358
for attr in ("homie", "name", "extensions", "implementation", "nodes", "fw"):
353359
self._publish_topic(self.topic + "/$" + attr, getattr(self, attr))
@@ -377,9 +383,9 @@ def begin(self):
377383
self.client.add_topic_callback(prop_topic + "/set", prop.callback)
378384
self.client.subscribe(prop_topic + "/set", qos=1)
379385
self._publish_topic(prop_topic, prop.value, retain=retained)
380-
self._publish_topic(self.topic + "/$state", "ready")
381386
if self.enable_broadcast:
382387
self.client.subscribe(self.base_topic + "/$broadcast/#", qos=1)
388+
self._publish_topic(self.topic + "/$state", "ready")
383389

384390
def set_state(self, state: str):
385391
"""Set the device's :homie-attr:`state` attribute on the MQTT broker.

docs/_static/extra_css.css

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,21 @@
2424
.topic-list li::marker {
2525
content: "/";
2626
}
27+
28+
*:root {
29+
--md-admonition-seealso-color: hsl(278, 100%, 63%);
30+
--md-eye--icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>');
31+
}
32+
33+
.admonition.seealso .admonition-title {
34+
background-color: hsla(278, 100%, 63%, 0.1);
35+
}
36+
37+
.admonition.seealso {
38+
border: 0 solid var(--md-admonition-seealso-color);
39+
}
40+
41+
.md-typeset .admonition.seealso :is(.admonition-title, summary)::before {
42+
background-color: var(--md-admonition-seealso-color);
43+
mask-image: var(--md-eye--icon);
44+
}

docs/conf.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,16 @@
158158
},
159159
],
160160
"toc_title_is_page_title": True,
161+
"social": [
162+
dict(
163+
icon="fontawesome/brands/github",
164+
link="https://github.com/2bndy5/CircuitPython_Homie",
165+
),
166+
dict(
167+
icon="fontawesome/brands/python",
168+
link="https://pypi.org/project/circuitpython-homie/",
169+
),
170+
],
161171
}
162172

163173
object_description_options = [

docs/examples.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,12 @@ In this secrets module should be 2 `dict`\ s:
2626
mqtt_settings = dict(
2727
broker="openhabian", # the broker's hostname or IP address
2828
port=1883, # the broker's port
29+
username="user_name",
30+
password="user_password",
2931
)
3032
33+
The MQTT username and password may not be required if you skipped :ref:`mqtt_user_password`.
34+
3135
Dependencies
3236
************
3337

docs/index.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@
2121

2222
.. toctree::
2323
:hidden:
24-
:caption: Tutorials
2524

26-
tutorials/openhab
25+
tutorials/intro
2726

2827
.. toctree::
2928
:hidden:

docs/tutorials/intro.rst

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
Tutorials
2+
=========
3+
4+
To aid with user setup, these docs are complete with tutorials about
5+
6+
.. toctree::
7+
:maxdepth: 1
8+
9+
mosquitto
10+
openhab
11+
12+
Controlling a system service in Linux (``systemctl``)
13+
-----------------------------------------------------
14+
15+
These are some common commands for ``systemctl`` on Linux that may be helpful, all of which
16+
should require root permission (``sudo``) to execute successfully.
17+
18+
.. program:: systemctl
19+
20+
.. option:: enable
21+
22+
This command is used to make a service start when the machine boots up. To enable Mosquitto
23+
broker (as a system service) to start on boot up:
24+
25+
.. code-block:: shell
26+
27+
sudo systemctl enable mosquitto
28+
29+
.. option:: status
30+
31+
This command is used to print the status of a running mosquitto broker. It can be useful because
32+
it will show if there was any errors in running the process.
33+
34+
.. code-block:: shell
35+
36+
sudo systemctl status mosquitto
37+
38+
.. hint::
39+
If there were any errors, then this will tell you what file in which the logs were saved.
40+
41+
.. option:: restart
42+
43+
This command is useful if you need to restart your broker after making changes to the
44+
configuration.
45+
46+
.. code-block:: shell
47+
48+
sudo systemctl restart mosquitto
49+
50+
.. option:: start
51+
52+
The command to start the broker as a service (as opposed to directly running the ``mosquitto``
53+
or ``openhab`` binary executables). This is really only useful if you don't want the broker
54+
service to start on boot (ie. doing tests configurations).
55+
56+
.. code-block:: shell
57+
58+
sudo systemctl start openhab
59+
60+
.. option:: stop
61+
62+
The command to stop any running system service. This is mentioned for completeness
63+
because it is the opposite of :std:option:`start`.

docs/tutorials/mosquitto.rst

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
Setting Up an MQTT broker (Mosquitto)
2+
=====================================
3+
4+
`Mosquitto <https://mosquitto.org/>`_ is a popular choice and is available for most platforms.
5+
`Download/install instructions <https://mosquitto.org/download/>`_ are pretty straight forward.
6+
7+
.. admonition:: Installing Mosquitto on Linux
8+
:class: todo
9+
10+
.. code-block:: shell
11+
12+
sudo apt-get install mosquitto
13+
14+
Configuring Mosquitto
15+
---------------------
16+
17+
You may have to change the default configuration used by the Mosquitto broker to allow other
18+
network devices to connect. For me (using v2.0.11 on Ubuntu), this meant editing the file
19+
located at **/etc/mosquitto/mosquitto.conf**.
20+
21+
Open the file with root permission from the terminal (or via SSH client):
22+
23+
.. code-block:: shell
24+
25+
sudo nano /etc/mosquitto/mosquitto.conf
26+
27+
Make sure a ``listener`` is bound to a port (typically ``1883`` by default) with the domain
28+
``0.0.0.0`` (the server machine's ``localhost``). If you want to skip
29+
mqtt_user_password_, then add a line that sets ``allow_anonymous`` to ``true``.
30+
It should end up looking like this:
31+
32+
.. code-block:: pacmanconf
33+
:caption: /etc/mosquitto/mosquitto.conf
34+
35+
listener 1883 0.0.0.0
36+
37+
# to bypass username and password configuration
38+
allow_anonymous true
39+
40+
Save and close the file, then :std:option:`systemctl restart` the broker.
41+
42+
Checking the Mosquitto broker logs
43+
**********************************
44+
45+
By default, the logs for mosquitto are saved to **/var/log/mosquitto/mosquitto.log**. This can be
46+
changed with the ``log_dest file`` value in the configuration:
47+
48+
.. code-block:: text
49+
:caption: Default Log Destination in **/etc/mosquitto/mosquitto.conf**
50+
51+
log_dest file /var/log/mosquitto/mosquitto.log
52+
53+
If the broker fails to understand a given configuration, then these logs will point to what
54+
configuration option was erroneous.
55+
56+
.. code-block:: shell
57+
:caption: Print Logs in the terminal (requires root permission)
58+
59+
sudo cat /var/log/mosquitto/mosquitto.log
60+
61+
.. _mqtt_user_password:
62+
63+
Setting a username and password
64+
-------------------------------
65+
66+
It is recommended that your MQTT broker's access be secured via a username and password.
67+
The Mosquitto broker uses a password file to store these values securely.
68+
69+
1. .. code-block:: shell
70+
:caption: Create the password file for a user
71+
72+
mosquitto_passwd -c pswd.txt username
73+
74+
The above command creates a password file named ``pswd.txt`` for a user named ``username``.
75+
76+
.. details:: Adding another user
77+
:class: info
78+
79+
Use the ``-b`` switch to add more users:
80+
81+
.. code-block:: shell
82+
83+
mosquitto_passwd -b pswd.txt other_username user_password
84+
.. details:: Removing a user
85+
:class: error
86+
87+
Use the ``-D`` switch to remove a user:
88+
89+
.. code-block:: shell
90+
91+
mosquitto_passwd -D pswd.txt other_username user_password
92+
.. note::
93+
If you inspect the password file after creation, you will notice that the password
94+
associated with usernames is not what you entered. This is because ``mosquitto_passwd``
95+
encrypts the password using a SHA512 scheme.
96+
2. .. code-block:: shell
97+
:caption: Move the password file to the broker's configuration path
98+
99+
sudo mv pswd.txt /etc/mosquitto/
100+
101+
The **pswd.txt** file you created should now be next to you broker's configuration file
102+
(**/etc/mosquitto/mosquitto.conf**).
103+
3. Add the following lines to the broker's configuration file.
104+
105+
.. details:: Open your broker's configuration file
106+
:class: faq
107+
108+
.. code-block:: shell
109+
110+
sudo nano /etc/mosquitto/mosquitto.conf
111+
112+
.. code-block:: text
113+
:caption: add the password file's path to the configuration
114+
115+
per_listener_settings true
116+
117+
listener 1883 0.0.0.0
118+
allow_anonymous false
119+
password_file /etc/mosquitto/pswd.txt
120+
121+
- ``per_listener_settings`` is required to assign the password file to a listener.
122+
- ``alow_anonymous`` should be disabled if you want to prohibit non-authenticated access to
123+
your broker.
124+
- ``password_file`` is the path to the password file created with encrypted passwords.
125+
126+
4. :std:option:`systemctl restart` (or :std:option:`systemctl start`) to force the broker to use
127+
the updated configuration.
128+
129+
.. admonition:: Enabling SSL
130+
:class: check
131+
132+
If desired, you can enable SSL support in your broker for additional security and
133+
anti-corruption of data. Since this is all rather technical and a bit more involved, I would
134+
recommend following `Steve's Internet Guide <http://www.steves-internet-guide.com/mosquitto-tls/>`_.
135+
136+
MQTT Explorer
137+
-------------
138+
139+
To verify that this library is publishing and subscribing topics with your MQTT broker, I
140+
recommend using the `MQTT Explorer app <https://mqtt-explorer.com/>`_ (which works well
141+
on my Windows PC).
142+
`Downloads are available <https://github.com/thomasnordquist/MQTT-Explorer/releases/latest>`_
143+
for most platforms. There's even a stable release deployed in the Windows App Store and the
144+
Snap Store for Linux.

0 commit comments

Comments
 (0)