Trocando informações com uma Raspberry Pi e plataforma dojot

Raspberry Pi e plataforma dojot

A dojot é uma plataforma brasileira desenvolvida principalmente pelo CPqD e que surgiu com uma proposta open source, visando facilitar o desenvolvimento de soluções e subsidiar o ecossistema IoT com conteúdo local voltado às necessidades do País.

O código dos componentes que compõem a solução está disponível no repositório do Github. Descritivos detalhados da arquitetura, do funcionamento dos componentes e alguns casos de uso podem ser encontrados na documentação.

Introdução

Na série introdutória da dojot, foram exploradas as funcionalidades iniciais da plataforma, permitindo a criação de dispositivos virtuais, visualização de seus atributos e definição de fluxos de processamento a partir de sinais enviados por um dispositivo.

Neste artigo, utilizaremos o que foi abordado para estabelecer comunicação entre um dispositivo real e a plataforma, monitorando sensores de entrada e controlando uma saída a partir do resultado de um fluxo de processamento.

Mapeando o dispositivo na plataforma dojot

Inicialmente, seria utilizada uma Raspberry Pi em conjunto com o add-on SenseHat.

Visando a comodidade dos leitores – principalmente daqueles que não contam com acesso a este tipo de hardware – este artigo utilizará o emulador Sense HAT Emulator.

Ainda que o dispositivo “real” seja emulado, a biblioteca utilizada simula de forma transparente as APIs do SenseHat, de forma que a aplicação possa ser portada para o dispositivo físico sem grandes problemas.

De maneira similar à descrita nos artigos introdutórios, os passos a serem seguidos para estabelecer a comunicação são:

  • criação de um modelo que descreva os principais atributos do dispositivo
  • criação do dispositivo a partir do modelo que o representa
  • mapeamento do deviceId nas aplicações cliente

Criando o modelo

Neste caso, ao mapear o SenseHat, serão realizadas as seguintes ações:

  • leitura de temperatura
  • leitura de umidade
  • leitura de pressão
  • escrita no visor

Assim, o modelo que dará origem a este dispositivo pode ser visualizado a seguir

humidity:

pressure:

temperature:

display:

protocol:

entrada do tipo float (dynamic)

entrada do tipo float (dynamic)

entrada do tipo float (dynamic)

saída do tipo string (actuator)

configuração

Instanciando um dispositivo a partir do modelo

Após termos o modelo criado, o utilizamos para instanciar um dispositivo.

Obtendo o deviceId

Uma vez salvo, já é possível obter o valor do deviceId na tela de detalhes para este dispositivo.

No caso deste exemplo, o ID é 1d89f2. Note que este valor é gerado cada vez que um dispositivo é criado – e, portanto, deve ser atualizado de acordo.

Interagindo com a plataforma

Até então, apenas foi abordado o uso diretamente via linha de comando de um cliente MQTT para envio de mensagens, simulando o comportamento de um dispositivo.

Nesta seção, utilizaremos uma biblioteca que permite realizar o envio das mesmas mensagens diretamente do código Python sendo executado no dispositivo real.

Instalando as dependências

Os códigos apresentados abaixo fazem uso de Python 3 e suas dependências são gerenciadas a partir do pip3, então esses devem estar instalados.

As dependências estão listadas no arquivo requirements.txt e podem ser instaladas a partir do comando:

pip3 install -r ./requirements.txt

São elas:

Paho MQTT

utilizada na comunicação com o broker mqtt. O uso neste exemplo será básico. Mais detalhes podem ser encontrados na documentação oficial.

sense_emu

biblioteca que espelha as APIs existentes no sense_hat. A documentação oficial pode ser encontrada neste endereço.

Utilizando o emulador

Uma vez instalado, o emulador pode ser executado com o comando:

sense_emu_gui

O código a seguir exemplifica o caso básico de uso.

from sense_emu import SenseHat
import time


#
# Raspberry Pi's Sensor initialization
sense = SenseHat()


#
# Execution loop
while True:
    print("Temperatura:", sense.temperature,
            "; Pressão:", sense.pressure,
            "; Umidade:", sense.humidity)
    time.sleep(4)

A referência sense dá acesso às APIs do SenseHat de forma simples e direta.

Neste exemplo, os valores de temperatura, pressão e umidade são impressos na tela com intervalos de 4 segundos.

Publicando valores na dojot

Conforme visto anteriormente, os atributos de um dispositivo podem ser enviados à plataforma a partir da publicação no tópico de formato /<tenant_name>/<device_id>/attrs

Assim, para que o dispositivo identificado por 36fc0a publique os valores lidos – assumindo o tenant default admin – o tópico de destino deve ser /admin/36fc0a/attrs

No código abaixo, o cliente Paho é utilizado para comunicação MQTT e envio dos atributos definidos manualmente. Note que o ID do cliente mantém o padrão visto ao utilizar o mosquitto: <tenant_name>:<device_id>.

import paho.mqtt.client as mqtt
import json
import time

#
# Properties definition
tenant_name = "admin"
device_id = "36fc0a"

#
# Internal definitions setup
client_id = "{}:{}".format(tenant_name, device_id)
topic_to_publish = "/{}/{}/attrs".format(tenant_name, device_id)

#
# MQTT Client setup and connection
client = mqtt.Client(client_id)

print("Connecting to mqtt broker")
client.connect(host='localhost', port=1883)
client.loop_start()

#
# Execution loop
while True:
    message = {
        "temperature" : 35.11,
        "pressure": 773.29,
        "humidity": 66.23
    }
    print("Publishing", message, 'to topic', topic_to_publish)
    client.publish(topic_to_publish, json.dumps(message))
    time.sleep(4)

Monitorando o dispositivo

Combinando os dois scripts anteriores, podemos realizar o envio das medições à plataforma dojot com a frequência desejada.

O trecho abaixo ilustra este caso de uso:

from sense_emu import SenseHat
import paho.mqtt.client as mqtt
import json
import time

#
# Properties definition
tenant_name = "admin"
device_id = "36fc0a"

#
# Internal definitions setup
client_id = "{}:{}".format(tenant_name, device_id)
topic_to_publish = "/{}/{}/attrs".format(tenant_name, device_id)

#
# MQTT Client setup and connection
client = mqtt.Client(client_id)

print("Connecting to mqtt broker")
client.connect(host='localhost', port=1883)
client.loop_start()

#
# Raspberry Pi's Sensor initialization
print("Initializing SenseHat emulator")
sense = SenseHat()

#
# Execution loop
while True:
    message = {
        "temperature" : sense.temperature,
        "pressure": sense.pressure,
        "humidity": sense.humidity
    }
    print("Publishing", message, 'to topic', topic_to_publish)
    client.publish(topic_to_publish, json.dumps(message))
    time.sleep(4)

Configurando um fluxo de processamento

Visando manter o exemplo o mais simples possível, iremos simular um cenário de uso onde a temperatura medida deve permanecer entre 20 e 30 ºC.

Assim, o fluxo deverá tomar nos casos extremos: valores abaixo de 20ºC ou acima de 30ºC.

Para tal, o seguinte fluxo deve ser criado:

RaspberryPi: define o dispositivo de entrada.

Envia os atributos a partir da variável payload

temperatureController: verifica os limiares de temperatura.

A mensagem recebida via payload é analisada neste bloco. Como o valor de interesse é a temperatura, a propriedade payload.temperature é configurada para verificação.

Os critérios configurados são:

  • Se temperatura maior que 30, acione saída 1
  • Se temperatura menor que 20, acione saída 2

highTemperatureWarning e lowTemperatureWarning: são ativados nos casos de alerta de temperatura alta e baixa, respectivamente.

Esse bloco é responsável por mapear a saída desejada ao modelo de saída do dispositivo.

Neste exemplo, configura-se uma variável output com o objeto { “display” : “high” }.

setDisplay: define o dispositivo de saída (actuator) para o fluxo e a variável que deve ser enviada ao mesmo.

No exemplo, a saída é o próprio Raspberry Pi e a variável é a output, definida no bloco anterior.

Obtendo a mensagem de retorno

Uma vez configurado, o fluxo emitirá um sinal nos casos de temperatura alta ou baixa.

Para que o dispositivo receba as mensagens destinadas a ele, o tópico /<tenant>/<device_id>/config deve ser subscrito.

O código abaixo destaca o trecho adicionado para que a subscrição ocorra, configurando também a função de callback a ser executada quando uma mensagem é recebida:

#
# Internal definitions setup
client_id = "{}:{}".format(tenant_name, device_id)

topic_to_publish = "/{}/{}/attrs".format(tenant_name, device_id)
topic_to_subscribe = "/{}/{}/config".format(tenant_name, device_id)

def on_message(client, userdata, message):
    decoded_message = json.loads(message.payload.decode())
    message_text = decoded_message['attrs']['message']
    print("Received", decoded_message)

#
# MQTT Client setup and connection
client = mqtt.Client(client_id)
client.on_message = on_message

print("Connecting to mqtt broker")
client.connect(host='localhost', port=1883)
client.loop_start()

print("Subscribing to topic", topic_to_subscribe)
client.subscribe(topic_to_subscribe)

Assim que uma mensagem for publicada no tópico, essa função será invocada.

Como o fluxo foi definido para atuar nos casos onde a temperatura é menor que 20 ou maior que 30ºC, podemos validar seu funcionamento variando a temperatura no SensorHat.

Valores publicados e recebidos. Note que apenas são recebidos valores quando ultrapassados os limiares definidos no fluxo de processamento.

Uma vez recebida a mensagem, fica a critério do desenvolvedor decidir como utilizá-la.

Imprimindo a mensagem de retorno no display

Neste exemplo, será impresso no display do SensorHat a situação definida a partir da mensagem recebida, indicando os casos de temperatura baixa e alta.

Modificando o código do on_message, o trecho a seguir mostra a adição que nos permite escrever no visor do dispositivo:

def on_message(client, userdata, message):
    decoded_message = json.loads(message.payload.decode())
    message_text = decoded_message['attrs']['message']
    print("Received", decoded_message)
    sense.clear()
    if message_text == "high":
        sense.show_message("HOT")
    elif message_text == "low":
        sense.show_message("COLD")

É possível forçar os valores de temperatura no dispositivo e validar a atualização do visor:

O código final do script é exibido a seguir:

https://github.com/znti/dojot-raspi-sensehat/blob/master/main.py
from sense_emu import SenseHat
import paho.mqtt.client as mqtt
import json
import time

#
# Properties definition
tenant_name = "admin"
device_id = "36fc0a"

#
# Internal definitions setup
client_id = "{}:{}".format(tenant_name, device_id)

topic_to_publish = "/{}/{}/attrs".format(tenant_name, device_id)
topic_to_subscribe = "/{}/{}/config".format(tenant_name, device_id)

def on_message(client, userdata, message):
    decoded_message = json.loads(message.payload.decode())
    message_text = decoded_message['attrs']['message']
    print("Received", decoded_message)
    sense.clear()
    if message_text == "high":
        sense.show_message("HOT")
    elif message_text == "low":
        sense.show_message("COLD")

#
# MQTT Client setup and connection
client = mqtt.Client(client_id)
client.on_message = on_message

print("Connecting to mqtt broker")
client.connect(host='localhost', port=1883)
client.loop_start()

print("Subscribing to topic", topic_to_subscribe)
client.subscribe(topic_to_subscribe)

#
# Raspberry Pi's Sensor initialization
print("Initializing SenseHat emulator")
sense = SenseHat()

#
# Execution loop
while True:
    message = {
        "temperature" : sense.temperature,
        "pressure": sense.pressure,
        "humidity": sense.humidity
    }
    print("Publishing", message, 'to topic', topic_to_publish)
    client.publish(topic_to_publish, json.dumps(message))
    time.sleep(4)

Conclusão

Até aqui, foram realizadas as configurações necessárias para estabelecer a conexão entre uma Raspberry Pi e a plataforma dojot. Tanto o envio quanto o recebimento de informações foram abordados, o que já permite realizar o controle de um atuador a partir dos sinais enviados ao fluxo de processamento.

No próximo artigo, serão adicionadas camadas de segurança nesta troca de dados a partir do uso de TLS com certificados digitais: com eles, é possível garantir a comunicação segura entre o dispositivo e a plataforma dojot.

Saiba mais

Introdução à plataforma dojot – Instalação e configuração

Simulação de dispositivos na plataforma dojot

Configurando fluxos de processamento de dados da plataforma dojot

Referências

https://sense-emu.readthedocs.io/en/v1.1/
https://github.com/rascaraficci/dojot-sense-hat
https://pypi.org/project/paho-mqtt/#usage-and-api
https://www.steves-internet-guide.com/into-mqtt-python-client/
https://www.steves-internet-guide.com/subscribing-topics-mqtt-client/

Dispositivos reais e segurança na comunicação

Configurando conexão segura com o uso de TLS na plataforma dojot
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
0 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Home » Internet Das Coisas » Trocando informações com uma Raspberry Pi e plataforma dojot

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: