[Point clé] Springboot + rabbitmq + protocole mqtt pour la maison intelligente

Démo push de nouvelles: https://www.cnblogs.com/songyaru/p/13596600.html

Envoyer / recevoir une démo: https://blog.csdn.net/z69183787/article/details/110079628

Dans le paragraphe précédent, j'ai eu l'honneur de participer au développement d'un projet de maison intelligente. Comme je n'ai aucune expérience de développement dans ce domaine, je suis assez curieux du modèle de développement et de la pile technologique du matériel intelligent.

 

Alarme intelligente de gaz combustible

Le produit est une alarme de gaz combustible. Si la concentration de fuite de gaz dans la maison atteint un certain seuil, l'alarme détecte et télécharge la valeur de concentration de gaz en arrière-plan. L'arrière-plan utilise des appels téléphoniques, des messages texte, WeChat, etc. pour rappeler utilisateurs qu'il peut y avoir une fuite de gaz dans la maison.

L'utilisateur peut également envoyer des instructions pour désactiver l'alarme et régler le volume de l'alarme. La fonction globale est relativement simple, la logique générale est illustrée dans la figure ci-dessous:

 

 

Mais quand j'ai participé au développement, j'ai en fait été un peu déçu, car dans tout le processus de développement, aucune nouvelle technologie n'a été utilisée, ou plusieurs middlewares conventionnels ont simplement changé l'utilisation.

La sélection de la technologie utilise rabbitmq comme composant de base, compte tenu principalement du faible coût d'exploitation et de maintenance et de la compétence relativement élevée des membres du groupe.


Permettez-moi de partager avec mes amis comment utiliser springboot + rabbitmq pour créer une plate-forme Internet des objets (IOT) En fait, le matériel intelligent n'est pas aussi élevé que prévu!

Beaucoup d'amis peuvent être un peu confus? Rabbitmq n'est-il pas une file d'attente de messages? Comment refaire du matériel intelligent ?

En fait, rabbitmq a deux protocoles: la file d'attente de messages que nous contactons habituellement est le protocole AMQP et le protocole MQTT utilisé dans le matériel intelligent.

1. Qu'est-ce que le protocole MQTT?

Le nom complet de MQTT (Message Queue Telemetry Transport): un protocole de communication léger basé sur le mode publication / abonnement (publication / abonnement), qui obtient des messages en s'abonnant à la rubrique correspondante. Il s'agit d'une transmission standard dans le protocole Internet of Thing.

Ce protocole sépare l'éditeur et l'abonné du message, de sorte qu'il peut fournir des services de messagerie fiables pour les appareils connectés à distance dans un environnement réseau non fiable, et l'utilisation est quelque peu similaire à MQ traditionnel.

 

 

Le protocole TCP est situé au niveau de la couche transport, le protocole MQTT est situé au niveau de la couche application et le protocole MQTT est basé sur le protocole TCP / IP, ce qui signifie que tant que la pile de protocoles TCP / IP est prise en charge, le protocole MQTT protocole peut être utilisé.

2. Pourquoi utiliser le protocole MQTT?

Pourquoi le protocole MQTT est-il si apprécié dans l'Internet des objets (IOT)? Au lieu d'autres protocoles, tels que le protocole HTTP plus familier?

  • Tout d'abord, le protocole HTTP est un protocole synchrone et le client doit attendre la réponse du serveur après la demande. Dans l'environnement Internet des objets (IOT), les appareils sont soumis à des influences environnementales, telles qu'une faible bande passante, une latence réseau élevée et une communication réseau instable. De toute évidence, les protocoles de messagerie asynchrone sont plus adaptés aux applications IOT.
  • HTTP est unidirectionnel. Si vous souhaitez recevoir des messages, le client doit établir une connexion. Dans les applications Internet des objets (IOT), les appareils ou les capteurs sont souvent des clients, ce qui signifie qu'ils ne peuvent pas recevoir passivement les commandes du réseau.
  • Il est généralement nécessaire d'envoyer une commande ou un message à tous les appareils du réseau. Il est non seulement difficile pour HTTP de réaliser une telle fonction, mais aussi extrêmement coûteux.

Trois, introduction du protocole MQTT

Comme mentionné précédemment, MQTT est un protocole léger qui se concentre uniquement sur l'envoi de messages, donc la structure de ce protocole est également très simple.

Paquet MQTT

Dans le protocole MQTT, un paquet de données MQTT se compose de trois parties: un en-tête fixe (en-tête fixe), un en-tête variable (en-tête variable) et un corps de message (charge utile).

  • En-tête fixe (en-tête fixe), tous les paquets de données ont un en-tête fixe, y compris le type de paquet de données et l'identification du paquet.
  • En-tête variable (en-tête variable), certains types de paquets de données ont des en-têtes variables.
  • Le corps du message de contenu (Payload), qui existe dans certains paquets de données, est le contenu du message spécifique reçu par le client.

 

 

Insérez la description de l'image ici

1. Tête fixe

En-tête fixe, utilisant deux octets, un total de 16 bits:

 

 

Les bits (4-7) représentent le type de message, en utilisant une représentation binaire à 4 bits, qui peut représenter les 16 types de message suivants, mais les positions 0 et 15 sont réservées à l'utilisation, il y a donc 14 types d'événements de message au total.

 

 

Indicateur DUP (indicateur de nouvelle tentative)

Indicateur DUP: pour assurer la transmission fiable du message et si le message a été remis. La valeur par défaut est 0, qui n'occupe qu'un octet, ce qui signifie qu'il est envoyé pour la première fois. Lorsque la valeur est 1, cela signifie que le message en cours a déjà été transmis.

Niveau QoS (niveau de qualité du message)

Niveau QoS: le niveau de qualité du message, qui sera présenté en détail ultérieurement

RETAIN (persistant)

  • Une valeur de 1: indique que le message envoyé doit être stocké de manière permanente et n'est pas affecté par le redémarrage du serveur. Non seulement il doit être envoyé à l'abonné actuel, mais le nouveau client s'abonnera à cette rubrique à l'avenir et l'abonné sera poussé immédiatement. Remarque : les abonnés nouvellement ajoutés ne retireront que le dernier message push avec l'indicateur RETAIN = 1.
  • La valeur est 0: ce message est envoyé uniquement à l'abonné actuel.

Longueur restante

Le nombre d'octets restants dans le message actuel, y compris les en-têtes de variables et la charge utile du corps du message.

2. Tête variable

L'en-tête fixe définit uniquement le type de message et certains bits d'indicateur, et certaines métadonnées de message doivent être placées dans l'en-tête de variable. Longueur d'octet de contenu d'en-tête variable + charge utile du corps du message = longueur restante.

L'en-tête variable est situé entre l'en-tête fixe et la charge utile, et contient le nom du protocole, le numéro de version, le logo de connexion, l'autorisation de l'utilisateur, le temps de pulsation, etc.

Des en-têtes variables existent dans ces types de messages: PUBLISH (QoS> 0), PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK.

3. Charge utile du corps du message

La charge utile du corps du message n'existe que dans les types de messages CONNECT, PUBLISH, SUBSCRIBE, SUBACK, UNSUBSCRIBE:

  • CONNECT: Contient le ClientId du client, le sujet, le message, le nom d'utilisateur et le mot de passe souscrits.
  • PUBLIER: Envoyez un message à la rubrique correspondante.
  • SOUSCRIRE: Sous réserve d'être abonné et QoS.
  • SUBACK: Le serveur confirme et répond au sujet et à la QoS appliqués par SUBSCRIBE.
  • UNSUBSCRIBE: annulez le sujet à souscrire.

Qualité des messages (QoS)

Qualité de service (Quality of Service), c'est-à-dire la qualité de l'envoi des messages. L'éditeur et l'abonné peuvent spécifier le niveau de qualité de service. Il existe trois niveaux de qualité de service 0, QoS 1 et QoS 2.

Voici les différences entre ces trois niveaux.

1 、 Qos 0

Qos 0: Au plus une fois (au plus une fois) le message est envoyé une seule fois. Il n'y a aucune garantie que le message sera livré avec succès. Il n'y a pas de mécanisme de confirmation et le message peut être perdu ou répété.

 

 

L'image provient d'Internet, s'il y a une violation de contact supprimer

2 、 Qos 1

Qos 1: Au moins une fois (au moins une fois). Par rapport à QoS 0, Qos 1 ajoute un mécanisme de confirmation d'acquittement. Lorsque l'expéditeur (éditeur) envoie le message au courtier MQTT (courtier), les deux conservent le message en premier Lorsque l'éditeur ou le courtier reçoit respectivement la confirmation PUBACK, il supprimera son message persistant, sinon il le renverra.

Mais il y a un problème. Bien que nous puissions garantir que nous recevrons le message du client ou du serveur par confirmation, nous ne pouvons garantir que le message ne sera reçu qu'une seule fois, c'est-à-dire lorsque l'éditeur client ne reçoit pas le message du client le courtier ou le courtier ne reçoit pas l'abonné. Puback, alors il sera toujours renvoyé.

Éditeur -> processus général du courtier:

  1. publisher store msg -> publier -> courtier (传递 message)
  2. courtier -> puback -> éditeur supprimer msg (confirmer que la livraison est réussie)

 

 

L'image provient d'Internet, s'il y a une violation de contact supprimer

3 、 Qos 2

Qos 2: Exactement une fois (une seule fois). Par rapport à QoS 1, la mise à niveau de QoS 2 réalise qu'un seul message est accepté. L'éditeur et le courtier conservent également le message. L'éditeur met en cache le message et le msgID correspondant, et le courtier met en cache le msgID., Il peut garantir que le message n'est pas répété, et l'ensemble du processus devient beaucoup plus compliqué en raison de l'ajout d'un mécanisme de confirmation.

Éditeur -> processus général du courtier:

  1. publisher store msg -> publier -> courtier -> magasin de courtier
  2. courtier msgID (transmettre le message) -> puberc (confirmer que la livraison est réussie)
  3. éditeur -> pubrel -> courtier supprime le msgID (dites au courtier de supprimer le msgID)
  4. broker -> pubcomp -> publisher delete msg (dites à l'éditeur de supprimer le msg)

 

 

L'image provient d'Internet, s'il y a une violation de contact supprimer

LWT (dernière volonté)

Le nom complet de LWT est Last Will and Testament. En fait, un testament est un sujet et un message correspondant prédéfini par le client, qui est attaché au paquet CONNECT, y compris le sujet du dernier souhait, la QoS du dernier souhait, et le message du dernier souhait.

Lorsque l'agent Broker MQTT détecte que le client est anormalement déconnecté, le serveur publie activement ce message et les abonnés concernés le recevront.

Prenez un châtaigne : tout le monde dans la salle de chat s'abonne à un sujet appelé discussion, mais Xiaofu a soudainement déconnecté le lien en raison de l'instabilité du réseau. À ce stade, tous les clients de la salle de discussion qui se sont abonnés à la discussion sur le sujet recevront un chat "Xiaofu quitté" Dernier message de souhait de "Room".

Paramètres liés du testament:

  • Will Flag: s'il faut utiliser LWT, 1 est activé
  • Thème Will: Nom du sujet du dernier souhait, les caractères génériques ne sont pas autorisés
  • Will Qos: QoS utilisé lors de la publication des derniers messages de souhaits
  • Will conserver: conserver le logo du dernier message testamentaire
  • Will Message: Contenu du dernier message de souhait

Ensuite, dans quels scénarios le client client se déconnecte-t-il anormalement?

  • Broker détecte l'exception d'E / S sous-jacente;
  • Le client n'a pas réussi à communiquer avec le courtier dans l'intervalle du battement de cœur Keep Alive;
  • Le client n'a pas envoyé de paquet DISCONNECT avant de fermer la connexion TCP sous-jacente;
  • Le client envoie un paquet de données mal formaté au courtier, provoquant la fermeture de la connexion avec le client, etc.

Remarque : lorsque le client se déconnecte en publiant le paquet DISCONNECT, il s'agit d'une déconnexion normale et ne déclenche pas le mécanisme LWT. Dans le même temps, le courtier supprimera également les paramètres LWT pertinents spécifiés par le client actuel lors de la connexion.

Quatre scénarios d'application du protocole MQTT

Le protocole MQTT est largement utilisé dans l'Internet des objets, l'Internet mobile, le matériel intelligent, l'Internet des véhicules, l'énergie électrique et d'autres domaines. Il existe de nombreuses scènes utilisées, en voici quelques-unes:

  • Communication M2M Internet des objets, collecte de données volumineuses Internet des objets
  • Push de message Android, push de message WEB
  • Messagerie instantanée mobile, telle que Facebook Messenger
  • Matériel intelligent, meubles intelligents, appareils intelligents
  • Communication télématique, collecte des piles de stations électriques
  • Ville intelligente, télémédecine, enseignement à distance
  • Marchés des industries de l'électricité, du pétrole et de l'énergie

Cinq, implémentation du code

Je n’entrerai pas dans les détails de l’environnement rabbitmq. Il existe de nombreux didacticiels en ligne. Si vous avez des conditions, vous pouvez utiliser le serveur. Si vous n’avez pas de conditions, je suis heureux de créer une version de Windows.

 

 

Insérez la description de l'image ici

1. Activez le protocole mqtt de rabbitmq

Ouvrons d'abord le protocole mqtt de rabbitmq, car il est fermé par l'installation par défaut, la commande est la suivante:

rabbitmq-plugins enable rabbitmq_mqtt
复制代码

2. Package de dépendance client Mqtt

Après avoir installé l'environnement rabbitmq et activé le protocole mqtt à l'étape précédente, le service de courtier de messages mqtt est en fait configuré. La prochaine chose à faire est d'implémenter le push et l'abonnement des messages clients.

Deux boîtes à outils, spring-integration-mqtt et org.eclipse.paho.client.mqttv3, sont utilisées ici.

<!--mqtt依赖包-->
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-mqtt</artifactId>
</dependency>
<dependency>
    <groupId>org.eclipse.paho</groupId>
       <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
    <version>1.2.0</version>
</dependency>
复制代码

3. Expéditeur du message

L'envoi de message est relativement simple, principalement appliqué à l'annotation @ServiceActivator, vous devez faire attention à la propriété messageHandler.setAsync, si elle est définie sur false, elle peut se bloquer lorsque le mode asynchrone est désactivé pour envoyer un message.

@Configuration
public class IotMqttProducerConfig {

    @Autowired
    private MqttConfig mqttConfig;

    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setServerURIs(mqttConfig.getServers());
        return factory;
    }

    @Bean
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }

    @Bean
    @ServiceActivator(inputChannel = "iotMqttInputChannel")
    public MessageHandler mqttOutbound() {
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(mqttConfig.getServerClientId(), mqttClientFactory());
        messageHandler.setAsync(false);
        messageHandler.setDefaultTopic(mqttConfig.getDefaultTopic());
        return messageHandler;
    }
}
复制代码

Lorsque MQTT fournit une API pour l'envoi de messages en externe, il doit utiliser l'annotation @MessagingGateway pour fournir un proxy de passerelle de messages. Le paramètre defaultRequestChannel spécifie le canal lié à l'envoi des messages.

Trois types d'interfaces API peuvent être implémentées: la charge utile est le message envoyé, le sujet est le sujet du message envoyé et la qualité du message qos.

@MessagingGateway(defaultRequestChannel = "iotMqttInputChannel")
public interface IotMqttGateway {

    // 向默认的 topic 发送消息
    void sendMessage2Mqtt(String payload);
    // 向指定的 topic 发送消息
    void sendMessage2Mqtt(String payload,@Header(MqttHeaders.TOPIC) String topic);
    // 向指定的 topic 发送消息,并指定服务质量参数
    void sendMessage2Mqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
}

复制代码

4. Abonnement aux actualités

L'abonnement aux messages est essentiellement similaire à la surveillance des messages MQ que nous utilisons habituellement. L'annotation @ServiceActivator indique que la méthode actuelle est utilisée pour traiter les messages MQTT et le paramètre inputChannel spécifie le canal de réception des messages.

/**
 * @Author: xiaofu
 * @Description: 消息订阅配置
 * @date 2020/6/8 18:24
 */
@Configuration
public class IotMqttSubscriberConfig {

    @Autowired
    private MqttConfig mqttConfig;

    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setServerURIs(mqttConfig.getServers());
        return factory;
    }

    @Bean
    public MessageChannel iotMqttInputChannel() {
        return new DirectChannel();
    }

    @Bean
    public MessageProducer inbound() {
        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(mqttConfig.getClientId(), mqttClientFactory(), mqttConfig.getDefaultTopic());
        adapter.setCompletionTimeout(5000);
        adapter.setConverter(new DefaultPahoMessageConverter());
        adapter.setQos(1);
        adapter.setOutputChannel(iotMqttInputChannel());
        return adapter;
    }

    /**
     * @author xiaofu
     * @description 消息订阅
     * @date 2020/6/8 18:20
     */
    @Bean
    @ServiceActivator(inputChannel = "iotMqttInputChannel")
    public MessageHandler handlerTest() {

        return message -> {
            try {
                String string = message.getPayload().toString();
                System.out.println("接收到消息:" + string);
            } catch (MessagingException ex) {
                //logger.info(ex.getMessage());
            }
        };
    }
}
复制代码

Six, message de test

Euh ~ Puisque cette racaille n'a aucune connaissance du matériel, pour simuler l'envoi de messages matériels, vous ne pouvez compter que sur un outil. En fait, le côté matériel implémente le protocole MQTT, qui est fondamentalement le même que le précédent, sauf que il est intégré au matériel dans une autre langue.

L'outil de test sélectionné ici est mqttbox, lien de téléchargement: http://workswithweb.com/mqttbox.html

1. Envoi de message de test

Nous utilisons mqttbox pour simuler l'envoi de messages à la rubrique mqtt_test_topic pour voir si l'arrière-plan peut être reçu avec succès.

 

Voyant que l'arrière-plan a réussi à envoyer le message à la rubrique mqtt_test_topic.

2. Abonnement aux messages de test

Utilisez mqttbox pour simuler l'abonnement au sujet mqtt_test_topic, et envoyez un message au sujet mqtt_test_topic en arrière-plan. Ici, j'ai simplement écrit un contrôleur pour appeler l'API pour envoyer le message.

http://127.0.0.1:8080/fun/testMqtt?topic=mqtt_test_topic&message=Je suis un message envoyé depuis l'arrière-plan vers le sujet mqtt_test_topic

 

Examinons le message d'abonnement de mqttbox, nous avons bien reçu le message d'arrière-plan et notre environnement de communication MQTT est maintenant configuré avec succès. Si vous remplacez l'outil mqttbox par un périphérique matériel spécifique, l'ensemble du processus est ce que nous appelons souvent la maison intelligente, mais ce n'est vraiment pas si difficile.

 

Sept, notes d'application

Pour les problèmes rencontrés dans notre environnement de production actuel, partageons ici pour laisser tout le monde monter sur le stand.

clientId doit être unique

Lorsque le client se connecte, il y aura un paramètre clientId, qui doit être unique pour chaque client. Cependant, pendant la phase de développement et de test, le clientId a été directement écrit à mort dans le code, et le service a été déployé dans une seule instance, et aucun problème n'a été exposé.

MqttPahoMessageDrivenChannelAdapter(mqttConfig.getClientId(), mqttClientFactory(), mqttConfig.getDefaultTopic());
复制代码

Cependant, à l'intérieur de l'environnement de production, étant donné que le service est déployé dans un cluster multi-instance, le problème étrange suivant s'est produit en conséquence. Un seul client peut recevoir le message à la fois. Non seulement les autres clients ne peuvent pas consommer le message, mais ils se déconnectent et se reconnectent constamment: connexion perdue: déconnecté; nouvelle tentative ...

 

 

C'est parce que le clientId est le même et que les clients se font concurrence pour la consommation. Enfin, la méthode d'acquisition clientId est remplacée par l'émetteur. Le problème est très bien, donc cet endroit nécessite une attention particulière.

Habituellement, le programme fonctionne bien dans l'environnement de développement, mais il existe de nombreux problèmes dans l'environnement de production, dont beaucoup sont causés par différentes méthodes de déploiement de services. Par conséquent, il est nécessaire d'en savoir plus distribué.

8. Autre middleware

MQTT est juste un protocole. Il existe de nombreux produits middleware de messagerie qui prennent en charge le protocole MQTT, et ce qui suit n'est qu'une partie d'entre eux.

  • Mosquitto
  • Eclipse Paho
  • RabbitMQ
  • Apache ActiveMQ
  • HiveMQ
  • JoramMQ
  • ThingMQ
  • VerneMQ
  • Apache Apollo
  • emqttd Xively
  • IBM Websphere .....

Pour résumer

C'est aussi la première fois que je fais des projets liés au matériel. J'ai senti que la maison intelligente était si grande quand j'en ai entendu parler auparavant, mais en fait, après avoir commencé à la développer, j'ai constaté que la technologie évolue constamment, et c'est juste une autre façon de l'utiliser.

Donnez l'adresse github de la démo du projet à deux mains: https://github.com/chengxy-nds/springboot-rabbitmq-mqtt.git , les amis intéressés peuvent télécharger et exécuter, c'est très simple à mettre en œuvre.

Je suppose que tu aimes

Origine blog.csdn.net/z69183787/article/details/110124359
conseillé
Classement