2. Utilizando a API da dojot

Esta seção descreve o passo a passo completo de como criar, alterar, enviar mensagens e conferir dados históricos relativos a um dispositivo. Este tutorial assume que está sendo utilizada a instalação docker-compose e que todos os componentes necessários estão sendo executados corretamente na dojot.

Nota

  • Audiência: desenvolvedores

  • Nível: básico

  • Tempo de leitura: 15 minutos

2.1. Pré-requisitos

Vamos utilizar:

  • curl para acessar as APIs da plataforma dojot;

  • jq para processar o retorno JSON das APIs da plataforma dojot.

  • mosquitto publicar e se subscrever no iotagent-mosca (or iotagent-mqtt) via MQTT.

Em distribuições Linux baseadas em Debian, você pode executar:

sudo apt-get install curl
sudo apt-get install jq
sudo apt-get install mosquitto-clients

2.2. Obtendo um token de acesso

Todas as solicitações devem conter um token de acesso válido. Veja maneiras de obter um token em Obtendo Token de Acesso (Access Token JWT).

Para verificar o token:

echo $JWT

O token (“eyJ0eXAiOiJKV1QiL …”) dentro de `` $ JWT`` deve ser usado em cada solicitação HTTP enviada para dojot em um cabeçalho especial. Essa solicitação seria semelhante a:

curl -X GET http://localhost:8000/device \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiL..."

É importante ressaltar que o token deve estar inteiro no cabeçalho da requisição, não apenas parte dele. No exemplo, somente os primeiros caracteres foram mostrados por questão de simplificação. Todas as demais requisições serão compostas da variável de ambiente chamada bash ${JWT} que contém o token obtido da dojot (mais especificamente do componente de autorização da dojot).

2.3. Criação de dispositivo

A fim de configurar um dispositivo físico na dojot, é necessário criar sua representação na plataforma. O exemplo mostrado aqui é apenas uma parte pequena do que é oferecido pelo componente DeviceManager. Para mais informações sobre esse componente, confira a documentação do DeviceManager.

Primeiramente vamos criar um modelo (template) para o dispositivo, pois todos os dispositivos são baseados em modelos, não esqueça.

curl -X POST http://localhost:8000/template \
-H "Authorization: Bearer ${JWT}" \
-H 'Content-Type:application/json' \
-d ' {
  "label": "Thermometer Template",
  "attrs": [
    {
      "label": "temperature",
      "type": "dynamic",
      "value_type": "float"
    },
    {
      "label": "fan",
      "type": "actuator",
      "value_type": "float"
    }
  ]
}'

Esta requisição deve retornar a seguinte mensagem:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  {
    "result": "ok",
    "template": {
      "created": "2018-01-25T12:30:42.164695+00:00",
      "data_attrs": [
        {
          "template_id": "1",
          "created": "2018-01-25T12:30:42.167126+00:00",
          "label": "temperature",
          "value_type": "float",
          "type": "dynamic",
          "id": 1
        }
      ],
      "label": "Thermometer Template",
      "config_attrs": [],
      "attrs": [
        {
          "template_id": "1",
          "created": "2018-01-25T12:30:42.167126+00:00",
          "label": "temperature",
          "value_type": "float",
          "type": "dynamic",
          "id": 1
        },
        {
          "template_id": "1",
          "created": "2018-01-25T12:30:42.167126+00:00",
          "label": "fan",
          "type": "actuator",
          "value_type": "float",
          "id": 2
        }
      ],
      "id": 1
    }
  }

Note que o template (modelo) ID é 1 (linha 35), caso você já tenha criado algum outro template este ID será diferente.

Para criar um dispositivo baseado nesse modelo (ID 1), envie a seguinte requisição para a dojot:

curl -X POST http://localhost:8000/device \
-H "Authorization: Bearer ${JWT}" \
-H 'Content-Type:application/json' \
-d ' {
  "templates": [
    "1"
  ],
  "label": "device"
}'

A lista de IDs de modelos na linha 6 contém um único ID do modelo configurado até o momento. Para conferir os dispositivos configurados, basta enviar uma requisição do tipo GET para /device:

curl -X GET http://localhost:8000/device -H "Authorization: Bearer ${JWT}"

Que deve retornar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  {
    "pagination": {
      "has_next": false,
      "next_page": null,
      "total": 1,
      "page": 1
    },
    "devices": [
      {
        "templates": [
          1
        ],
        "created": "2018-01-25T12:36:29.353958+00:00",
        "attrs": {
          "1": [
            {
              "template_id": "1",
              "created": "2018-01-25T12:30:42.167126+00:00",
              "label": "temperature",
              "value_type": "float",
              "type": "dynamic",
              "id": 1
            },
            {
              "template_id": "1",
              "created": "2018-01-25T12:30:42.167126+00:00",
              "label": "fan",
              "value_type": "actuator",
              "type": "float",
              "id": 2
           }
          ]
        },
        "id": "0998", # <-- this is the device-id
        "label": "device_0"
      }
    ]
  }

O device id utilizado nos próximos passos deve ser alterado conforme o retornado na criação do device. Na execução acima o id retornado foi 0998 na linha 34. Portanto, todos os lugares nos próximos passos com referencias a 0998 devem ser alterados.

2.4. Enviando mensagens

Até o momento um token de acesso foi obtido, um modelo (template) e um dispositivo (baseado no modelo) foram criados. Em um sistema real, o dispositivo físico publica mensagens para a dojot com todos os seus atributos contendo valores correntes. Nesse tutorial serão publicadas mensagens MQTT montadas “na mão” para a plataforma, emulando um dispositivo físico. Para tal, será utilizado o mosquito_pub e mosquitto_sub do projeto mosquitto.

O formato padrão de mensagem usado pela dojot é um simples “chave-valor” JSON (é possível traduzir qualquer formato para esse esquema utilizando fluxos), como abaixo:

{
  "temperature" : 10.6
}

Atenção

Algumas distribuições Linux, como as baseadas em Debian, têm dois pacotes para mosquitto - um contendo ferramentas para cliente (ou seja, mosquitto_pub e mosquitto_sub para publicar mensagens e se subscrever em tópicos) e outro contendo um broker MQTT também. Neste tutorial, apenas as ferramentas do pacote `mosquitto-clients` em Distribuições Linux baseadas no Debian serão usadas. Verifique se um outro broker MQTT não está em execução antes de iniciar a dojot (executando comandos como ps aux | grep mosquitto) para evitar conflitos de porta.

Por simplicidade, nós não estamos utilizando TLS nos exemplos abaixo. Verifique o artigo Usando MQTT com segurança (TLS) para maiores esclarecimentos sobre sua utilização.

Nota

Para executar mosquitto_pub e` mosquitto_sub` sem usar TLS como nos exemplos abaixo, você precisa definir algumas configurações (ou para como desativar o modo sem TLS). Para obter mais detalhes sobre este tópico, consulte a página Modo inseguro do MQTT (sem TLS).

A partir da versão v0.5.2, você pode escolher entre dois brokers MQTT: Mosca ou VerneMQ. Por padrão, o VerneMQ é utilizado, mas você pode utilizar o Mosca também. Verifique o Guia de instalação para mais informações.

2.4.1. Usando o VerneMQ

Como descrito no Dúvidas Mais Frequentes, existem algumas considerações a respeito dos tópicos MQTT:

  • Você deve adicionar o username que originou a mensagem usando o atributo de mesmo nome do MQTT. Ele deve seguir o seguinte padrão: <tenant>:<device-id>, como admin:efac. Ele deve ser o mesmo que o colocado no tópico.

  • O tópico para publicação deve assumir o padrão <tenant>:<device-id>/attrs (por exemplo: admin:efac/attrs).

  • O tópico de subscrição deve assumir o padrão <tenant>:<device-id>/config (por exemplo: admin:efac/config).

  • Os dados da mensagem MQTT (payload) devem ser um JSON com cada chave sendo um atributo do dispositivo cadastrado na dojot, como:

{ "temperature" : 10.5, "pressure" : 770 }

A requisição deve resultar na seguinte mensagem:

mosquitto_pub -h localhost -p 1883 -u admin:0998 -t admin:0998/attrs -m '{"temperature": 10.6}' -q 1

Se não houver saída (output), a mensagem foi enviada ao broker MQTT.

Repare que estamos enviando a publicação com o parâmetro -q 1. Isto significa que a mensagem usará QoS 1, i.e., é garantido pelo menos um envio da mensagem.

Além disso, você pode enviar uma mensagem de configuração da dojot para o dispositivo. O atributo de destino deve ser do tipo “actuator” ou “atuador”.

Para simular o recebimento da mensagem em um dispositivo, podemos usar o mosquitto_sub:

mosquitto_sub -h localhost -p 1883 -u admin:0998 -t admin:0998/config -q 1

Disparando o envio da mensagem da dojot para o dispositivo.

curl -X PUT \
    http://localhost:8000/device/0998/actuate \
    -H "Authorization: Bearer ${JWT}" \
    -H 'Content-Type:application/json' \
    -d '{"attrs": {"fan" : 100}}'

2.4.2. Usando o Mosca (legado)

Como descrito no Dúvidas Mais Frequentes, existem algumas considerações a respeito dos tópicos MQTT:

  • Pode-se configurar o ID do dispositivo origem da mensagem utilizando o parâmetro MQTT client-id. Deve seguir o seguinte padrão: <service>:<deviceid>, como em admin:efac.

  • Se algo o impossibilita de realizar isto, então o dispositivo deve configurar seu ID no tópico utilizado para publicar as mensagens. O tópico deve assumir o padrão /<service-id>/<device-id>/attrs (e.g.: /admin/efac/attrs).

  • O tópico deve assumir o padrão /<service-id>/<device-id>/config (por exemplo: /admin/efac/config).

  • Os dados da mensagem MQTT (payload) devem ser um JSON com cada chave sendo um atributo do dispositivo cadastrado na dojot, como:

{ "temperature" : 10.5, "pressure" : 770 }

Atenção

VerneMQ é o novo broker MQTT padrão. O suporte ao Mosca será eventualmente retirado, então use o VerneMQ se possível!

Vamos publicar a mensagem a seguir:

mosquitto_pub -h localhost -t /admin/0998/attrs -p 1883 -m '{"temperature": 10.6}'

Se não houver saída (output), a mensagem foi enviada ao broker MQTT.

Além disso, você pode enviar uma mensagem de configuração da dojot para o dispositivo. O atributo de destino deve ser do tipo “actuator” ou “atuador”.

Para simular o recebimento da mensagem em um dispositivo, podemos usar o mosquitto_sub:

mosquitto_sub -h localhost -p 1883 -t /admin/0998/config

Disparando o envio da mensagem da dojot para o dispositivo.

curl -X PUT \
    http://localhost:8000/device/0998/actuate \
    -H "Authorization: Bearer ${JWT}" \
    -H 'Content-Type:application/json' \
    -d '{"attrs": {"fan" : 100}}'

Nota

Consideraremos a utilização de VerneMQ pelo restante do tutorial.

2.5. Conferindo dados históricos

A fim de se conferir todos os valores que foram publicados pelo dispositivo para um atributo particular, pode-se utilizar a API do History, veja mais em Componentes e APIs. Vamos, então, enviar agora alguns outros valores à dojot para que possamos conseguir resultados um pouco mais interessantes:

mosquitto_pub -h localhost -p 1883 -u admin:0998 -t admin:0998/attrs -m '{"temperature": 36.5}' -q 1
mosquitto_pub -h localhost -p 1883 -u admin:0998 -t admin:0998/attrs -m '{"temperature": 15.6}' -q 1
mosquitto_pub -h localhost -p 1883 -u admin:0998 -t admin:0998/attrs -m '{"temperature": 10.6}' -q 1

Para recuperar todos os valores enviados dos atributos temperature desse dispositivo:

curl -X GET \
  -H "Authorization: Bearer ${JWT}" \
  "http://localhost:8000/history/device/0998/history?lastN=3&attr=temperature"

O endpoint do histórico é construído por meio desses valores:

  • .../device/0998/...: o ID do dispositivo é 0998 - isso é obtido do atributo id do próprio dispositivo

  • .../history?lastN=3&attr=temperature: o atributo requerido é temperature e deve ser recuperado os 3 últimos valores.

    A requisição deve resultar na seguinte mensagem:

[
  {
    "device_id": "0998",
    "ts": "2018-03-22T13:47:07.050000Z",
    "value": 10.6,
    "attr": "temperature"
  },
  {
    "device_id": "0998",
    "ts": "2018-03-22T13:46:42.455000Z",
    "value": 15.6,
    "attr": "temperature"
  },
  {
    "device_id": "0998",
    "ts": "2018-03-22T13:46:21.535000Z",
    "value": 36.5,
    "attr": "temperature"
  }
]

A mensagem acima contém todos os valores previamente enviados pelo dispositivo.