Outils pour utilisateurs

Outils du site


issue132:tutoriel1

Hi everyone. It’s been quite a while since I’ve been able to do much in the way of writing, but things are slowly getting better, so I’ve decided to start again with a discussion of MQTT. MQTT is a lightweight, easy to use, network protocol to send data from one computer or application to another. It works in a client/server model, using a broker, publishers and subscribers. So what does that mean? One of the best examples I found that helps to break it all down, was to compare it to a post office (https://www.baldengineer.com/mqtt-introduction.html).

Salut à vous tous. Ça fait un bon moment que je n'ai pas été capable d'écrire longuement, mais les choses s'améliorent lentement ; aussi, j'ai décidé de redémarrer avec une présentation de MQTT.

MQTT est un protocole de réseau léger et facile d'emploi pour envoyer des données d'un ordinateur ou d'une application à une autre. Il fonctionne sous un modèle client/serveur, en utilisant un « broker » (intermédiaire), des éditeurs et des abonnés.

Et qu'est-ce que cela veut dire ?

Un des meilleurs exemples que j'ai trouvé qui aide à le décortiquer, a été de le comparer à un bureau de poste (https://www.baldengineer.com/mqtt-introduction.html).

The post office (broker or server) exists to route letters and packages (messages) from people and companies (publishers) to other people and companies (subscribers). If you want to send a message to someone, you create the message and send it to someone else through the post office. The post office receives your message and routes it to the recipient. However, the recipient needs to be known to the post office for them to be able to deliver it to them. In the above example, Mike wants to send a message to Sally. Mike (the publisher) sends the message to the post office and they know Sally's address, so they send it to her (subscriber). Sally can also send messages (not only a subscriber, but a publisher as well), through the post office, to John (another subscriber).

Le bureau de poste (intermédiaire ou serveur) existe pour diriger les lettres et paquets (les messages) de gens et d'entreprises (les éditeurs) vers d'autres gens et entreprises (les abonnés). Si vous voulez envoyer un message à quelqu'un, vous créez votre message et vous l'envoyez à quelqu'un d'autre par l'intermédiaire du bureau de poste. Le bureau de poste reçoit votre message et le dirige vers le destinataire. Cependant, le destinataire doit être connu du bureau de poste pour qu'il soit capable de le lui livrer.

Dans l'exemple ci-dessus, Mike veut envoyer un message à Sally. Mike (l'éditeur) envoie le message au bureau de poste qui connaît l'adresse de Sally ; ainsi, il le lui envoie (elle est l'abonnée). Sally (qui est à la fois abonnée et éditrice) peut aussi envoyer des messages, par le biais de la poste, à John (un autre abonné).

In the real world, we have an application, acting as a publisher, that sends messages, based on a topic, to the broker. The broker then sends the message along to any other program, on any other machine or the same machine, that has subscribed to that message topic. I have been asked, what happens if one of the clients that are subscribed to a topic goes away for some reason. There are three Quality of Service (QoS) levels that can be set for any message being sent to the broker. When a client normally connects to the broker, it is in a non-persistent manner and the QoS level is set to 0, so any messages that arrive when a subscribing client is not connected are lost. If it is important that the subscribers get all messages, the publishing client must set up a persistent session and send the messages with a Quality of Service level higher than 0. We’ll deal with QoS and persistent sessions next month when we create our publishing client.

Dans le monde réel, nous avons une application, agissant comme un éditeur, pour envoyer des messages, basés sur un sujet, à l'intermédiaire. L'intermédiaire renvoie ensuite le message à un autre programme, sur une autre machine ou sur la même machine, qui est abonnée au sujet de ce message.

On m'a demandé ce qui se passe si l'un des clients qui est abonné au sujet part pour une raison quelconque. Il y a trois niveaux de Qualité de Service (QoS, Quality of Service) qui peuvent être réglés pour chaque message envoyé à l'intermédiaire. Quand un client se connecte normalement à l'intermédiaire, c'est de manière non permanente et le niveau QoS est réglé à 0, de sorte que tout message qui arrive quand un client abonné n'est pas connecté est perdu. Si c'est important que les abonnés reçoivent tous les messages, le client éditeur doit établir une session permanente et envoyer les messages avec une Qualité de Service plus grande que 0. Nous nous occuperons de QoS et des sessions permanentes le mois prochain quand nous créerons notre client éditeur.

Let's assume that we have a Raspberry Pi 3 that sits in our garage that reads a DHT11 or DHT22 Humidity and Temperature sensor. Let's further assume that we have another Raspberry Pi 3 that we want to use to monitor that information in our bedroom. We can set up a MQTT broker on our bedroom RPi to receive the messages by using Mosquitto available in the software manager. The RPi in the garage can use a modified version of the software that we used way back in Full Circle Magazine #109 to monitor the sensor and publish the messages to the Mosquitto broker in the bedroom. On the RPi in the bedroom, we will write a simple Python program to subscribe to those messages. But first, let’s look deeply into MQTT under Python. For testing purposes, we’ll run the sensor, publishing program, broker and subscriber program all on the same Raspberry Pi.

Supposons qu'il y ait un Raspberry Pi 3 dans notre garage qui lit un capteur d'humidité et de température DHT11 ou DHT22. Supposons encore que nous ayons un autre Raspberry Pi 3 dans notre chambre, que nous voulons utiliser pour surveiller cette information. Nous pourrions paramétrer un intermédiaire MQTT sur le RPi de notre chambre pour recevoir les messages en utilisant Mosquitto, disponible dans le gestionnaire de logiciels.

Le RPi du garage peut utiliser une version modifiée du logiciel que nous avons utilisé dans le Full Circle Magazine n° 109, pour piloter le capteur et distribuer les messages à l'intermédiaire Mosquitto dans la chambre. Sur le RPi de la chambre, nous écrirons un programme simple en Python pour s'abonner à ces messages. Mais, d'abord, étudions en détail MQTT sous Python.

Pour les besoins des tests, nous lancerons le capteur, le programme d'édition, le programme d'intermédiaire et d'abonné ensemble sur le même Raspberry Pi.

The first thing we need to do is install Mosquitto and its two clients. From the Main Menu, go to Preferences | Add / Remove Software. In the search box, type ‘mosquitto’. You are looking for two packages. The first is the broker. It shows up as ‘MQTT version 3.1 / 3.1.1 compatible message broker mosquitto-1.4.15-0mosquitto1’. Select it, then, a few lines down from that, you want to find ‘Mosquitto command line MQTT clients mosquitto-clients-1.4.15-0mosquitto1’. Select this as well, then click the ‘Apply’ button. Once these are installed, you can dismiss the Software manager. Alternately, you can use apt-get to install it. In a terminal window, type sudo apt-get install mosquitto mosquitto-clients and they will be installed for you.

La première chose qu'il faut faire est d'installer Mosquitto et ses deux clients. À partir du menu principal, allez dans Preferences | Add / Remove Software (Préférences | Ajouter/supprimer un logiciel). Dans le champ de recherche, tapez « mosquitto ». Vous cherchez deux paquets. Le premier est l'intermédiaire. Il est présenté comme « MQTT version 3.1 / 3.1.1 compatible message broker mosquitto-1.4.15-0mosquitto1 ». Sélectionnez-le, puis, quelques lignes plus bas, vous devriez trouver « Mosquitto command line MQTT clients mosquitto-clients-1.4.15-0mosquitto1 ». Sélectionnez-le aussi, puis cliquez sur le bouton « Apply » (Appliquer). Une fois qu'ils sont installés, vous pouvez fermer le gestionnaire de logiciels. Autrement, vous pouvez utiliser apt-get pour l'installer. Dans une fenêtre de terminal, tapez :

sudo apt-get install mosquitto mosquitto-clients

et ils s'installeront pour vous.

Once you have these programs installed, reboot the RPi and mosquitto will automatically be started. You won’t see anything, but it is running. Now we’ll make sure things are working correctly. Open two terminal windows. Put one on the left side of the screen and the other on the right side. In the left window type mosquitto_sub -h localhost -t test When you press <enter>, nothing appears to happen, but you’ve created your first MQTT subscription. Let’s press pause for a second and see what we did. The first part of the line we just typed was (of course) the command to run ‘mosquitto_sub’, the command line subscription client for MQTT. The ‘-h localhost’ tells the client that the broker, or host, is running on our local host. The ‘-t test’ tells the client that it should subscribe to the topic named ‘test’. More on that in a minute. The reason that nothing happened when you pressed <enter> is that it’s waiting for a message to be published on the ‘test’ topic. So, let’s move over to the right terminal window and type

Une fois que les programmes sont installés, redémarrez votre RPi et mosquitto sera automatiquement lancé. Vous ne voyez rien, mais il tourne. Maintenant, nous nous assurerons que tout tourne correctement.

Ouvrez deux fenêtres de terminal. Mettez-en une sur le côté gauche de l'écran et l'autre sur le côté droit. Dans la fenêtre de gauche, tapez

mosquitto_sub -h localhost -t test

Quand vous appuyez sur Entrée, vous ne voyez rien, mais vous avez créé votre premier abonnement à MQTT. Appuyons sur Pause pour un court instant et voyons ce que nous avons fait.

La première partie de la ligne que nous venons de taper était (bien sûr) la commande pour lancer « mosquitto-sub », le client d'abonnement en ligne de commande de MQTT. « -h localhost » dit au client que l'intermédiaire, ou hôte, tourne sur notre hôte local. « -t test » dit au client qu'il devrait s'abonner au sujet appelé « test ». Plus à ce sujet dans une minute. La raison pour laquelle rien ne se passait quand vous avez appuyé sur Entrée est qu'il attend un message à transmettre sur le sujet « test ». Aussi, passons sur la fenêtre de terminal de droite et tapons

mosquitto_pub -h localhost -t test -m 'Hi There' Now look at the left terminal. You should see ‘Hi There’ echoed in the terminal. The ‘mosquitto_pub’ is the command-line publishing client. It runs one command at a time, so, everytime you want to publish a message, you have to enter the entire command into the terminal. Just like the command-line for the subscription client, the ‘-h localhost -t test’ portion of the command says to attach to the broker and subscribe to the ‘test’ topic. The final part of the command is the message itself, which is, of course, the ‘-m “Hi There”’ portion. While this seems very simple on the face of it, there is a lot going on here. The mosquitto broker (server) is running on our RPi and sits there by default listening on TCP/IP port 1883. You can change the port number to most any available TCP/IP port, however port 1883 is registered with IANA specifically for MQTT. TCP/IP port 8883 is also registered, for using MQTT over SSL. If you don’t want to run your own broker, there are many public brokers you can use, some of them are free. You can find a list of some of these and their conditions for use at https://github.com/mqtt/mqtt.github.io/wiki/public_brokers.

mosquitto_pub -h localhost -t test -m 'Hi There'

Maintenant, regardez le terminal de gauche. Vous pouvez voir « Hi there » reproduit sur le terminal.

« mosquitto_pub » est le client d'édition en ligne de commande. Il lance une commande à la fois ; aussi, chaque fois que vous voulez émettre un message, vous devez saisir toute la commande dans le terminal. Exactement comme la ligne de commande du client d'abonnement, la partie « -h localhost -t test » de la commande dit de se relier à l'intermédiaire et de s'abonner au sujet « test ». La fin de la commande est le message lui-même, qui est, bien sûr, la partie « -m Hi There ».

Alors que ceci semble très simple à première vue, pas mal de choses se passent.

L'intermédiaire mosquitto (le serveur) tourne sur votre RPi et, par défaut, se tient à l'écoute du port TCP/IP 1883. Vous pouvez remplacer le numéro du port par n'importe quel port TCP/IP disponible ; cependant, le port 1883 est enregistré par l'IANA spécifiquement pour MQTT. Le port TCP/IP 8883 est aussi enregistré pour l'utilisation de MQTT par SSL. Si vous ne voulez pas faire tourner votre propre intermédiaire, il y a de nombreux intermédiaires publics que vous pouvez utiliser, dont certains sont gratuits. Vous pouvez trouver une liste de certains d'entre eux et leurs conditions d'utilisation sur https://github.com/mqtt/mqtt.github.io/wiki/public_brokers.

When a program wants to publish to a broker, it first needs to connect, then sends the topic and the message. It doesn’t have to be concerned who’s there, if anyone. A subscribing program also doesn’t have to care about much, other than subscribing to the proper topic that is being published on the broker. The key here is that if you accidentally subscribe to the wrong topic, nothing will ever come in. When we set up our two terminal window test above, we started the subscriber client before the first message ever came in. The broker didn’t know (or care) what the topic was that we were subscribing to. It assumed we knew what we were doing. In the same way, when we published our ‘Hi There’ message on the ‘test’ topic, the broker simply took it and sent it out to whatever clients out there that happened to be subscribed to the topic, if any.

Quand un programme veut émettre vers un intermédiaire, il doit d'abord se connecter, puis il envoie le sujet et le message. Il ne se préoccupe pas de savoir s'il y quelqu'un à l'autre bout, et qui. Un programme d'abonnement ne s'en soucie pas beaucoup non plus, à part l'abonnement au sujet qui a été envoyé à l'intermédiaire. La clé ici est que, si vous vous abonnez accidentellement au mauvais sujet, rien ne vous arrivera. Lorsque nous avons mis en place notre test à deux terminaux ci-dessus, nous avons démarré le client abonné avant que le premier message n'arrive. L'intermédiaire ne connaît pas le sujet auquel nous souscrivons (et ne s'en préoccupe pas). Il suppose que nous savions ce que nous faisions. De la même manière, quand nous émettons notre message « Hi There » sur notre sujet « test », l'intermédiaire se contente de le prendre et de l'envoyer à n'importe quel client qui s'est abonné au sujet, le cas échéant.

The topic itself can be as simple as ‘test’ or extremely verbose. Some basic guidelines for topics are: • Case sensitive • Must be a UTF-8 string • Must consist of at least one character to be valid. • Wildcards are allowed when subscribing to a topic hierarchy, but when publishing to a topic, any message can be published to only a single topic (no wildcards are allowed when publishing). • There are no topics created on a broker by default other than $SYS system topics. • Topics are created by a subscribing or publishing client. They are NOT permanent. • Topics should not start with ‘$’, since those messages are for broker system messages. • Topics should be specific in nature, not general.

Le sujet lui-même peut être aussi simple que « test » ou extrêmement verbeux. Certaines règles de base pour les sujets sont : • Sensible à la casse. • Doit être une chaîne en UTF-8. • Doit consister en au moins un caractère pour être valide. • Des jokers sont autorisés lors d'un abonnement à une hiérarchie de sujets, mais lors de l'émission d'un sujet, tout message ne peut être envoyé qu'à un seul sujet (pas de joker lors de l'émission). • Aucun sujet n'est créé par défaut par l'intermédiaire en dehors des sujets système $SYS. • Les sujets sont créés par un client d'abonnement ou d'émission. Ils NE sont PAS permanents. • Les sujets ne doivent pas commencer par « $ », réservé pour les messages système de l'intermédiaire. • Les sujets doivent être spécifiques par nature, pas généraux.

Other than that, there are very little constraints on what a topic is or how it is constructed. Typically, if a client needs to publish more than a single type of message, the topics will be level based with each level separated by a forward slash (/). For example, in the program we will be writing to monitor and publish the DHT sensor values, we should use two different topics. One for the humidity value and one for the temperature value. We could combine the values into a string and only use one topic, but in this case, we will publish them separately. Making a very gross assumption, we will provide for a complete home solution, with multiple sensors of various types in multiple rooms of the house. We could then start our topic(s) with: housesensors/

En dehors de ça, il y a très peu de contraintes sur ce qu'est un sujet ou comment il est construit. Typiquement, si un client a besoin de publier plusieurs types de message, les sujets seront mis bout à bout et chaque partie sera séparée par un slash (/). Par exemple, dans le programme que nous écrirons pour suivre et émettre les valeurs du capteur DHT, nous devrions utiliser deux sujets différents. Un pour la valeur d'humidité et un pour la valeur de température. Nous pourrions combiner les valeurs dans une chaîne et n'utiliser qu'un seul sujet ; mais, dans le cas présent, nous les émettrons séparément. En faisant une estimation très grossière, nous fournirons une solution domestique complète, avec de nombreux capteurs de types divers dans différentes pièces de la maison. Nous pouvons commencer nos sujets avec :

housesensors/

This describes the topic to be one that will have sensor data specific to the house itself. This could include bedrooms, living areas and garden areas, but not something like a parking lot. The next level could possibly be floor based, as in first floor, basement and so on. housesensors/firstfloor/ Next could be the room or area. housesensors/firstfloor/bedroom/ Finally, we could set the topic to the specific type of value being published. housesensors/firstfloor/bedroom/humidity housesensors/firstfloor/bedroom/temperature

Il s'agit d'un sujet qui fournira des données de capteurs spécifiques à la maison elle-même. Cela peut comprendre les chambres, les zones de vie et les parties du jardin, mais pas un lieu comme un parking. Le prochain niveau pourrait être basé sur les étages, comme le premier étage, le rez-de-chaussée, et ainsi de suite.

housesensors/firstfloor/

Le suivant pourrait être la pièce ou la zone.

housesensors/firstfloor/bedroom/

Enfin, nous pourrions définir le sujet comme étant le type de valeur qui sera émise.

housesensors/firstfloor/bedroom/humidity

housesensors/firstfloor/bedroom/temperature

Notice that none of the topic strings have spaces in them. While spaces are not specifically prohibited, UTF-8 allows for many kinds of white space and could confuse things. You could also use mixed cases like ‘HouseSensors/FirstFloor/Bedroom/Humidity’, but since all topic strings are case sensitive, if you mistype a topic when publishing or subscribing, it could cause a good amount of time to debug things. I feel it makes it easier to go with all lower case. For our Python programs to communicate MQTT, we will use the paho-mqtt library. You can install it using pip. For Python 2.x: pip install –user paho-mqtt Or for Python 3.x: pip3 install –user paho-mqtt Full documentation on the phao library can be found at https://www.eclipse.org/paho/clients/python/ .

Notez qu'il n'y a aucune espace dans les chaînes de sujet. Alors que les espaces ne sont pas spécifiquement interdits, UTF-8 autorise beaucoup de sortes d'espace blanc, mais ça pourrait semer la confusion. Vous pourriez aussi utiliser une casse variée comme « HouseSensors/FirstFloor/Bedroom/Humidity » mais, comme toutes les chaînes de sujets sont sensibles à la casse, si vous vous trompez dans la saisie d'un sujet lors de l'émission ou de l'abonnement, il pourrait se passer du temps avant que les choses ne soient résolues. Je pense qu'il est préférable de tout mettre en minuscules.

Pour que nos programmes en Python puissent communiquer avec MQTT, nous utiliserons la bibliothèque paho-mqtt. Vous pouvez l'installer avec pip. Pour Python 2.x :

pip install –user paho-mqtt

Ou pour Python 3.x :

pip3 install –user paho-mqtt

Une documentation complète de la bibliothèque paho se trouve à https://www.eclipse.org/paho/clients/python/ .

As a sample program for you to test with, I’ll give you a short program that you can run and use the mosquitto_pub to send messages to it based on sample code from the eclipse site. I’ve made a couple of changes to make it work properly here. Of course, we need to import the library to get started. import paho.mqtt.client as mqtt Next, we’ll create a callback function (shown top right) that will run whenever the client connects to the broker. Next, we will make a callback function that runs whenever a message is received from the broker. It will print in the terminal the topic followed by the message. def on_message(client, userdata, msg): print(msg.topic+“ ”+str(msg.payload)) Now we instantiate the client and bind our callback functions to it.

Comme exemple de programme pour que vous le testiez, je vous donnerai un programme court que vous pouvez lancer, puis utiliser mosquitto_pub pour lui envoyer des messages sur la base de l'exemple de code du site eclipse. J'y ai fait quelques modifications pour qu'il fonctionne correctement ici.

Bien sûr, il nous faut importer la bibliothèque pour démarrer.

import paho.mqtt.client as mqtt

Ensuite, nous créerons une fonction de rappel (ci-dessus à droite) qui tournera si un message est reçu de l'intermédiaire. Elle imprimera le sujet suivi du message sur le terminal.

def on_message(client, userdata, msg):

  print(msg.topic+" "+str(msg.payload))

Maintenant, nous instancions le client et lui lions nos fonctions de rappel.

client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message Next, we connect to the broker, located at localhost. The 60 at the end of the call specifies a ‘keepalive’ time of 60 seconds, where the client pings the broker every 60 seconds. client.connect(“localhost”, 1883, 60) Finally we tell the client to loop_forever. Use the <ctrl>C keyboard interrupt to exit the sample program. # Blocking call that processes network traffic, dispatches callbacks and # handles reconnecting.

client = mqtt.Client()

client.on_connect = on_connect

client.on_message = on_message

Ensuite, nous nous connectons à l'intermédiaire, localisé sur localhost. Le 60 à la fin de l'appel spécifie un délai de « keepalive » (maintient actif) de 60 secondes, où le client « ping » l'intermédiaire toutes les 60 secondes.

client.connect(“localhost”, 1883, 60)

Enfin, nous disons au client de « loop_forever » (faire une boucle infinie). Utilisez l'interruption au clavier avec Ctrl-C pour sortir du programme exemple.

# Blocage de l'appel qui traite le trafic du réseau, répartit des rappels et

# traite les reconnexions.

# Other loop*() functions are available that give a threaded interface and a # manual interface. client.loop_forever() Now, save the program as ‘client1.py’ and run it. Go back to the terminal running mosquitto_pub and republish the previous message to the ‘test’ topic. You should see it appear in the terminal window of our running Python program. I’ve put the code up on Pastebin at https://pastebin.com/zL5ed9g9 Next month, we’ll update our original Python program from Full Circle Magazine #109 to support MQTT. Until then, have fun.

# D'autres fonctions loop() sont disponibles qui donnent une interface enfilée et

# une interface manuelle.

client.loop_forever()

Maintenant, sauvegardez le programme sous « client1.py » et lancez-le.

Retournez au terminal qui exécute mosquitto_pub et renvoyez le message précédent au sujet « test ». Vous devriez le voir apparaître dans la fenêtre de terminal où notre programme Python tourne. J'ai placé le code sur Pastebin à https://pastebin.com/zL5ed9g9

Le mois prochain, nous mettrons à jour notre programme Python original du n° 109 du Full Circle Magazine pour qu'il supporte MQTT.

Jusque-là, amusez-vous bien.

Encart de la page 21, les deux lignes commençant par « # »

# Subscribing in on_connect() means that if we lose the connection and # reconnect then subscriptions will be renewed.

# S'abonner avec on_connect signifie que si nous perdons la connexion et # nous nous reconnectons, les abonnements seront renouvelés.

issue132/tutoriel1.txt · Dernière modification : 2018/05/07 17:52 de andre_domenech