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 relativo a um dispositivo. Este tutorial assume que está sendo utilizada a instalacao 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 em 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

Como mencionado em Autenticação de usuário, todas as requisições devem conter um token de acesso que seja válido. É possível gerar um novo token enviando a seguinte requisição:

JWT=$(curl -s -X POST http://localhost:8000/auth \
-H 'Content-Type:application/json' \
-d '{"username": "admin", "passwd" : "admin"}' | jq -r ".jwt")

Checar:

echo $JWT

Se o intuito for gerar um token para outro usuário, é necessário somente mudar o username e passwd no corpo da requisição. O token (“eyJ0eXAiOiJKV1QiL…”) deve ser usado em toda a requisição HTTP enviada para a dojot, colocando-o no cabeçalho da mensagem. A requisição seria algo desse tipo:

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 o documento DeviceManager how-to.

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",
        "label": "device_0"
      }
    ]
  }

2.4. Enviando mensagens

Até o momento um token de acesso foi obtido, um modelo e um dispositivo (baseado no modelo) foram criados. Em um sistema real, o dispositivo físico envia mensagens para a dojot com todos os seus atributos contendo valores correntes. Nsse tutorial serão enviadas 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.

Atenção

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

Nota

Para executar mosquitto_pub e mosquitto_sub sem usar TLS, como noexemplos abaixo, você deve definir ALLOW_UNSECURED_MODE com o valor` ‘true’` para o serviço iotagent-mqtt, isto é, ALLOW_UNSECURED_MODE = ‘true’.Você pode alterar este valor no arquivo docker-compose.yml da dojot e então matar e subir o docker-compose novamente. Por padrão, esse valor já é ‘true’.

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
}

Vamos enviar essa mensagem para a dojot:

mosquitto_pub -h localhost -t /admin/0998/attrs -p 1883 -i admin:0998 -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  -i admin:0998 -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}}'

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 por algum motivo você não pode fazer tal coisa, 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 (por exemplo: /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) deve ser um JSON com cada chave sendo um atributo do dispositivo cadastrado na dojot, como:
{ "temperature" : 10.5,"pressure" : 770 }

Estes exemplos estão usando o MQTT sem TLS, nós recomendamos Usando MQTT com segurança (TLS).

2.5. Conferindo dados históricos

A fim de se conferir todos os valores que foram enviados 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 -t /admin/0998/attrs -i admin:0998 -m '{"temperature": 36.5}'
mosquitto_pub -t /admin/0998/attrs -i admin:0998 -m '{"temperature": 15.6}'
mosquitto_pub -t /admin/0998/attrs -i admin:0998 -m '{"temperature": 10.6}'

Para recuperar todos os valores enviados do atributo 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.