MQTT: mudanças entre as edições

De Wiki Cursos IFPR Foz
Ir para navegaçãoIr para pesquisar
 
(202 revisões intermediárias por 2 usuários não estão sendo mostradas)
Linha 7: Linha 7:
*Site: [https://www.hivemq.com/mqtt-essentials/  MQTT Essentials] <ref name=MQTT_Essentials> MQTT Essentials: The Ultimate Kickstart For MQTT Beginners, https://www.hivemq.com/mqtt-essentials/.</ref>.
*Site: [https://www.hivemq.com/mqtt-essentials/  MQTT Essentials] <ref name=MQTT_Essentials> MQTT Essentials: The Ultimate Kickstart For MQTT Beginners, https://www.hivemq.com/mqtt-essentials/.</ref>.
   
   
As aplicações de Internet das Coisas podem envolver abordagens avançadas de '''telemetria''', de forma a poder conectar diferentes '''dispositivos inteligentes''' em atividades de '''sensoreamento''', '''monitoramento''' e '''controle''', além da conexão dos mesmos a '''Internet''' ou a '''sistemas de controle central''' <ref name=LAMPKIN/>.
As aplicações de '''Internet das Coisas''' podem envolver abordagens avançadas de '''telemetria''', de forma a poder conectar diferentes '''dispositivos inteligentes''' em atividades de '''sensoreamento''', '''monitoramento''' e '''controle''', além da conexão dos mesmos a '''Internet''' ou a '''sistemas de controle central''' <ref name=LAMPKIN/>.


==MQTT - Conceitos básicos==
==MQTT - Conceitos básicos==


Conceitos básicos <ref name=LAMPKIN/>:
;Conceitos básicos do MQTT <ref name=LAMPKIN/>:


* '''Publicador/Subscritor''': O '''protocolo MQTT''' é baseado no  '''modelo publisher/subscriber''', isto é, o princípio de '''publicar mensagens''' ('''publisher''') e '''subscrever tópicos''' ('''subscriber''') para receber '''mensagens'''.  
===Modelo Publicador/Subscritor===
O '''protocolo MQTT''' é baseado no  '''modelo publisher/subscriber''', isto é, o princípio de '''publicar mensagens''' ('''publisher''') e '''subscrever tópicos''' ('''subscriber''') para receber '''mensagens'''.  
*:Um '''cliente''' pode '''subscrever tópicos''' e '''receber  mensagens''' de atualizações quando algo for publicado sobre este tópico. Alternativamente, um cliente pode '''publicar mensagens''' relativas a um dado tópico e deixá-la disponível para os assinantes.
*:Um '''cliente''' pode '''subscrever tópicos''' e '''receber  mensagens''' de atualizações quando algo for publicado sobre este tópico. Alternativamente, um cliente pode '''publicar mensagens''' relativas a um dado tópico e deixá-la disponível para os assinantes.


* '''Tópicos e subscrições''': As '''mensagens MQTT''' são publicadas em '''tópicos''' ('''topic'''), que são áreas de interesse.  
O modelo '''publisher/subscriber''' oferece uma alternativa ao modelo '''cliente/servidor'''. No modelo '''cliente/servidor''' o cliente se comunica diretamente o servidor num serviço fim a fim. No modelo '''publisher/subscriber''' o '''publicador''' e o '''subscritor''' não se comunicam diretamente. A comunicação é realizada por um terceiro componente, o '''brocker''' <ref name=MQTT_Essentials/>.
 
===Tópicos e subscrições===
 
As '''mensagens MQTT''' são publicadas em '''tópicos''' ('''topic'''), que são áreas de interesse.  
*:Os clientes, por sua vez, assinam para receber mensagens de uma dada subscrição. As subscrições podem ser explicitas, ou organizadas  hierarquicamente, com o cliente usando '''wildcards''' ('''#''' ou '''+''') para receber mensagens de uma variedade de tópicos.
*:Os clientes, por sua vez, assinam para receber mensagens de uma dada subscrição. As subscrições podem ser explicitas, ou organizadas  hierarquicamente, com o cliente usando '''wildcards''' ('''#''' ou '''+''') para receber mensagens de uma variedade de tópicos.
*:Exemplos:
*:Exemplos:
Linha 23: Linha 28:
*:*'''topic''': /casa/superior/temperatura
*:*'''topic''': /casa/superior/temperatura
*:*'''topic''': /casa/superior/umidade
*:*'''topic''': /casa/superior/umidade
*:*'''wildcard multilevel''': /casa/terreo/# -> sensores do térreo
*:*'''wildcard multilevel''': /casa/# -> todos os sensores da casa (# multinível)
*:*'''wildcard sigle level''': /casa/+ -> casa com térreo e superior, mas não com sensores.
*:*'''wildcard sigle level''': /casa/+/temperatura -> todos os sensores de temperatura (+ somente um nível)


[[Arquivo:MQTT_PublisherSubscriber.png]]
[[Arquivo:MQTT_PublisherSubscriber.png]]


* '''Qualidade de Serviço''': O MQTT define três níveis de Qualidade de Serviço ('''QoS'''):  
===Qualidade de Serviço===
 
O MQTT define três níveis de Qualidade de Serviço ('''QoS'''):  
*:*('''0''') ''best effort'', envia a mensagem uma vez;
*:*('''0''') ''best effort'', envia a mensagem uma vez;
*:*('''1''') envia a mensagem várias vezes;
*:*('''1''') envia a mensagem uma ou mais vezes, podendo haver mensagens duplicadas;
*:*('''2''') assegura o recebimento da mensagem.
*:*('''2''') assegura o recebimento de apenas uma mensagem.


*'''Retem as mensagens''': O servidor MQTT retem as mensagens publicadas no '''brocker''' mesmo depois de enviada a todos os subscritores.
===Reter mensagens===
O servidor MQTT pode '''reter mensagens''' publicadas no '''brocker''', mesmo depois de enviada a todos os subscritores, e tê-las disponível para um novo subscritor deste tópico.


*'''Conexões duráveis e sessões limpas''': Quando um cliente se conecta a um servidor com a ''flag'' '''''clean session = true''''', quando ele se desconectar, todas as subscrições serão removidas. Se a ''flag'' '''''clean session = false''''' (opcional) a conexão é tratada como durável e as subscrições do cliente continuam mesmo após uma desconexão.
===Sessões persistentes===
Permitem a um cliente '''subscritor'''  manter suas subscrições mesmo após uma desconexão. Neste caso, a sessão é tratada como '''persistente''' e as subscrições do cliente continuaram ativas após a próxima conexão.
 
===Último desejo e Testamento===
 
Característica também chamada '''LWT''' ('''''Last Will and Testament''''') do MQTT. Quando um '''cliente''' (publicador ou subscritor) se conecta a um servidor e pode informar que possui um '''último desejo''', isto é, '''mensagens importantes''' que deveriam ser '''publicadas''' em caso de '''desconexão involuntária'''.
 
==MQTT - sensores e atuadores==
 
O MQTT tem aplicabilidade especial para dispositivos para sensoriamento remoto <ref name=LAMPKIN/>.
 
;Sensores: Sensores medem ou monitoram parâmetros do ambiente ou de um sistema e reportam a informação para humanos ou outros dispositivos ou sistemas. Com a ajuda do protocolo MQTT a informação obtida pelos sensores pode ser realizada via rede.
:Múltiplos sensores podem ser posicionados para reportar vários parâmetros e medições em diferentes localizações, dando uma visão completa das condições de operação de um dispositivo ou sistema.
 
;Atuadores: Atuadores são dispositivos que atuam sobre variáveis de um sistema visando alterar seu comportamento.
 
O '''controle''' de um sistema normalmente envolve '''sensores''' monitorando parâmetros do sistema e '''atuadores''' visando corrigir sua operação. A '''ação de controle''' é realizada a partir de um '''algoritmo de controle''', que pode ser executado por controlador central, ou diretamente pelos sensores/atuadores, que, neste caso, devem ter processamento  no próprio sensor/atuador.


*'''''Will''''': Característica também chamada '''LWT'' (''Last Will and Testament'') do MQTT. Quando um cliente se conecta a um servidor e pode informar que possui uma '''will''', isto é, mensagens importantes que deveriam ser publicadas, mesmo em caso de desconexão involuntária. É necessária uma atribuição prévia das mensagens que deveriam ser enviadas, chamado '''testamento'''. Isto é importante para '''sensores de alerta''', que informam o sistema caso percam o contato com a rede.  
O modelo '''publisher/subscriber''' do '''MQTT''' pode ser bastante útil para interligar '''sensores''', '''atuadores''' e '''sistemas de controle''' em diferentes tipos de aplicações, em particular àquelas que envolvem as chamadas tecnologias de Internet das Coisas.


O modelo '''publisher/subscriber''' oferece uma alternativa ao modelo '''cliente/servidor'''. No modelo '''cliente/servidor''' o cliente se comunica diretamente o servidor num serviço fim a fim. No modelo '''publisher/subscriber''' o '''publicador''' e o '''subscritor''' não se comunicam diretamente. A comunicação é realizada por um terceiro componente, o '''brocker''' <ref name=MQTT_Essentials/>.
[[Arquivo:MQTT_SensorAtuador.png]]


==Mensagens do protocolo MQTT <ref name=MQTT_Essentials/>==
==Mensagens do protocolo MQTT <ref name=MQTT_Essentials/>==


O protocolo '''MQTT''' trabalha no topo da pilha de protocolos '''TCP/IP'''.
O protocolo '''MQTT''' trabalha no topo da pilha de protocolos '''TCP/IP''' (''Transmission Control Protocol/Internet Protocol''), que são os principais protocolos da Internet.
 
[[Arquivo:MQTT TCP IP.png]]
[[Arquivo:MQTT TCP IP.png]]


Linha 55: Linha 80:
;brocker MQTT: O '''brocker MQTT''' intermedeia a comunicação entre os clientes publicadores e subscritores.
;brocker MQTT: O '''brocker MQTT''' intermedeia a comunicação entre os clientes publicadores e subscritores.
:O '''brocker''' é o responsável de receber todas as mensagens, determinar quais são os subscritores de cada mensagem, e, em seguida, encaminhar as estas mensagens aos subscritores.
:O '''brocker''' é o responsável de receber todas as mensagens, determinar quais são os subscritores de cada mensagem, e, em seguida, encaminhar as estas mensagens aos subscritores.
;Blibliotecas MQTT: Bibliotecas cliente MQTT estão disponíveis em diferentes linguagens de programação, como Android, Arduino, C, C++, Ct#, Go, iOS, Java, JavaScript, and .NET. Veja lista completa em [https://github.com/mqtt/mqtt.github.io/wiki/libraries MQTT wiki].


===Mensagens de Conexão===
===Mensagens de Conexão===
Linha 60: Linha 87:
Uma '''conexão MQTT''' é sempre entre um '''cliente''' e um '''brocker'''. O '''cliente''' inicia a conexão enviando uma mensagem '''CONNECT''' ao '''brocker''', que responde com a mensagem '''CONNACK'''. A conexão é mantida até que o cliente envie uma mensagem '''DISCONNECT'''.
Uma '''conexão MQTT''' é sempre entre um '''cliente''' e um '''brocker'''. O '''cliente''' inicia a conexão enviando uma mensagem '''CONNECT''' ao '''brocker''', que responde com a mensagem '''CONNACK'''. A conexão é mantida até que o cliente envie uma mensagem '''DISCONNECT'''.


          ---------->
            CONNECT
  '''Cliente'''              '''Brocker'''
  '''Cliente'''              '''Brocker'''
          <----------
    |    ---------->    |
            CONNACK
    |      CONNECT      |
    |    <----------     |
    |      CONNACK       |


;Detalhe das mensagens:
;Detalhe das mensagens:
Linha 71: Linha 98:
  clientId        "cliente1"   
  clientId        "cliente1"   
  cleanSession    true
  cleanSession    true
keepAlive      60
  username        "user1"          (opcional)
  username        "user1"          (opcional)
  passwd          "1234"            (opcional)
  passwd          "1234"            (opcional)
Linha 78: Linha 106:
  lastWillRetain  false            (opcional)
  lastWillRetain  false            (opcional)
  keepAlive      60
  keepAlive      60
O '''clientId''' é um '''identificador único''' do cliente para o '''brocker''' com o qual vai se comunicar.


A ''flag'' '''cleanSession''' informa se a '''sessão''' é '''persistente''' ou não.
A ''flag'' '''cleanSession''' informa se a '''sessão''' é '''persistente''' ou não.
Linha 83: Linha 113:
O '''username''' e '''passwd''' são enviados em '''modo texto''', portanto, é aconselhável utilizá-las juntamente com '''transporte seguro''' através de autenticação de clientes com SSL.
O '''username''' e '''passwd''' são enviados em '''modo texto''', portanto, é aconselhável utilizá-las juntamente com '''transporte seguro''' através de autenticação de clientes com SSL.


Os parâmetros '''lastWill''' são utilizados pelo '''brocker''' para notificar clientes subscritores sobre uma desconexão involuntária deste publicador. Quando um cliente de conecta e informa ao brocker, pela mensasgem CONNECT, o tópico, a QoS e a mensagem lastWill. No caso de uma desconexão involuntária deste cliente o '''brocker''' envia a mensagem lastWill aos clientes subscritores.
Parâmetros '''lastWill''' (ver abaixo).


O parâmetro '''keepAlive''' informa o '''tempo em segundos''' que o '''cliente''' se comunica com o '''brocker''' depois de iniciada a conexão. Para manter a conexão o cliente deve enviar regularmente a mensagem '''PING Request''' ao brocker, que responde com '''PING Replay'''.
Parâmetro '''keepAlive''' (ver abaixo).  


  '''CONNACT'''
  '''CONNACT'''
Linha 101: Linha 131:
*5 Conexão recusada: não autorizado
*5 Conexão recusada: não autorizado


===Mensagem para Publicação e Subscrição===
===Keep Alive===
O '''protocolo MQTT''' é baseado no '''TCP''', o qual transfere mensagens de forma '''confiável''', '''ordenada''' e '''livre de erros'''. Entretanto, eventualmente, podem ocorrer falhas em uma conexão TCP, na qual uma das partes perde a conexão e a outra continua ativa, ficando no estado chamado '''''half-open connection'''''. O '''''keep alive''''' do MQTT visa contornar este problema.
 
Para '''manter a conexão ativa''' entre um '''cliente''' e o '''brocker''', caso não haja publicação, o cliente deve enviar regularmente a mensagem '''PING Request''' ao brocker, que responde com '''PING Response'''. O parâmetro '''keepAlive''' informa o '''tempo em segundos''' que o '''cliente''' pode ficar sem se comunicar com o '''brocker''' depois de iniciada a conexão.


;Publicação:
PINGREQ
 
PINGRESP
 
Se o '''brocker''' não recebe um PINGREQ ou algum outro pacote do cliente, o brocker  '''fecha a conexão''' e envia a mensagem '''lastWill''' e '''testamento''' aos subscritores (caso este cliente tenha especificado uma '''LWT''').
 
===Último desejo e Testamento===
 
Característica também chamada '''LWT''' ('''''Last Will and Testament''''') do MQTT. É utilizado pelo '''brocker''' para notificar clientes subscritores sobre uma '''desconexão involuntária''' de um cliente.
 
Quando um '''cliente''' (publicador ou subscritor) se conecta a um servidor e pode informar que possui mensagens '''lastWill''', isto é, '''mensagens importantes''' que deveriam ser '''publicadas''', mesmo em caso de '''desconexão involuntária'''.
 
Para fazer a atribuição prévia das mensagens '''lastWill''', chamadas '''testamento''', utiliza-se os parâmetros '''lastWill''' na mensagem CONNECT.
 
;Exemplo de aplicação <ref name=MQTT_Essentials> MQTT Essentials: The Ultimate Kickstart For MQTT Beginners, https://www.hivemq.com/mqtt-essentials/.</ref>: Informar ao sistema quando um '''cliente''' está fora de operação, por exemplo, um '''sensor''' que monitora um '''tópico crítico''' do sistema.
:Passos:
:#O '''cliente''' se '''conecta''' ao '''brocker''' e informa uma '''''lastWill''''', por exemplo: '''tópico = ''sensor/status''''', '''mensagem = ''off_line''''' e seta ''flag'' '''reter mensagem''';
:#O '''cliente''' se '''conecta''' e '''publica''' para o mesmo '''tópico''' nova '''mensagem = ''on_line''''' e seta ''flag'' '''reter mensagem''';
:#Enquanto o '''cliente''' estiver '''conectado''', novos '''subscritores''' receberão a '''mensagem = ''on_line''''' para o '''tópico = ''sensor/status''''';
:#Caso o '''cliente''' se '''desconecte involuntariamente''' (sem a mensagem DISCONNECT) a mensagem '''''lastWill''''' será publicada e todos os subscritores receberão a '''mensagem = ''off_line''''' para o '''tópico = ''sensor/status'''''.
 
===Mensagem para Publicação===


O '''cliente''' '''publica''' mensagens assim que estabelece a conexão com o '''brocker'''. Cada '''mensagem''' contem um '''tópico''', que é utilizado para encaminhar a mensagem aos '''clientes''' '''subscritores'''.
O '''cliente''' '''publica''' mensagens assim que estabelece a conexão com o '''brocker'''. Cada '''mensagem''' contem um '''tópico''', que é utilizado para encaminhar a mensagem aos '''clientes''' '''subscritores'''.
Linha 109: Linha 163:
A mensagem de publicação é utilizada também pelo '''brocker''' para encaminhar as mensagens publicadas aos subscritores.
A mensagem de publicação é utilizada também pelo '''brocker''' para encaminhar as mensagens publicadas aos subscritores.


[[Arquivo:MQTT_Publisher.png]]
Mensagem de publicação:
  '''PUBLISH'''
  '''PUBLISH'''
  packetId    0
  packetId    0
  topicName  "sensor/temperatura"
  topicName  "sensor/temperatura"
  qos        0
  qos        0
  retainFlag  true
  retainFlag  false
  payload    "25,0"
  payload    "25,0"
  dupFlag    false
  dupFlag    false


:O parâmetro '''retainFlag''' define quando a mensagem deve ser salva no '''brocker''' como último valor bom para este tópico.
:O parâmetro '''packetId''' é um '''identificador único para a mensagem''' e é utilizado para retransmitir mensagens com '''QoS diferente de 0'''. A biblioteca do cliente e/ou brocker é responsável por gerenciar os identificadores.


:O parâmetro '''packetId''' é um '''identificador único para a mensagem''' e é utilizado para retransmitir mensagens com '''QoS diferente de 0'''.
:O '''dupFlag''' indica que a mensagem é uma duplicata sendo retransmitida para um cliente que não enviou um reconhecimento da anterior. É utilizado para retransmitir mensagens com '''QoS diferente de 0'''.


:O '''dupFlag''' indica que a mensagem é uma duplicata sendo retransmitida para um cliente que não enviou um reconhecimento da anterior. É utilizado para retransmitir mensagens com '''QoS diferente de 0'''.
:O parâmetro '''retainFlag''' define quando o '''brocker''' deve '''reter a mensagem'''  como '''último valor adequado''' para este tópico. 
 
===Reter mensagem===
 
A característica de '''reter mensagem''' permite ao '''brocker'''  dispor do  '''último valor adequado''' para este tópico ('''''last known good value'''''). Desta forma, caso haja novos subscritores para tópicos com mensagens retidas, eles receberão imediatamente as mensagens disponíveis. As '''mensagens retidas''' eliminam a espera por atualizações do cliente para o tópico assinado.
 
===Publicação com Qualidade de Serviço (QoS)===
 
O '''protocolo MQTT''' define três níveis de '''Qualidade de Serviço''' ('''QoS'''):
*('''0''') ''best effort'', envia a mensagem uma vez;
*('''1''') envia a mensagem pelo menos uma vez, mas podem haver mensagens duplicadas, e aguarda confirmação de recebimento;
*('''2''') assegura o recebimento uma única mensagem e da confirmação do recebimento.
 
No MQTT a '''QoS''' deve considerar os dois lados da entrega da mensagem:
#A comunicação entre o '''cliente publicador''' e o '''brocker''';
#A comunicação entre o '''brocker''' e os '''clientes subscritores'''.
A '''QoS''' é considerada separadamente. O '''cliente publicador''' define a '''QoS''' quando '''publica''' no '''brocker'''. O '''brocker''', por sua vez, encaminha a mensagem ao '''cliente subscritor''' de acordo com a '''QoS''' definida no momento da '''subscrição'''. Caso a subscrição tenha QoS maior que o que foi publicado, utiliza-se a menor QoS.
 
;QoS = 0: '''Serviço ''best-effort''''', sem garantia de entrega da mensagem.
 
'''Emissor                  Receptor'''  Ação
    |    -------------->    |      -Publica a mensagem aos subscritores
    |    PUBLISH QoS=0      |
 
;QoS = 1: A '''mensagem é enviada pelo menos uma vez''' ao receptor. O emissor armazena a mensagem até receber um reconhecimento do receptor com a mensagem PUBACK. O PUBACK utiliza o '''packetId''' da mensagem publicada para reconhecer a mensagem. Caso o emissor não receba reconhecimento num tempo apropriado a mensagem é reenviada com  '''dupFlag = true'''. Se o receptor recebe uma mensagem duplicada ele responde com PUBACK e reencaminha a mensagem aos subscritores. Note que os subscritores também podem receber mensagens duplicadas.
 
:Cenário 1: Uma mensagem enviada:
'''Emissor                  Receptor'''  Ação
    |    -------------->    |      -Armazena a mensagem na base de dados
    |    PUBLISH QoS=1      |      -Publica a mensagem aos subscritores
    |    <--------------    |
    |        PUBACK          |
 
:Cenário 2: Mais de uma mensagem enviada:
'''Emissor                  Receptor'''  Ação
    |    -------------->    |      -Armazena a mensagem na base de dados
    |    PUBLISH QoS=1      |      -Publica a mensagem aos subscritores
    |          X--------    |
    |        PUBACK          |
    |    -------------->    |      -Atualiza base de dados
    |    PUBLISH QoS=1      |      -Publica a mensagem aos subscritores
    |    <--------------    |
    |        PUBACK          |
 
 
;QoS = 2: É a '''maior QoS''' do MQTT. '''Garante a entrega de apenas uma mensagem''' aos subscritores . O protocolo utiliza um '''acordo em quatro vias''' entre o emissor e o receptor.
:O QoS=2 deve ser utilizado somente se não forem desejadas mensagens duplicadas.


[[Arquivo:MQTT_Publisher.png]]
'''Emissor                  Receptor'''  Ação
    |    -------------->    |      -Armazena e bloqueia a mensagem na base de dados
    |    PUBLISH QoS=2      |      (se houver mensagens duplicadas atualiza base de dados)
    |    <--------------    |     
    |        PUBREC          |
    |    -------------->    |      -Publica a mensagem aos subscritores
    |        PUBREL          |     
    |    <--------------    |
    |        PUBCOMP        |
:A mensagem é enviada pelo emissor com PUBLISH. Caso o receptor receba a mensagem ele reconhece com PUBREC e deixa a mensagem bloqueada no servidor. Se o emissor não recebe o PUBREC num tempo apropriado ele envia novamente a mensagem com '''dupFlag = true'''. Caso o emissor receba o PUBREC ele tem a garantia que o receptor recebeu a mensagem e envia o PUBREL. Quando o receptor recebe o PUBREL ele responde com PUBCOMP e então encaminha a mensagem aos subscritores. As mensagens trocadas utilizam o '''packetId''' da mensagem publicada para reconhecimento.


;Subscrição:
===Mensagens para e Subscrição===


Para '''receber''' mensagens um '''cliente''' deve '''subscrever''' um dado tópico em um '''brocker''' MQTT.
Para '''receber''' mensagens um '''cliente''' deve '''subscrever''' um dado tópico em um '''brocker''' MQTT.


  '''SUBSCRIBE'''
  '''SUBSCRIBE'''
  packetId             4343 (exemplo)
  packetId     4343 (exemplo)
  List of Subscritions
  List of Subscritions:
  topic        "sensores_ambiente/#"
  qos          0
  topic        "sensor/alerta"
  qos          1


:O '''packetId''' é um '''identificador único''' para a mensagem entre o '''cliente''' e o '''brocker'''. A biblioteca do cliente e/ou brocker é responsável por gerenciar os identificadores.
:O '''packetId''' é um '''identificador único''' para a mensagem entre o '''cliente''' e o '''brocker'''. A biblioteca do cliente e/ou brocker é responsável por gerenciar os identificadores.


:A  '''List of Subscritions''' contém a lista de '''subscrições''' do cliente, cada qual contendo um '''tópico''' e a '''QoS'''. O '''tópico''' pode ser expresso de maneira hierárquica, separados por com '''/''', e também usando '''wildcards''' ('''#''' ou '''+''').
:A  '''List of Subscritions''' contém a lista de '''subscrições''' do cliente, cada qual contendo um '''tópico''' e a '''QoS'''. O '''tópico''' pode ser expresso de forma explícita ou de maneira hierárquica, separados por com '''/''', e também pode utilizar '''wildcards''' ('''#''' ou '''+''').


Cada subscrição é confirmada com SUBACK.
Cada subscrição é confirmada com SUBACK.
  '''SUBACK'''
  '''SUBACK'''
  packetId    4343 (exemplo)     
  packetId    4343 (exemplo)     
returnCode  0
  returnCode  1
  returnCode  1
returnCode  0
  ...
  ...


Linha 147: Linha 263:


:O returnCode informa o código para cada par tópico/QoS como segue:
:O returnCode informa o código para cada par tópico/QoS como segue:
:*0 Sucesso: máximo QoS - 0
:*0 Sucesso: máximo QoS 0
:*1 Sucesso: máximo QoS - 1
:*1 Sucesso: máximo QoS 1
:*2 Sucesso: máximo QoS - 2
:*2 Sucesso: máximo QoS 2
:*128 Falha
:*128 Falha
'''Cliente A              Brocker            Cliente B'''
    |      ----------->    |                    |
    |        SUBSCRITE      |                    |
    |      <-----------    |                    |
    |        SUBACK        |                    |
    |                      |    <----------      |
    |      <-----------    |      PUBLISH        |
    |        PUBLISH        |                    |


Um cliente pode cancelar uma subscrição com UNSUBSCRIBE.
Um cliente pode cancelar uma subscrição com UNSUBSCRIBE.
Linha 167: Linha 292:
:O '''packetId''' é o mesmo identificador da mensagem UNSUBSCRIBE correspondente.
:O '''packetId''' é o mesmo identificador da mensagem UNSUBSCRIBE correspondente.


==MQTT - sensores e atuadores==
===Sessões persistentes===
 
Quando um cliente '''subscritor''' se conecta (CONNECT) a um servidor com a ''flag'' '''''clean session = true''''' após ele se desconectar todas as '''subscrições serão removidas'''.
 
Caso o  cliente '''subscritor''' se conecte com ''flag'' '''''clean session = false''''' (opcional) a sessão é tratada como '''persistente''' e as subscrições do cliente vão continuar após a próxima conexão.
 
As '''sessões persistentes''' eliminam a necessidade do cliente de '''subscrever''' todos os '''tópicos''' a cada vez qua a cada reconexão.
 
Com as '''sessões persistentes''' um '''cliente''' que ficou '''fora de serviço''' por um dado período poderá receber todas as mensagens que ficaram armazenadas no servidor sobre os tópicos que ele subscreve.
 
;O que é armazenado numa sessão persistente:
*mensagens de QoS 1 ou 2 não confirmadas pelo cliente;
*mensagens de QoS 1 ou 2 que o cliente perdeu quando estava '''off-line'''.
<!--
==[[MQTT e Mosquitto: Analise do protocolo com Wireshark]]==
 
Nesta página Wiki estão descritos experimentos visando a '''análise''' do '''protocolo MQTT''' e '''brocker Mosquitto''' utilizando captura de mensagens com '''Wireshark'''.
 
==[[MQTT e Arduino ou ESP]]==
Nesta página Wiki serão descritos experimentos utilizando um '''Arduíno''' e '''ESP8266''' e a '''biblioteca MQTT''' para comunicação com um '''brocker Mosquitto'''.


O MQTT tem aplicabilidade especial para dispositivos para sensoriamento remoto <ref name=LAMPKIN/>.
==MQTT-SN - ''MQTT for Sensor Networks''==


;Sensores: Sensores medem ou monitoram parâmetros do ambiente ou de um sistema e reportam a informação para humanos ou outros dispositivos ou sistemas. Com a ajuda do protocolo MQTT a informação obtida pelos sensores pode ser realizada via rede.
Referências: <ref>Steve’s Internet Guide. Introduction to MQTT-SN (MQTT for Sensor Networks). http://www.steves-internet-guide.com/mqtt-sn/</ref>  <ref>Fábio Souza. MQTT-SN: MQTT para rede de sensores, Embarcados, abril, 2018. https://www.embarcados.com.br/mqtt-sn-mqtt-para-rede-de-sensores/ </ref> <ref NAME=MQTT-SN_Specification>MQTT For Sensor Networks (MQTT-SN). Protocol Specification, Version 1.2, 2013. https://mqtt.org/new/wp-content/uploads/2009/06/MQTT-SN_spec_v1.2.pdf</ref>
:Múltiplos sensores podem ser posicionados para reportar vários parâmetros e medições em diferentes localizações, dando uma visão completa das condições de operação de um dispositivo ou sistema.


;Atuadores: Atuadores são dispositivos que atuam sobre variáveis de um sistema visando alterar seu comportamento.
O protocolo '''MQTT-SN''' foi projetado especificamente para trabalhar com '''sensores''' se comunicando a partir de '''redes sem fio'''.


O '''controle''' de um sistema normalmente envolve '''sensores''' monitorando parâmetros do sistema e '''atuadores''' visando corrigir sua operação. A '''ação de controle''' é realizada a partir de um '''algoritmo de controle''', que pode ser executado por controlador central, ou diretamente pelos sensores/atuadores, que, neste caso, devem ter processamento no próprio sensor/atuador.
Estes sensores têm as seguintes caraterísticas principais:
*Baterias de baixa potência e com capacidades limitadas de processamento e armazenamento
*Limitações no tamanho das mensagens trocadas
*Não estão sempre ativos


O modelo '''publisher/subscriber''' do '''MQTT''' pode ser bastante útil para interligar '''sensores''', '''atuadores''' e '''sistemas de controle''' em diferentes tipos de aplicações, em particular àquelas que envolvem as chamadas tecnologias de Internet das Coisas.
O '''MQTT-SN''' usa o modelo '''Publisher/Subscriber''' e foi projetado para trabalhar da mesma forma que o MQTT.


[[Arquivo:MQTT_SensorAtuador.png]]
===MQTT-SN x MQTT===


==MQTT - Blibliotecas==
As principais diferenças entre o MQTT-SN e MQTT são:
*Tamanho reduzido das mensagens (max 128 bytes);
*Uso do protocolo de transporte '''UDP''' (ao invés do TCP), ou, diretamente sobre outra rede sem fio, como '''Bluetooth''' e '''ZigBee'''.


Bibliotecas cliente MQTT estão disponíveis em diferentes linguagens de programação, como Android, Arduino, C, C++, Ct#, Go, iOS, Java, JavaScript, and .NET. Veja lista completa em [https://github.com/mqtt/mqtt.github.io/wiki/libraries MQTT wiki].
Outras diferenças:
*Mensagem CONNECT simplificada, com duas mensagens especiais para uso com ''lastWill'', caso exista.
*Nomes de tópicos pequenos (2 bytes) e pré definidos com registro no ''gateway''.
*Processo de descoberta para os clientes encontrarem o ''gateway''.
*Procedimento de ''keep alive'' para clientes que não permanecem sempre ativos.


==[https://mosquitto.org/ Mosquitto]==
===Arquitetura===


Mosquitto é um Brocker MQTT ''open source'', que pode ser utilizado desde computadores de placa única até servidores.
Conta com três componentes:
#'''MQTT-SN client'''
#'''MQTT-SN Gateway'''
#'''MQTT-SN forwarder'''
Não há o brocker como no MQTT.


O Mosquitto implementa o modelo '''publilsher/subscriber''' e pode ser utilizado em aplicações de '''Internet das Coisas''', as quais fazem uso de sensores de baixa potência, atuadores, dispositivos móveis, microcontroladores e outros dispositivos programáveis.
[[Arquivo:MQTT-SN-architecture.jpg|500px]]


O Mosquitto oferece comandos de linha como '''mosquitto_pub''' e '''mosquitto_sub''' para publicar e subscrever no '''brocker''', respectivamente, além de bibliotecas em C para implementação de cliente MQTT.
Um '''MQTT-SN client''' se comunica com um '''brocker MQTT''' através de um '''MQTT-SN Gateway'''. O  '''MQTT-SN Gateway''' pode ou não estar integrado a um '''brocker MQTT'''. Se não estiver integrado o ''gateway'' faz a tradução das mensagens do protocolo MQTT-SN para MQTT.


;Instalação no Ubuntu:
Um '''MQTT-SN client''' pode também se comunicar com um '''MQTT-SN Gateway''' através de um '''MQTT-SN forwarder''' caso o cliente não esteja conectado a mesma rede do gateway.
sudo apt-get update
sudo apt-get mosquitto
sudo apt-get install mosquitto-clients


Iniciar o Mosquitto:
;Tipos de MQTT-SN Gateway: Há dois tipos de ''gateways'':
  mosquitto -v (verbose: mostra ações realizadas a cada mensagens publicada/subscrita)
*''Gateways'' Transparentes: Cada comunicação de um '''MQTT-SN client''' com o '''MQTT-SN Gateway''' tem sua corresponde na comunicação com o '''brocker MQTT'''
*''Gateways'' Agregadores: O '''MQTT-SN Gateway''' pode agregar vários '''MQTT-SN client''' e decide qual dado será encaminhado ao '''brocker MQTT'''.


;Porta TCP: O Mosquitto de escuta por padrão na '''porta TCP''' '''1883''':
===Detalhe de algumas mensagens <ref NAME=MQTT-SN_Specification/>===
;Conexão: Na conexão, caso a ''flag'' indique que há '''lastWill''', o gateway solicita o tópico e a mensagem correspondente:
Cliente              Gateway
    |    ---------- >      |
    | CONNECT (flags,...)  |
    |    <----------      |
    |    WILLTOPICREC      |
    |    ---------- >      |
    |      WILLTOPIC      |
    |    <----------      |
    |    WILLMSGREC      |
    |    ---------- >      |
    |      WILLMSG        |
    |    <----------      |
    |      CONNACK        |


;Teste do Mosquitto:
:As informações do '''lastWill''' podem ser atualizadas a qualquer tempo com as mensagens WILLTOPICUPD e WILLMSGUPD.


Use um terminal para '''subscrever''' um '''tópico''':
;Registro de nome de um tópico: Devido a limitação no tamanho das mensagens, o nome do tópico não é publicado junto com a mensagem. Portanto, é necessário que o cliente '''registre o nome do tópico''' no gateway, com a mensagem REGISTER, que é reconhecida com REGACK e retorno de um '''topicId''' (2 bytes), usado na '''publicação''' de mensagens.
mosquitto_sub -t "teste"
-->
Use outro terminal para '''publicar''' uma '''mensagem''' em um '''tópico''':
mosquitto_pub -m "Mensagem" -t "teste"
Usuários e senhas podem ser configurados para uso no Mosquito, ver <ref>[https://medium.com/tht-things-hackers-team/instalar-mqtt-broker-no-linux-debian-ubuntu-f8861da70ef6 Fernando Veiga. Instalar MQTT-Broker no Linux, Things Hackers Team, 2018.]</ref> <ref>[https://fazbe.github.io/Instalando-testando-e-conhecendo-o-MQTT-no-Ubuntu/ Faz-B. Instalando, testando e conhecendo o MQTT no Ubuntu, 2017.] </ref>.


==Referências==
==Referências==
Linha 217: Linha 382:
[[Categoria:IoT]]
[[Categoria:IoT]]


[[Usuário:Evandro.cantu|Evandro.cantu]] ([[Usuário Discussão:Evandro.cantu|discussão]]) 11h27min de 25 de março de 2020 (-03)
[[Usuário:Evandro.cantu|Evandro.cantu]] ([[Usuário Discussão:Evandro.cantu|discussão]]) 16h24min de 13 de abril de 2020 (-03)

Edição atual tal como às 19h32min de 28 de janeiro de 2022

MQTT - Message Queue Telemetry Transport

MQTT (Message Queue Telemetry Transport) é um protocolo de mensagens para sensores e pequenos dispositivos móveis, baseado no modelo publicador/subscritor, ideal para aplicações de Internet das Coisas, em particular para a comunicação máquina a máquina (M2M - Machine to Machine).

Referências:

As aplicações de Internet das Coisas podem envolver abordagens avançadas de telemetria, de forma a poder conectar diferentes dispositivos inteligentes em atividades de sensoreamento, monitoramento e controle, além da conexão dos mesmos a Internet ou a sistemas de controle central [1].

MQTT - Conceitos básicos

Conceitos básicos do MQTT [1]

Modelo Publicador/Subscritor

O protocolo MQTT é baseado no modelo publisher/subscriber, isto é, o princípio de publicar mensagens (publisher) e subscrever tópicos (subscriber) para receber mensagens.

  • Um cliente pode subscrever tópicos e receber mensagens de atualizações quando algo for publicado sobre este tópico. Alternativamente, um cliente pode publicar mensagens relativas a um dado tópico e deixá-la disponível para os assinantes.

O modelo publisher/subscriber oferece uma alternativa ao modelo cliente/servidor. No modelo cliente/servidor o cliente se comunica diretamente o servidor num serviço fim a fim. No modelo publisher/subscriber o publicador e o subscritor não se comunicam diretamente. A comunicação é realizada por um terceiro componente, o brocker [2].

Tópicos e subscrições

As mensagens MQTT são publicadas em tópicos (topic), que são áreas de interesse.

  • Os clientes, por sua vez, assinam para receber mensagens de uma dada subscrição. As subscrições podem ser explicitas, ou organizadas hierarquicamente, com o cliente usando wildcards (# ou +) para receber mensagens de uma variedade de tópicos.
    Exemplos:
    • topic: /casa/terreo/temperatura
    • topic: /casa/terreo/umidade
    • topic: /casa/superior/temperatura
    • topic: /casa/superior/umidade
    • wildcard multilevel: /casa/# -> todos os sensores da casa (# multinível)
    • wildcard sigle level: /casa/+/temperatura -> todos os sensores de temperatura (+ somente um nível)

Qualidade de Serviço

O MQTT define três níveis de Qualidade de Serviço (QoS):

    • (0) best effort, envia a mensagem uma vez;
    • (1) envia a mensagem uma ou mais vezes, podendo haver mensagens duplicadas;
    • (2) assegura o recebimento de apenas uma mensagem.

Reter mensagens

O servidor MQTT pode reter mensagens publicadas no brocker, mesmo depois de enviada a todos os subscritores, e tê-las disponível para um novo subscritor deste tópico.

Sessões persistentes

Permitem a um cliente subscritor manter suas subscrições mesmo após uma desconexão. Neste caso, a sessão é tratada como persistente e as subscrições do cliente continuaram ativas após a próxima conexão.

Último desejo e Testamento

Característica também chamada LWT (Last Will and Testament) do MQTT. Quando um cliente (publicador ou subscritor) se conecta a um servidor e pode informar que possui um último desejo, isto é, mensagens importantes que deveriam ser publicadas em caso de desconexão involuntária.

MQTT - sensores e atuadores

O MQTT tem aplicabilidade especial para dispositivos para sensoriamento remoto [1].

Sensores
Sensores medem ou monitoram parâmetros do ambiente ou de um sistema e reportam a informação para humanos ou outros dispositivos ou sistemas. Com a ajuda do protocolo MQTT a informação obtida pelos sensores pode ser realizada via rede.
Múltiplos sensores podem ser posicionados para reportar vários parâmetros e medições em diferentes localizações, dando uma visão completa das condições de operação de um dispositivo ou sistema.
Atuadores
Atuadores são dispositivos que atuam sobre variáveis de um sistema visando alterar seu comportamento.

O controle de um sistema normalmente envolve sensores monitorando parâmetros do sistema e atuadores visando corrigir sua operação. A ação de controle é realizada a partir de um algoritmo de controle, que pode ser executado por controlador central, ou diretamente pelos sensores/atuadores, que, neste caso, devem ter processamento no próprio sensor/atuador.

O modelo publisher/subscriber do MQTT pode ser bastante útil para interligar sensores, atuadores e sistemas de controle em diferentes tipos de aplicações, em particular àquelas que envolvem as chamadas tecnologias de Internet das Coisas.

Mensagens do protocolo MQTT [2]

O protocolo MQTT trabalha no topo da pilha de protocolos TCP/IP (Transmission Control Protocol/Internet Protocol), que são os principais protocolos da Internet.

O modelo publisher/subscriber do MQTT desacopla a mensagem enviada pelo cliente publicador (publisher) do cliente subscritor (subscriber).

O MQTT usa tópicos para determinar quais mensagens vão ser encaminhadas a cada subscriber.

Cliente MQTT
Tanto o publisher quanto o subscriber são clientes MQTT.
Um cliente MQTT é qualquer dispositivo que rode a biblioteca MQTT, desde um microcontrolador até um servidor de grande porte.
brocker MQTT
O brocker MQTT intermedeia a comunicação entre os clientes publicadores e subscritores.
O brocker é o responsável de receber todas as mensagens, determinar quais são os subscritores de cada mensagem, e, em seguida, encaminhar as estas mensagens aos subscritores.
Blibliotecas MQTT
Bibliotecas cliente MQTT estão disponíveis em diferentes linguagens de programação, como Android, Arduino, C, C++, Ct#, Go, iOS, Java, JavaScript, and .NET. Veja lista completa em MQTT wiki.

Mensagens de Conexão

Uma conexão MQTT é sempre entre um cliente e um brocker. O cliente inicia a conexão enviando uma mensagem CONNECT ao brocker, que responde com a mensagem CONNACK. A conexão é mantida até que o cliente envie uma mensagem DISCONNECT.

Cliente              Brocker
   |    ---------->     |
   |      CONNECT       |
   |    <----------     |
   |      CONNACK       |
Detalhe das mensagens
CONNECT
clientId        "cliente1"  
cleanSession    true
keepAlive       60
username        "user1"           (opcional)
passwd          "1234"            (opcional)
lastWillTopic   "topic1/will"     (opcional)
lastWillQoS     2                 (opcional)
lastWillMessage "unexpected exit" (opcional)
lastWillRetain  false             (opcional)
keepAlive       60

O clientId é um identificador único do cliente para o brocker com o qual vai se comunicar.

A flag cleanSession informa se a sessão é persistente ou não.

O username e passwd são enviados em modo texto, portanto, é aconselhável utilizá-las juntamente com transporte seguro através de autenticação de clientes com SSL.

Parâmetros lastWill (ver abaixo).

Parâmetro keepAlive (ver abaixo).

CONNACT
sessionPresent  false
returnCode      0

O parâmetro sessionPresent informa ao cliente se o brocker já tem uma conexão persistente anterior com este cliente.

O parâmetro returnCode é o retorno com o estado da conexão, que pode ser:

  • 0 Conexão aceita
  • 1 Conexão recusada: versão inválida
  • 2 Conexão recusada: userId rejeitada
  • 3 Conexão recusada: servidor não disponível
  • 4 Conexão recusada: username ou passwd inválida
  • 5 Conexão recusada: não autorizado

Keep Alive

O protocolo MQTT é baseado no TCP, o qual transfere mensagens de forma confiável, ordenada e livre de erros. Entretanto, eventualmente, podem ocorrer falhas em uma conexão TCP, na qual uma das partes perde a conexão e a outra continua ativa, ficando no estado chamado half-open connection. O keep alive do MQTT visa contornar este problema.

Para manter a conexão ativa entre um cliente e o brocker, caso não haja publicação, o cliente deve enviar regularmente a mensagem PING Request ao brocker, que responde com PING Response. O parâmetro keepAlive informa o tempo em segundos que o cliente pode ficar sem se comunicar com o brocker depois de iniciada a conexão.

PINGREQ
PINGRESP

Se o brocker não recebe um PINGREQ ou algum outro pacote do cliente, o brocker fecha a conexão e envia a mensagem lastWill e testamento aos subscritores (caso este cliente tenha especificado uma LWT).

Último desejo e Testamento

Característica também chamada LWT (Last Will and Testament) do MQTT. É utilizado pelo brocker para notificar clientes subscritores sobre uma desconexão involuntária de um cliente.

Quando um cliente (publicador ou subscritor) se conecta a um servidor e pode informar que possui mensagens lastWill, isto é, mensagens importantes que deveriam ser publicadas, mesmo em caso de desconexão involuntária.

Para fazer a atribuição prévia das mensagens lastWill, chamadas testamento, utiliza-se os parâmetros lastWill na mensagem CONNECT.

Exemplo de aplicação [2]
Informar ao sistema quando um cliente está fora de operação, por exemplo, um sensor que monitora um tópico crítico do sistema.
Passos:
  1. O cliente se conecta ao brocker e informa uma lastWill, por exemplo: tópico = sensor/status, mensagem = off_line e seta flag reter mensagem;
  2. O cliente se conecta e publica para o mesmo tópico nova mensagem = on_line e seta flag reter mensagem;
  3. Enquanto o cliente estiver conectado, novos subscritores receberão a mensagem = on_line para o tópico = sensor/status;
  4. Caso o cliente se desconecte involuntariamente (sem a mensagem DISCONNECT) a mensagem lastWill será publicada e todos os subscritores receberão a mensagem = off_line para o tópico = sensor/status.

Mensagem para Publicação

O cliente publica mensagens assim que estabelece a conexão com o brocker. Cada mensagem contem um tópico, que é utilizado para encaminhar a mensagem aos clientes subscritores.

A mensagem de publicação é utilizada também pelo brocker para encaminhar as mensagens publicadas aos subscritores.

Mensagem de publicação:

PUBLISH
packetId    0
topicName   "sensor/temperatura"
qos         0
retainFlag  false
payload     "25,0"
dupFlag     false
O parâmetro packetId é um identificador único para a mensagem e é utilizado para retransmitir mensagens com QoS diferente de 0. A biblioteca do cliente e/ou brocker é responsável por gerenciar os identificadores.
O dupFlag indica que a mensagem é uma duplicata sendo retransmitida para um cliente que não enviou um reconhecimento da anterior. É utilizado para retransmitir mensagens com QoS diferente de 0.
O parâmetro retainFlag define quando o brocker deve reter a mensagem como último valor adequado para este tópico.

Reter mensagem

A característica de reter mensagem permite ao brocker dispor do último valor adequado para este tópico (last known good value). Desta forma, caso haja novos subscritores para tópicos com mensagens retidas, eles receberão imediatamente as mensagens disponíveis. As mensagens retidas eliminam a espera por atualizações do cliente para o tópico assinado.

Publicação com Qualidade de Serviço (QoS)

O protocolo MQTT define três níveis de Qualidade de Serviço (QoS):

  • (0) best effort, envia a mensagem uma vez;
  • (1) envia a mensagem pelo menos uma vez, mas podem haver mensagens duplicadas, e aguarda confirmação de recebimento;
  • (2) assegura o recebimento uma única mensagem e da confirmação do recebimento.

No MQTT a QoS deve considerar os dois lados da entrega da mensagem:

  1. A comunicação entre o cliente publicador e o brocker;
  2. A comunicação entre o brocker e os clientes subscritores.

A QoS é considerada separadamente. O cliente publicador define a QoS quando publica no brocker. O brocker, por sua vez, encaminha a mensagem ao cliente subscritor de acordo com a QoS definida no momento da subscrição. Caso a subscrição tenha QoS maior que o que foi publicado, utiliza-se a menor QoS.

QoS = 0
Serviço best-effort, sem garantia de entrega da mensagem.
Emissor                  Receptor   Ação
   |    -------------->     |       -Publica a mensagem aos subscritores
   |     PUBLISH QoS=0      |
QoS = 1
A mensagem é enviada pelo menos uma vez ao receptor. O emissor armazena a mensagem até receber um reconhecimento do receptor com a mensagem PUBACK. O PUBACK utiliza o packetId da mensagem publicada para reconhecer a mensagem. Caso o emissor não receba reconhecimento num tempo apropriado a mensagem é reenviada com dupFlag = true. Se o receptor recebe uma mensagem duplicada ele responde com PUBACK e reencaminha a mensagem aos subscritores. Note que os subscritores também podem receber mensagens duplicadas.
Cenário 1: Uma mensagem enviada:
Emissor                  Receptor   Ação
   |    -------------->     |       -Armazena a mensagem na base de dados
   |     PUBLISH QoS=1      |       -Publica a mensagem aos subscritores
   |    <--------------     |
   |        PUBACK          |
Cenário 2: Mais de uma mensagem enviada:
Emissor                  Receptor   Ação
   |    -------------->     |       -Armazena a mensagem na base de dados
   |     PUBLISH QoS=1      |       -Publica a mensagem aos subscritores
   |          X--------     |
   |        PUBACK          |
   |    -------------->     |       -Atualiza base de dados
   |     PUBLISH QoS=1      |       -Publica a mensagem aos subscritores
   |    <--------------     |
   |        PUBACK          |


QoS = 2
É a maior QoS do MQTT. Garante a entrega de apenas uma mensagem aos subscritores . O protocolo utiliza um acordo em quatro vias entre o emissor e o receptor.
O QoS=2 deve ser utilizado somente se não forem desejadas mensagens duplicadas.
Emissor                  Receptor   Ação
   |    -------------->     |       -Armazena e bloqueia a mensagem na base de dados
   |     PUBLISH QoS=2      |       (se houver mensagens duplicadas atualiza base de dados)
   |    <--------------     |       
   |        PUBREC          |
   |    -------------->     |       -Publica a mensagem aos subscritores
   |        PUBREL          |       
   |    <--------------     |
   |        PUBCOMP         |
A mensagem é enviada pelo emissor com PUBLISH. Caso o receptor receba a mensagem ele reconhece com PUBREC e deixa a mensagem bloqueada no servidor. Se o emissor não recebe o PUBREC num tempo apropriado ele envia novamente a mensagem com dupFlag = true. Caso o emissor receba o PUBREC ele tem a garantia que o receptor recebeu a mensagem e envia o PUBREL. Quando o receptor recebe o PUBREL ele responde com PUBCOMP e então encaminha a mensagem aos subscritores. As mensagens trocadas utilizam o packetId da mensagem publicada para reconhecimento.

Mensagens para e Subscrição

Para receber mensagens um cliente deve subscrever um dado tópico em um brocker MQTT.

SUBSCRIBE
packetId      4343 (exemplo)
List of Subscritions:
 topic         "sensores_ambiente/#"
 qos           0
 topic         "sensor/alerta"
 qos           1
O packetId é um identificador único para a mensagem entre o cliente e o brocker. A biblioteca do cliente e/ou brocker é responsável por gerenciar os identificadores.
A List of Subscritions contém a lista de subscrições do cliente, cada qual contendo um tópico e a QoS. O tópico pode ser expresso de forma explícita ou de maneira hierárquica, separados por com /, e também pode utilizar wildcards (# ou +).

Cada subscrição é confirmada com SUBACK.

SUBACK
packetId    4343 (exemplo)    
returnCode  0
returnCode  1
...
O packetId é o mesmo identificador da mensagem SUBSCRIBE correspondente.
O returnCode informa o código para cada par tópico/QoS como segue:
  • 0 Sucesso: máximo QoS 0
  • 1 Sucesso: máximo QoS 1
  • 2 Sucesso: máximo QoS 2
  • 128 Falha
Cliente A               Brocker            Cliente B
   |      ----------->     |                     |
   |        SUBSCRITE      |                     |
   |      <-----------     |                     |
   |         SUBACK        |                     |
   |                       |    <----------      |
   |      <-----------     |      PUBLISH        |
   |        PUBLISH        |                     |

Um cliente pode cancelar uma subscrição com UNSUBSCRIBE.

UNSUBSCRIBE
packetId    4344 (exemplo)   
topic1      "/sensor/temp"
topic2      "/sensor/umid"
...
O packetId é um identificador único para a mensagem entre o cliente e o brocker. A biblioteca do cliente e/ou brocker é responsável por gerenciar os identificadores.

Reconhecimento

UNSUBACK
packetId
O packetId é o mesmo identificador da mensagem UNSUBSCRIBE correspondente.

Sessões persistentes

Quando um cliente subscritor se conecta (CONNECT) a um servidor com a flag clean session = true após ele se desconectar todas as subscrições serão removidas.

Caso o cliente subscritor se conecte com flag clean session = false (opcional) a sessão é tratada como persistente e as subscrições do cliente vão continuar após a próxima conexão.

As sessões persistentes eliminam a necessidade do cliente de subscrever todos os tópicos a cada vez qua a cada reconexão.

Com as sessões persistentes um cliente que ficou fora de serviço por um dado período poderá receber todas as mensagens que ficaram armazenadas no servidor sobre os tópicos que ele subscreve.

O que é armazenado numa sessão persistente
  • mensagens de QoS 1 ou 2 não confirmadas pelo cliente;
  • mensagens de QoS 1 ou 2 que o cliente perdeu quando estava off-line.

Referências

  1. 1,0 1,1 1,2 1,3 Valerie Lampkin; Weng Tat Leong; Leonardo Olivera; Sweta Rawat; Nagesh Subrahmanyam; Rong Xiang. Building Smarter Planet Solutions with MQTT and IBM WebSphere MQ Telemetry, ibm.com/redbooks, 2012.
  2. 2,0 2,1 2,2 2,3 MQTT Essentials: The Ultimate Kickstart For MQTT Beginners, https://www.hivemq.com/mqtt-essentials/.

Evandro.cantu (discussão) 16h24min de 13 de abril de 2020 (-03)