Puntos de conocimiento MQTT

1. Introducción a MQTT

1. Introducción

MQTT (transporte de telemetría de cola de mensajes) es un protocolo de mensajería instantánea desarrollado por IBM. Es un protocolo de mensajería de publicación / suscripción extremadamente ligero diseñado para dispositivos con restricciones de red, ancho de banda bajo y redes de alta latencia y poco confiables. Debido a las características de peso ligero mencionadas anteriormente, es el protocolo de transmisión preferido para la implementación en el hogar inteligente. En comparación con XMPP, es más ligero y ocupa poco ancho de banda.

 MQTT 官 网 : http: //mqtt.org/
 MQTT介绍: http: //www.ibm.com
 MQTT Android github : https: //github.com/eclipse/paho.mqtt.android
 MQTT API : http: // www .eclipse.org / paho / files / javadoc / index.html
 API de Android MQTT: http://www.eclipse.org/paho/files/android-javadoc/index.html

2. Características

a. Debido al uso del modo de mensajes de publicación / suscripción, puede proporcionar publicación de mensajes de uno a muchos
b. Sobrecarga de red ligera y baja
c. Transmisión de mensajes con protección del contenido de carga
d. Hay tres cualidades de publicación de mensajes (Qos) :
qos = 0: "Como máximo una vez", la pérdida o duplicación del mensaje se producirá en este nivel. La publicación de mensajes depende de la red TCP / IP
qos = 1: "Al menos una vez" para garantizar que llegue el mensaje, pero la duplicación de mensajes puede ocurre
qos = 2: "Sólo una vez", para asegurar que el mensaje llegue una vez
e. Mecanismo de notificación, ambas partes serán notificadas cuando ocurra una interrupción anormal

3. Principio

14523188625918865.png

 

El protocolo MQTT tiene tres identidades: editor, intermediario y suscriptor. Tanto el editor como el suscriptor son clientes y el proxy es el servidor. Al mismo tiempo, el editor de mensajes también puede ser suscriptor (para ahorrar memoria y tráfico, editores y los suscriptores generalmente se definirán juntos).
El mensaje transmitido por MQTT se divide en dos partes: tema (tema, que puede entenderse como el tipo de mensaje. Después de que los suscriptores se suscriban, recibirán el contenido del mensaje (carga útil) del tema) y carga útil (carga útil, que puede ser entendido como el contenido del mensaje).

2. Uso general de MQTT

Agregar dependencia

repositorios {     maven {         url "https://repo.eclipse.org/content/repositories/paho-releases/"     } }



dependencias {     compilar 'org.eclipse.paho: org.eclipse.paho.client.mqttv3: 1.1.0'     compilar 'org.eclipse.paho: org.eclipse.paho.android.service: 1.1.0' }


Agregar restricción

    <usa-permiso android: name = "android.permission.INTERNET" />
    <usa-permiso android: name = "android.permission.ACCESS_NETWORK_STATE" />
    <usa-permiso android: name = "android.permission.WAKE_LOCK" / >

Servicio de registro

        <! - Servicio Mqtt ->
        <servicio android: name = "org.eclipse.paho.android.service.MqttService" />
        <servicio android: name = "com.dongyk.service.MQTTService" />

 

QoS (Calidad de servicio) se
refiere a la calidad de servicio de la transmisión de mensajes. Incluye los siguientes niveles:

calidad de servicio Significado específico
QoS0 Distribuir como máximo una vez
QoS1 Significa al menos una vez
QoS2 El delegado distribuye solo una vez

cleanSession El
indicador cleanSession es la definición de si un cliente se preocupa por el estado anterior después de establecer una conexión TCP en el protocolo MQTT. La semántica específica es la siguiente:

cleanSession Significado específico
cierto Conexión no persistente, cuando el cliente vuelve a conectarse, ya no le importan todas las relaciones de suscripción anteriores y los mensajes fuera de línea.
falso Conexión persistente, cuando el cliente se vuelve a conectar, el mensaje sin conexión anterior debe procesarse y la relación de suscripción anterior seguirá teniendo efecto

Los resultados de diferentes combinaciones de QoS y cleanSession se muestran en la siguiente tabla:

Nivel de QoS cleanSession = verdadero cleanSession = falso
QoS0 No hay mensajes sin conexión, los mensajes en línea solo intentan presionar una vez No hay mensajes sin conexión, los mensajes en línea solo intentan presionar una vez
QoS1 Sin mensajes fuera de línea, se garantiza que los mensajes en línea serán accesibles Hay mensajes fuera de línea, se garantiza que todos los mensajes serán accesibles
QoS2 Sin mensajes fuera de línea, se garantiza que los mensajes en línea se publicarán solo una vez Hay mensajes sin conexión, se garantiza que todos los mensajes se enviarán solo una vez

Para el mensaje con QoS> 0, si es una conexión persistente, cuando el cliente está fuera de línea, el mensaje se enviará al corredor. Cuando el cliente esté en línea, mqtt extraerá el mensaje del corredor y lo enviará al cliente. .

 

Suscripción multipunto de cliente Mqtt

El tema de mqtt es un concepto jerárquico. Necesitamos utilizar este punto técnico cuando nos suscribimos a múltiples temas. La
función es introducir jerarquía en el tema. Los niveles se dividen en separadores de nivel de tema, comodines de varios niveles y comodines de un solo nivel
. Una cosa a tener en cuenta es que estos niveles no se pueden usar en la interfaz de publicación para publicar mensajes.
Clasificación de
nivel Separadores de nivel de tema: /
comodines de varios niveles: #
Comodines de un solo nivel: +

El separador de nivel de tema
"/" se utiliza para separar cada nivel del árbol de temas y proporcionar una estructura jerárquica para el espacio de temas. Cuando aparecen dos comodines en un tema, el uso de separadores de nivel de tema es muy importante.
// Asunto Tema1: dividido en tres niveles / prueba / niño / aaa // Tema2: dividido en cuatro niveles / prueba / niño / aaa2 / bbb2
comodín
multicapa comodín multicapa "#" es una coincidencia para cualquier número de niveles en el tema Comodín. Usemos un caso para ilustrar el
Caso 1
Suscríbase a los temas: / test / child / #
Recibiremos mensajes de estos temas:
/ test / child / test / child / aaa / test / child / ccc / test / child / aaa / bbb / prueba / niño / aaa / bbb / ddd

El comodín de varios niveles puede entenderse como un nivel mayor o igual a 0.
Los comodines de varios niveles solo pueden determinar el nivel actual o el siguiente.

Errores comunes y casos de presentación correctos
# // Correcto , todos los temas que no comienzan con / serán recibidos / # // Correcto / prueba / # / niño // Error, # debe ser el último carácter / prueba / # // Correcto / test / child # // Error comodín no válido / test / child / # // Comodín de un
solo nivel satisfactorio comodín de un
solo nivel "+" solo coincide con un nivel del tema
Caso 1
Suscribirse al tema: / test / child / +
Recibiremos estos El mensaje enviado por el sujeto: Nota: No puedo recibir el mensaje enviado por / test / child subject
/ test / child / aaa / test / child / bbb / test / child / ccc
Errores comunes y casos de presentación correctos
+ // Éxito / + / / Éxito / prueba / + / hijo // Éxito, / prueba / + // Éxito / prueba / hijo + // Error comodín no válido / prueba / hijo / + //
Sintaxis y uso del tema de éxito
Cuando construir una aplicación, diseñar el tema Al crear un árbol, debe considerar la siguiente sintaxis y semántica de los nombres de los
temas : el tema tiene al menos un carácter de longitud.
El nombre del sujeto distingue entre mayúsculas y minúsculas. Por ejemplo, CUENTAS y Cuentas son dos temas diferentes.
El nombre del tema puede contener espacios. Por ejemplo, Cuentas por pagar es un tema efectivo.
Comenzar con / producirá un tema diferente. Por ejemplo, / finnace es diferente de Finance. / finance coincide con "+ / +" y / +, pero no coincide con +
No incluya caracteres nulos (Unicode \ x0000) en ningún asunto.
Los siguientes principios se aplican a la construcción y el contenido del
árbol de temas. En el árbol de temas, la longitud está limitada a 64k, pero no hay límite para el número de niveles dentro de este.
Puede haber cualquier número de nodos raíz; es decir, puede haber cualquier número de árboles de temas

 

 

 

 

 

 

 


————————————————

Suscripción de múltiples temas del cliente Mqtt: https://blog.csdn.net/qq_22889431/article/details/105321843

La realización del mensaje fuera de línea mqtt: https://www.jianshu.com/p/e85cdaae65bd

 

mqtt es un protocolo de mensajería de publicación / suscripción extremadamente liviano (diseñado para dispositivos restringidos y redes de bajo ancho de banda, alta latencia o poco confiables), con un tamaño de código pequeño y bajo consumo de energía, adecuado para dispositivos móviles, vehículos Cuando la señal de la red es inestable ( red débil, desconectada, sin red en el túnel, etc.) y la red se restablece más tarde, puede continuar enviando y recibiendo mensajes, y puede recibir los mensajes fuera de línea anteriores. El envío adicional de mensajes fuera de línea también puede ser controlado por el propio servidor de mensajería instantánea, pero si el protocolo Mqtt admite de forma nativa el envío fuera de línea, ¿no significaría que los desarrolladores provinciales lo manejarán por sí mismos? Al mismo tiempo, adhiriéndose a la visión de usar el nuevo en lugar del antiguo, elija decididamente Mqtt5 en lugar de Mqtt3. En comparación con Mqtt3, Mqtt5 tiene muchas actualizaciones, como: código de razón (PUBACK / PUBREC), suscripción compartida, vencimiento de sesión , modo de solicitud / respuesta (ResponseTopic, CorrelationData), Will Delay, etc.
Para la selección de servidor y cliente de Mqtt, consulte el siguiente enlace:
Sitio web oficial de Mqtt Sitio web
chino de
Mqtt Mqtt Lado del servidor
Mqtt Lado del cliente En el
proceso de desarrollo real, el lado del servidor elige Emq, el lado del cliente elige HiveMq, ambos admiten Mqtt5.
Mqtt5 admite varias configuraciones básicas para la recepción de mensajes fuera de línea:
ClientId
CleanStart: false
SessionExpiry
Qos: 2
El indicador de sesión presente en CONNACK
ClientId se utiliza para identificar de forma exclusiva la sesión del usuario.
CleanStart se establece en 0, lo que significa que se crea una sesión persistente. Cuando el cliente se desconecta, la sesión permanece y guarda los mensajes fuera de línea hasta que se agota el tiempo de espera y se cierra la sesión. CleanStart se establece en 1, lo que significa que se crea una nueva sesión temporal. Cuando se desconecta el cliente, la sesión se destruye automáticamente.
SessionExpiry especifica cuánto tiempo se guardará la sesión cuando CleanStart sea 0. Si el cliente no se conecta dentro de un período de tiempo definido por el usuario, puede descartar el estado (por ejemplo, suscripciones y mensajes almacenados en búfer) sin limpiar.
Qos es la calidad de servicio del mensaje. Si desea admitir mensajes fuera de línea, debe suscribirse y publicar. Qos> = 1
sesión presente significa que el identificador de sesión presente se incluye en el resultado de retorno de ConnAck de la conexión al mqtt servidor, que indica si el clientId actual existe La sesión persistente anterior (sesión persistente), si hay una sesión antes (no se vuelva a suscribir al tema en este momento, si se suscribe de nuevo, no se recibirán los mensajes anteriores), la sesión retendrá la relación de suscripción anterior y los mensajes del cliente cuando esté fuera de línea (Qos> = 1), mensajes no sincronizados. El punto clave es explicar el uso de session present. Cuando el cliente se conecta al servidor mqtt y obtiene el identificador isSessionPresent en el connack, si isSessionPresent = true, la sesión ya existe y no hay necesidad de suscribirse al tema repetidamente (la relación de suscripción se ha guardado en la sesión, si repite la suscripción nuevamente, no recibirá los mensajes fuera de línea anteriores), puede procesar mensajes fuera de línea y mensajes nuevos posteriormente a través de la recepción global; si isSessionPresent = false, no hay sesión (o la sesión ha expirado), y debe volver a suscribirse al tema en este momento, y no se han recibido mensajes sin conexión anteriormente, y los mensajes sin conexión solo se pueden obtener a través de otros métodos (por ejemplo, el servicio de sincronización completo de IM servicio de back-end).

Por ejemplo, ClientId = 1, CleanStart = false, SessionExpiry = 3600s, Qos = 2 significa que la sesión con clientId = 1 se designa como una sesión persistente. Los mensajes fuera de línea de 3600s después de que el usuario esté fuera de línea serán guardados por el servidor Mqtt y el tiempo fuera de línea del usuario no excede los 3600s y cuando vuelve a conectarse con ClientId = 1, puede recibir una inserción adicional del mensaje durante el período fuera de línea, y Qos = 2 (exactamente una vez) garantiza que el mensaje solo se recibirá por el cliente una y otra vez.
Tome el código del cliente HiveMq como ejemplo:
Nota: la recepción de mensajes globales de asyncClient.publishes debe colocarse antes del
paquete de llamada al método connect com.mx.mqtt.sys;

import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
import com.hivemq.client.mqtt.datatypes.MqttQos;
import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedContext;
import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedListener;
import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext;
import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener;
import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5ConnAckException;
import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
import com.mx.mqtt.jwt.JwtUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.UnsupportedEncodingException;

/ **
 * emqx - Sesión
 *
 * @Ahthor luohq
 * @Date 2020-04-09
 * /
public class EmqxOfflineClient {

    / **
     * 日志
     * /
    Logger final estático privado logger = LogManager.getLogger (EmqxOfflineClient.class);


    Cadena final estática privada MQTT_JWT_SECRET = "xxxx";
    Cadena final estática privada MQTT_SERVER_HOST = "192.168.xxx.xxx";
    Entero final estático privado MQTT_SERVER_PORT = 1883;
    Cadena final estática privada MQTT_CLIENT_ID = "luohq-offline";
    Cadena final estática pública MQTT_SUB_TOPIC = "luohq / offline";
    público estático final Long SESSION_EXPIRATION = 5 * 60L;


    privado estático booleano isSessionPresent = false;
    cliente privado estático Mqtt5BlockingClient;
    privado estático Mqtt5AsyncClient asyncClient;


    public static void main (String [] args) {         / ** Construir cliente mqtt * /         buildMqtt5Client ();


        / ** Si la sesión no existe, debe suscribirse al tema nuevamente * /
        if (! IsSessionPresent) {             logger.info ("[CLIENT-SUB] Suscribirse al tema:" + MQTT_SUB_TOPIC);             // Suscribirse al tema             asyncClient.subscribeWith ()                     .topicFilter (MQTT_SUB_TOPIC)                     .qos (MqttQos.EXACTLY_ONCE)                     .send ();         }






    }


    public static Mqtt5BlockingClient buildMqtt5Client () {         / ** * bloqueo客户端/         cliente = Mqtt5Client.builder ()                 .identificador (MQTT_CLIENT_ID)                 .serverHost (MQTT_SERVER_HOST)                 .serverPort (MQTT_SERVER_PORT)                 .addConnectedListener (nueva MqttClientConnectedListener () {                     @Override                     public void onConnected (MqttClientConnectedContext context) {                         logger.info ("mqtt onConnected context");                     }                 })                 .addDisconnectedListener (nuevo MqttClientDisconnectedListener () {                     @Override













                    public void onDisconnected (MqttClientDisconnectedContext context) {                         logger.info ("mqtt onDisconnected context");                     }                 })                 // Reconexión automática (reconexión retardada exponencialmente (retardo de inicio 1 s, después de cada tiempo 2 veces, hasta 2 minutos limitado) retardo: 1 s- > 2s -> 4s -> ... -> 2min)                 .automaticReconnectWithDefaultConfig ()                 .buildBlocking ();         asyncClient = client.toAsync ();







        / ** Emqx JWT 认证 * /
        String authJwt = JwtUtils.generateJwt (MQTT_CLIENT_ID, MQTT_JWT_SECRET);
        Mqtt5SimpleAuth auth = Mqtt5SimpleAuth.builder ()
                .nombre de usuario (MQTT_CLIENT_ID)
                .password (authJwt.getBytes ())
                .build ();
        Mqtt5ConnAck connAck = nulo;

 


        / ** Procesamiento global de mensajes (antes de la conexión) * /
        asyncClient.publishes (MqttGlobalPublishFilter.ALL, mqtt5Publish -> {             try {                 byte [] msg = mqtt5Publish.getPayloadAsBytes ();                 String msgStr = new String (mqtt5Publish.getPayload) UTF-8 ");                 logger.info (" [CLIENTE-RECV] "+ msgStr);             } catch (UnsupportedEncodingException e) {                 e.printStackTrace ();             }         });








        / ** Lógica de conexión * /
        try {             connAck = client.connectWith ()                     .simpleAuth (auth)                     / ** cleanSession = false * /                     .cleanStart (false)                     / ** La sesión expira en 7 días * /                     .sessionExpiryInterval (SESSION_EXPIRATION)                     / * * duración de keepalive * /                     //.keepAlive(60)                     .send ();         } catch (Mqtt5ConnAckException e) {             e.printStackTrace ();             connAck = e.getMqttMessage ();         }













        / ** Conexión (conexión normal sin contraseña) * /
        // Mqtt5ConnAck connAck = client.connect ();

        / ** Compruebe si la sesión ya existe antes de * /
        isSessionPresent = connAck.isSessionPresent ();
        if (connAck.isSessionPresent ()) {             logger.info ("la sesión está presente:" + connAck.getSessionExpiryInterval (). OrElse (-1 ));         }

 

        logger.info (connAck.getReasonCode () + ":" + connAck.getReasonString () + ":" + connAck.getResponseInformation ());


        if (connAck.getReasonCode (). isError ()) {             logger.error ("¡La conexión Mqtt5 falló!");             System.exit (-1);         }         return client;     } } La configuración principal anterior: clientId, cleanStart = fasle, sessionExpiry> 0, Qos> = 1, procesamiento de presente de sesión CONNACK, es indispensable y es imposible aceptar mensajes fuera de línea sin una configuración. ———————————————— Declaración de derechos de autor: Este artículo es el artículo original del blogger de CSDN "Luo Xiaocang EX", y sigue el acuerdo de derechos de autor CC 4.0 BY-SA. Adjunte el enlace fuente original para reimpresión y esta declaración. Enlace original: https://blog.csdn.net/luo15242208310/article/details/103971457
















 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Supongo que te gusta

Origin blog.csdn.net/MYBOYER/article/details/107482127
Recomendado
Clasificación