SlideShare uma empresa Scribd logo
1 de 114
Baixar para ler offline
Ferment-IoT
[ˈfɜrmɛnt - aɪoʊ]
Conteúdo
1. IoT numa casca de noz
2. Introdução aos Microcontroladores
3. Breve revisão de protocolos de comunicação
4. Comparativo de sensores
5. Comparativo de atuadores
6. Estudo de Caso
7. Aplicação Real
8. Propostas de melhorias
9. Onde encontrar?
Quem sou eu?
Donato Azevedo Viana
Twitter: @donatoaz
LinkedIn: https://www.linkedin.com/in/donato-viana/
Resumidademente: qualquer dispositivo que interaja via rede.
1. IoT numa casca de nóz
Máquina de coca "conectada", primeiro dispositivo IoT?
1. IoT numa casca de nóz
1. IoT numa casca de nóz
1. IoT numa casca de nóz
2. Introdução a Microcontroladores
1. CPU 2. Memória 3. Periféricos
1 - CPU - unidade de processamento
Operações aritméticas - ADDLW, SUBLW, INCF, etc
Atribui um valor a um registro ou a bits de um registro - MOVLW, CLRW, BSF, etc
Realiza operações booleanas - ANDLW, IORLW, XORLW, etc
Chama ou retorna de sub-rotinas - GOTO, CALL, RETFIE, etc
Não faz nada - NOP ;)
2. Introdução a Microcontroladores
2 - Memória
Volátil - SRAM, DRAM
Não Volátil - EEPROM, Flash
(EEPROM = electrically erasable programmable
read-only memmory)
Antigamente:
ROM, PROM, EPROM
2. Introdução a Microcontroladores
3 - Periféricos
Timers, counters, watchdog, geradores de PWM
Entradas e Saídas discretas e analógicas
Entradas e saídas seriais (I²C Bus, SPI Bus, UART, CAN-Bus, etc)
I²C = Inter-Integrated Circuit
SPI = Serial Peripheral Communication
UART = Universal Asynchronous Receiver Transceiver
CAN = Controller Area Network
2. Introdução a Microcontroladores
"Me dê uma CPU, uma memória e periféricos e
micro-controlarei o mundo"
-- Arquimedes
2. Introdução a Microcontroladores
(Sob minha perspectiva)
2001 - Curso técnico de Eletrônica (COLTEC UFMG)
PICs!
2. Introdução a Microcontroladores
2. Introdução a Microcontroladores
2. Introdução a Microcontroladores
Zilog Z80…
Basic Stamp...
PIC18F877a…
ARDUINO!!
2. Introdução a Microcontroladores
Arduino (placa de desenvolvimento / diversão)
Ambiente de Desenvolvimento Simplificado!!
USB out-of-the-box!!
Programador integrado!!
Programável em C!! Comunidade!!
Código aberto!!
Much peripherals, very shields!!
2. Introdução a Microcontroladores
Enter the chinese!
Arduino clones… mais baratos, menos confiáveis.
Espressif!! ESP8266 ESP01 - baratinha com wifi
NodeMCU - Lua (É tetraaaaaaaaaaaaaaaaaa!!!11!!)
Wifi e Bluetooth BLE Integrados - ganhou meu coração.
2. Introdução a Microcontroladores
2. Introdução a Microcontroladores
2. Introdução a Microcontroladores
O ESP-01 vem com 512Kb de
flash.
É possível Ráqueá-lo para 4MB,
o que permite:
1. OTA (Over The Air updates)
2. Coisas de maior pegada
(mruby? TLS?)
ESP32 - "Evolução do ESP8266"
1. CPUS:
a. Dual core XTensa 32-bits, 240 MHZ
b. ULP co-processor -- deep sleep yaaaay
2. Memórias:
a. 448 kB de ROM para boot e funções core
b. • 520 kB de SRAM para dados e instruções
i. – 8 kB de SRAM em RTC, pode ser usada para dados; é acessada pela CPU principal
durante boot do modo deep sleep
2. Introdução a Microcontroladores
Periféricos:
12-bit SAR ADC up to 18 channels + 2 × 8-bit DACs
10 × touch sensors (capacitive sensing GPIOs)
Built in Temperature sensor
4 × SPI + 2 × I²S interfaces + 2 × I²C interfaces + 3 × UART
SD/SDIO/CE-ATA/MMC/eMMC host controller
SDIO/SPI slave controller
Ethernet MAC interface with dedicated DMA and IEEE 1588 Precision Time Protocol support
CAN bus 2.0
Infrared remote controller (TX/RX, up to 8 channels)
Motor PWM
LED PWM (up to 16 channels)
Hall effect sensor
Ultra low power analog pre-amplifier
2. Introdução a Microcontroladores
2. Introdução a Microcontroladores
2. Introdução a Microcontroladores
气温18摄氏度
3. Breve revisão de protocolos de comunicação
Existem diversos protocolos de comunicação.
Os fatores chave a serem considerados são:
1. Restrições do dispositivo embarcado
2. Requisitos de QoS - Quality of Service
3. Arquitetura
Outros fatores que podem ser avaliados:
1. É proprietário ou aberto?
2. É escalável (suporte a muitos dispositivos se comunicando concorrentemente)
3. Breve revisão de protocolos de comunicação
Existem diversas camadas de protocolos (Ye l OS ta ), alguns já são padrões
mais difundidos e aceitos, por exemplo, os protocolos de infraestrutura (IPv4/v6),
os protocolos de identificação (URI), os de transporte (WiFi, Bluetooth, LoRa)...
O foco aqui é discutir 2 protocolos de *comunicação de dados*, abertos,
existentes:
1. MQTT
2. CoAP
Lista compreensiva de protocolos:
https://www.postscapes.com/internet-of-things-protocols/
3. Breve revisão de protocolos de comunicação
Então vamos começar a falar do "problema":
Um dispositivo IoT coleta leituras de Temperatura através de um sensor, e
precisa enviar esta informação para uma aplicação web. O dispositivo também
possui um atuador que é comandado pela aplicação web (pelo usuário ou
automaticamente) conforme alguma regra pré-estabelecida.
3. Breve revisão de protocolos de comunicação
Situação 1:
O dispositivo pode enviar em intervalos predeterminados a temperatura coletada
para um servidor e paralelamente "perguntar" ao servidor se precisa atuar de
alguma maneira.
Desvantagens: Se a atuação for infrequente, gasta-se muito do recurso banda
com essas perguntas.
3. Breve revisão de protocolos de comunicação
Situação 2
O servidor pode ser o ente ativo, e periodicamente "perguntar" a temperatura, ou
comandar uma atuação.
Desvantagem: o dispositivo em campo precisa implementar um servidor e ficar
constantemente "ouvindo" por perguntas. Gasta-se muito com o recurso energia
desta forma.
3. Breve revisão de protocolos de comunicação
POLLING é quando algum dos entes precisa constantemente "perguntar /
comunicar" a outro(s) o seu estado.
Para dispositivos IoT, via-de-regra, realizar polling (com tamanho de mensagem
grande) é indesejável.
Mas e mensagem "pequena"…?
3. Breve revisão de protocolos de comunicação
MQTT Message Queueing Telemetry Transport
Protocolo recente, tipo Pub/Sub (Publish/Subscribe). Ele resolve o problema de
polling usando mensagens do tipo PINGREQ muito leves. A cada intervalo
predeterminado (parâmetro keepalive, em segundos) o assinante envia uma
mensagem PINGREQ para o árbitro para verificar se há alguma mensagem
destinada a ele. Se não há, o árbitro responde com outra mensagem do tipo
PINGREQ. Cada mensagem tem apenas 2 bytes, muito menos se comparado a
um protocolo convencional (26 bytes para HTTP - https://stackoverflow.com/a/25065027/119958).
3. Breve revisão de protocolos de comunicação
Arquitetura MQTT
3. Breve revisão de protocolos de comunicação
Conceitos importantes:
1. Tópico (topic)
2. Assinante (subscriber)
3. Produtor (publisher)
4. Árbitro (broker)
Arquitetura MQTT
3. Breve revisão de protocolos de comunicação
QoS 0 "Fire and Forget"
Melhor esforço. Tem apenas as garantias inerentes do protocolo de transmissão
(TCP). Cliente não se importa se o broker recebeu ou não. Dados pouco sensíveis.
3. Breve revisão de protocolos de comunicação
QoS 1 - "At least once"
Cliente espera que o árbitro confirme o recebimento com uma mensagem do tipo
PUBACK.
3. Breve revisão de protocolos de comunicação
QoS 1 em ação no Wireshark
3. Breve revisão de protocolos de comunicação
QoS 1 - atenção!
Se o cliente publica uma mensagem e não recebe um PUBACK em um tempo
determinado, ele reenvia -- normalmente este detalhe é transparente para nós
usuários.
Massss… não evita envios repetidos, porque às vezes o árbitro apenas realmente
demorou para confirmar o recebimento.
3. Breve revisão de protocolos de comunicação
QoS 2 - "At most once"
No máximo uma vez, porém é o mais lento, já que 4 mensagens são usadas.
3. Breve revisão de protocolos de comunicação
QoS 2 em ação
3. Breve revisão de protocolos de comunicação
Cliente que não suporta QoS2
Ao enviar uma mensagem com flag de QoS = 2, o árbitro responde com
uma mensagem Publish Received. Mas se o cliente não sabe interagir com
esta mensagem (e portanto não responde com uma mensagem de Publish
Release) o árbitro acha que o
cliente não recebeu a confirmação
e vai enviar incessantemente a
Mensagem Publish Received.
3. Breve revisão de protocolos de comunicação
Retenção de Mensagens
Árbitro mantém a última mensagem publicada retida, e os novos assinantes
sempre recebem esta mensagem ao se conectar.
3. Breve revisão de protocolos de comunicação
Vamos fazer um exemplo ao-vivo: MQTT Broker no google cloud
3. Breve revisão de protocolos de comunicação
CoAP - Constrained Application Protocol
Protocolo mais recente que o MQTT, muito semelhante ao REST (HTTP), porém
"emagrecido" para se adequar à realidade de dispositivos embarcados, que tem
restrições.
3. Breve revisão de protocolos de comunicação
Features CoAP
REST para IoT - parece que você está consumindo uma API (response object,
status code, content type… you name it!)
Integração transparente - uma aplicação não precisa nem saber que está
acessando um sensor, porque ela vai fazer um GET padrãozão.
RFC 7252 - projetado para durar décadas
Payload agnostic - assim como uma API, você pode transferir JSON, XML, Yaml,
etc
Discovery - o Tinder do IoT
Observe - subscribe do CoAP
3. Breve revisão de protocolos de comunicação
Arquitetura MQTT
3. Breve revisão de protocolos de comunicação
3. Breve revisão de protocolos de comunicação
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver| T | TKL | Code | Message ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Token (if any, TKL bytes) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options (if any) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1 1 1 1 1 1 1 1| Payload (if any) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 7: Message Format
VERSION (2 bits)
Por enquanto só
existe a 1
TYPE (2 bits)
Confirmable (0),
Non-confirmable (1),
Acknowledgement (2),
Reset (3)
TOKEN LENGTH (4
bits)
Indica o tamanho do
Token (0 a 8 bytes)
Código (8 bits: 3 MSB + 5
LSB)
Lê-se da forma: c.dd: c (0-7),
dd (0-31). Exemplos:
0.01 - GET request
2.00 - Response status OK
4.04 - Response Not Found
5.00 - Internal Server Error
Message ID: Usado
para evitar duplicações
e para associar
respostas de ACK/RST
←→ CON/NCON
Token: usado para associar
uma requisição a uma resposta
em casos de concorrência. Só
não vai existir quando a
implementação garantir que
não haverão requisições
Opções
Marcador de
Início de Carga
(Payload) 0xFF
CoAP Códigos
+------+------------------------------+-----------+
| Code | Description | Reference |
+------+------------------------------+-----------+
| 2.01 | Created | [RFC7252] |
| 2.02 | Deleted | [RFC7252] |
| 2.03 | Valid | [RFC7252] |
| 2.04 | Changed | [RFC7252] |
| 2.05 | Content | [RFC7252] |
| 4.00 | Bad Request | [RFC7252] |
| 4.01 | Unauthorized | [RFC7252] |
| 4.02 | Bad Option | [RFC7252] |
| 4.03 | Forbidden | [RFC7252] |
| 4.04 | Not Found | [RFC7252] |
| 4.05 | Method Not Allowed | [RFC7252] |
| 4.06 | Not Acceptable | [RFC7252] |
| 4.12 | Precondition Failed | [RFC7252] |
| 4.13 | Request Entity Too Large | [RFC7252] |
| 4.15 | Unsupported Content-Format | [RFC7252] |
| 5.00 | Internal Server Error | [RFC7252] |
| 5.01 | Not Implemented | [RFC7252] |
| 5.02 | Bad Gateway | [RFC7252] |
| 5.03 | Service Unavailable | [RFC7252] |
| 5.04 | Gateway Timeout | [RFC7252] |
| 5.05 | Proxying Not Supported | [RFC7252] |
+------+------------------------------+-----------+
CoAP Opções
+--------+------------------+-----------+
| Number | Name | Reference |
+--------+------------------+-----------+
| 0 | (Reserved) | [RFC7252] |
| 1 | If-Match | [RFC7252] |
| 3 | Uri-Host | [RFC7252] |
| 4 | ETag | [RFC7252] |
| 5 | If-None-Match | [RFC7252] |
| 7 | Uri-Port | [RFC7252] |
| 8 | Location-Path | [RFC7252] |
| 11 | Uri-Path | [RFC7252] |
| 12 | Content-Format | [RFC7252] |
| 14 | Max-Age | [RFC7252] |
| 15 | Uri-Query | [RFC7252] |
| 17 | Accept | [RFC7252] |
| 20 | Location-Query | [RFC7252] |
| 35 | Proxy-Uri | [RFC7252] |
| 39 | Proxy-Scheme | [RFC7252] |
| 60 | Size1 | [RFC7252] |
| 128 | (Reserved) | [RFC7252] |
| 132 | (Reserved) | [RFC7252] |
| 136 | (Reserved) | [RFC7252] |
| 140 | (Reserved) | [RFC7252] |
+--------+------------------+-----------+
+-------------+---------------------------------------+
| Range | Registration Procedures |
+-------------+---------------------------------------+
| 0-255 | IETF Review or IESG Approval |
| 256-2047 | Specification Required |
| 2048-64999 | Expert Review |
| 65000-65535 | Experimental use (no operational use) |
+-------------+---------------------------------------+
3. Breve revisão de protocolos de comunicação
Wiresharking CoAP
Mas UDP não tem as garantias de entrega e ordem do TCP…
Verdade, mas o protocolo TCP é mais pesado e os especificadores do CoAP
entenderam que protocolos mais simples poderiam ser usados. CoAP especifica
um "Stop-and-Wait" [1] simplificado, com tentativas espaçadas exponencialmente
no tempo ("Exponential Backoff") [2].
[1] https://en.wikipedia.org/wiki/Stop-and-wait_ARQ
[2] https://en.wikipedia.org/wiki/Exponential_backoff
3. Breve revisão de protocolos de comunicação
3. Breve revisão de protocolos de comunicação
Stop-and-wait
Exponential
Back Off
Características do sistema observado:
Variável: Temperatura
Dinâmica: Lenta (minutos ou até mesmo horas)
Elemento atuado: geladeira (on-off)
Atuação somente para resfriar: desvantagem: dinâmica de resfriamento bem
diferente da de aquecimento
4. Comparativo de sensores
4. Comparativo de sensores
4. Comparativo de sensores
4. Comparativo de sensores
Termopares
Vantagens:
Simples e relativamente baratos
Robustos e tem grande range de temperaturas (depende do tipo)
Desvantagens:
Não lineares, precisam de circuito externo para compensação (MAX6675 faz
compensação e digitalização com resolução de 12bits)
4. Comparativo de sensores
MAX6675 + Termopar Tipo K
4. Comparativo de sensores
Esquema de conexão -- usa protocolo SPI (Serial Peripheral Interface) - 3 pinos.
OK para o ESP32, mas ruim para ESP8266-01…
4. Comparativo de sensores
Preço relativamente baixo no ML
4. Comparativo de sensores
Erro alto?
4. Comparativo de sensores
Erro alto?
4. Comparativo de sensores
Contribuição Open Source! Com 7 (and counting…)
4. Comparativo de sensores
Porém…
Não é a prova d'água out-of-the-box -- precisa de poço termométrico.
Precisa de 3 pinos do micro-controlador
Fiquei assustado com a possibilidade de erro de +/- 3oC
4. Comparativo de sensores
Sensor Integrado (I.C.) DS18b20
Vantagens:
Interface digital, baixo erro, usa apenas 1 pino (parasite power!)
Desvantagens:
(que não afetam o meu caso): baixo range -55oC a +125oC e baixo tempo de
resposta (em alguns casos mais de 10 segundos, devido ao encapsulamento a
prova d'água)
4. Comparativo de sensores
4. Comparativo de sensores
Exemplo de como o encapsulamento pode afetar (gráfico abaixo para LM35)
Encapsulamento a prova d'água do DS18b20
adiciona bastante tempo para estabilizar a leitura.
4. Comparativo de sensores
Ausência de Biblioteca One-Wire nativa para o ESP32? Sem problemas:
https://github.com/DavidAntliff/esp32-ds18b20 - versão multi-dispositivo
https://github.com/feelfreelinux/ds18b20 - versão simplificada para apenas 1
sensor
4. Comparativo de sensores
5. Comparativo de Atuadores
Tipos de relé:
Eletro-mecânico
Estado Sólido
4. Comparativo de atuadores
5. Comparativo de atuadores
Relés eletromecânicos cargas indutivas (ex: motor do compressor de uma
geladeira)
Arco voltáico - danifica os contatos do relé e diminui a vida útil.
5. Comparativo de atuadores
Mas e o diodo de "flyback"? Até funciona, mas nos relés chineses (baratos, do
aliexpress), ainda assim tive problemas com agarramento (sticking).
Sem diodo flyback Com diodo flyback
5. Comparativo de atuadores
Relé de estado sólido
Não possui partes mecânicas == não sofre de agarramento
Dependendo da carga, pode aquecer (e muito), se necessário deve-se utilizar um
dissipador + cooler
Isolamento físico (opto-acoplado)
É basicamente um opto-acoplador (circuito de acionamento) + um Triac (circuito
de carga)
5. Comparativo de atuadores
5. Comparativo de atuadores
=
5. Comparativo de atuadores
6. Estudo de Caso
6. Estudo de Caso
6. Estudo de Caso
6. Estudo de Caso
6. Estudo de Caso
6. Estudo de Caso
7. Projeto
Árbitro Mosquitto:
6. Estudo de
Caso
Docker component:
mqtt:
image: 'donatoaz/mymosquitto'
ports:
- "1883:1883"
- "9001:9001"
volumes:
- /home/donato/cervejator/mqtt/config:/mqtt/config:ro
- /home/donato/cervejator/mqtt/data:/mqtt/data
- /home/donato/cervejator/mqtt/log:/mqtt/log
7. Projeto
donato@porter ~/mosquitto $ cat config/mosquitto.conf
# Place your local configuration in /mqtt/config/conf.d/
pid_file /var/run/mosquitto.pid
persistence true
persistence_location /mqtt/data/
#user mosquitto
allow_anonymous true
port 1883
log_dest file /mqtt/log/mosquitto.log
log_dest stdout
log_type all
connection_messages true
log_timestamp true
include_dir /mqtt/config/conf.d
7. Projeto
Banco de Dados Postgresql
Docker Component
db:
image: postgres
environment:
POSTGRES_DB: cervejator
POSTGRES_USER: ****
POSTGRES_PASSWORD: ****
7. Projeto
Key-value Store - Redis DB
Docker Component
redis:
image: redis:3.2
7. Projeto
Assinante MQTT
É uma Rake Task (Roda em seu próprio processo, mas tem acesso ao ambiente
Rails da aplicação Web).
Contém um cliente MQTT que assina ao tópico: "sensor/#"
Para cada mensagem que recebe do tipo "sensor/#":
1. Cria tarefa para armazenar assíncronamente o dado -- não tem de ficar
bloqueado esperando uma operação de E/S
2. Faz um broadcast do valor recebido nos Canais Active Cable para stream em
tempo real no browser do cliente
7. Projeto
Docker Component:
subscriber:
build:
context: .
dockerfile: Dockerfile.subscriber
restart: always
environment:
RAILS_ENV: "production"
REDIS_URL: "redis://redis:6379"
MQTT_BROKER_HOST: "mqtt"
MQTT_BROKER_PORT: "1883"
command: bundle exec rake mqtt:subscriber
volumes:
- /home/donato/cervejator:/web
depends_on:
- redis
- db
- mqtt
7. Projeto
Background Jobs - Resque
Processamento Assíncrono de Tarefas:
1. Execução de escritas no banco de dados - PersistDataJob
class PersistDataJob < ApplicationJob
queue_as :readings
def perform(datum)
Datum.create(datum)
end
end
7. Projeto
Escalonador de malhas de controle
$ cat config/schedule.yml
development: &development
ScheduleControlLoopsJob:
description: 'Polls control loops'
queue: 'control_loops'
every:
- '20s'
test:
<<: *development
production:
<<: *development
class ScheduleControlLoopsJob < ApplicationJob
queue_as :control_loops
def perform
ControlLoop.all.each do |cl|
next unless cl.mode == "auto"
if Time.now >= cl.next_run
ControlLoopJob.perform_later(cl.id)
end
if cl.missed_deadline?
ActiveJob::Base.logger.error "Control Loop
##{cl.id}:#{cl.name} is missed deadline!"
end
end
end
end
7. Projeto
Background Jobs - Resque
Processamento Assíncrono
de Tarefas:
2. Execução das malhas de
controle com envio de
mensagem MQTTT
class ControlLoopJob < ApplicationJob
queue_as :run_control_loops
def perform(control_loop_id)
ctrl = ControlLoop.find(control_loop_id)
action = ctrl.run
return if action == :inactive
cli = MQTT::Client.connect(host: ENV['MQTT_BROKER_HOST'],
username: 'mosquitto',
port: ENV['MQTT_BROKER_PORT'])
cli.publish("actuator/#{ctrl.actuator.write_key}",
action,
false, 1)
cli.disconnect()
ctrl.update_attribute(:next_run,
Time.now + ctrl.sampling_rate.seconds)
end
end
7. Projeto
Stream de dados em
tempo real via
websockets usando
Action Cable
Server side (ruby):
class SensorChannel < ApplicationCable::Channel
def subscribed
sensor = Sensor.find(params[:id])
stream_for sensor,
coder: ActiveSupport::JSON do |message|
transmit message
end
end
end
class ActuatorChannel < ApplicationCable::Channel
def subscribed
actuator = Actuator.find(params[:id])
stream_for actuator, coder:
ActiveSupport::JSON do |message|
transmit message
end
end
end
7. Projeto
App.cable.subscriptions.create { channel: "SensorChannel", id: sensor_id },
received: (data) ->
@addDataToChart data
Stream de dados em
tempo real via
websockets usando
Action Cable
Client side (coffeescript):
7. Projeto
7. Projeto
initialize_gpio
Configurando as entradas e
saídas do ESP32
void initialize_gpio(void)
{
gpio_pad_select_gpio(ACTUATOR_GPIO);
gpio_set_direction(ACTUATOR_GPIO,
GPIO_MODE_OUTPUT);
ds18b20_init(14);
}
GPIO = General Purpose Input/Output
7. Projeto
Esp_event_loop_init
Evita esperas bloqueadas, a
própria lib do ESP-IDF se
encarrega de criar uma task
que chama este callback
sempre que há um novo
evento.
static
esp_err_t event_handler(void *ctx, system_event_t *event)
{
switch (event->event_id)
{
case SYSTEM_EVENT_STA_START:
ESP_LOGI(TAG, "System started, going to connect to wifi.");
wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
ESP_LOGI(TAG, "Got IP, conn to MQTT. %s : %d, user: %s, pass: %s",
MQTT_HOST, MQTT_PORT, MQTT_USER, MQTT_PASS);
esp_mqtt_start(MQTT_HOST, MQTT_PORT, "esp-mqtt", "", "");
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
ESP_LOGI(TAG, "WiFi lost, stop MQTTT and attempt a reconnect.");
esp_mqtt_stop();
esp_wifi_connect();
break;
default:
break;
}
return ESP_OK;
}
7. Projeto
typedef enum {
SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */
SYSTEM_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */
SYSTEM_EVENT_STA_START, /**< ESP32 station start */
SYSTEM_EVENT_STA_STOP, /**< ESP32 station stop */
SYSTEM_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */
SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
SYSTEM_EVENT_STA_GOT_IP, /**< ESP32 station got IP from connected AP */
SYSTEM_EVENT_STA_LOST_IP, /**< ESP32 station lost IP and the IP is reset to 0 */
SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
} system_event_id_t;
7. Projeto
Inicialização da lib MQTT
esp_mqtt_init(mqtt_status_cb, mqtt_message_cb, 256, 2000);
Status Call Back
Function
Chamado sempre
que o status
(conectado,
desconectado)
muda
Status Call Back Function
Chamado sempre que é
recebida uma mensagem
Buffer Size para
leitura/escrita de
payloads
Timeout para comandos
enviados ao árbitro (em
mS)
7. Projeto
Callback de
mensagens recebidas
(atuador)
static void
mqtt_message_cb(const char *topic, uint8_t *payload, size_t len)
{
printf("incomingt%s:%s (%d)n", topic, payload, (int)len);
if (strcmp((char *) payload,"on") == 0) {
ESP_LOGI(TAG, "Setting pin %d to high", ACTUATOR_GPIO);
gpio_set_level(ACTUATOR_GPIO, 1);
} else if (strcmp((char *) payload, "off") == 0) {
ESP_LOGI(TAG, "Setting pin %d to low", ACTUATOR_GPIO);
gpio_set_level(ACTUATOR_GPIO, 0);
} else {
ESP_LOGI(TAG, "Received an unknown actuator command");
}
}
7. Projeto
Callback de Status:
Se conectado,
começa a publicar.
Se desconectado,
para de publicar e
tenta conectar
novamente...
static void
mqtt_status_cb(esp_mqtt_status_t status)
{
switch (status)
{
case ESP_MQTT_STATUS_CONNECTED:
ESP_LOGI(TAG, "Cool, we got a CONNECT ACK from broker!");
esp_mqtt_subscribe(ACTUATOR_WRITE_KEY, 0);
xTaskCreatePinnedToCore(process, "process", 8192, NULL, 10, &task,
1);
break;
case ESP_MQTT_STATUS_DISCONNECTED:
ESP_LOGI(TAG, "Shoot, MQTT disconnected! Going to retry...
Stopping publishing task.");
vTaskDelete(task);
vTaskDelay(5000 / portTICK_PERIOD_MS);
esp_mqtt_start(MQTT_HOST, MQTT_PORT, "esp-mqtt", "", "");
break;
}
}
7. Projeto
8. Aplicação Real
8. Aplicação Real
(Mostrar em tempo real)
8. Aplicação Real
9. Propostas de Melhoria
Usar o EMQTT (Erlang) ao invés do Mosquitto
9. Propostas de Melhoria
Usar CoAP, de modo que o aplicativo web seja mais passivo e os
dispositivos implementem e exponham o que quiserem (aplicativo web
vira um "Registry" --
https://www.monterail.com/blog/2016/iot-with-elixir-and-coap-part-1-example-on-how-to-easily-
prototype-and-build-an-iot-platform
9. Propostas de Melhoria
Usar AnyCable ao invés de action cable
https://evilmartians.com/chronicles/anycable-actioncable-on-steroids
https://github.com/anycable/anycable-go
9. Propostas de Melhoria
10. Onde Encontrar?
with 'github.com/donatoaz' do
esp8266-esp01-MAX6675 - conectando termopar ao esp8266
cervejator - aplicação dockerizada apresentada
Esp32-mqtt-cervejator - cliente mqtt para o esp32
end
@donatoaz (twitter)
Perguntas???
Referências MQTT, Docker e Wireshark
https://github.com/toke/docker-mosquitto
https://cloud.google.com/community/tutorials/docker-
compose-on-container-optimized-os
https://docs.docker.com/compose/compose-file/com
pose-file-v2/#container_name
https://mosquitto.org/man/mosquitto-conf-5.html
https://www.wireshark.org/docs/dfref/m/mqtt.html
https://github.com/RubyDevInc/paho.mqtt.ruby
https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels
Lib MQTT para ESP32
https://github.com/tuanpmt/esp_mqtt
https://github.com/256dpi/esp-mqtt
Docker cheatsheet
$ docker-compose up
-- o BD ainda não existe, então:
$ docker-compose run web bundle exec rake db:create db:migrate db:seed
-- Por algum motivo, o yarn install não instalou as paradas, então:
$ docker-compose run web yarn add jquery jquery-ujs amcharts lodash
-- Os ativos estáticos também não existem ainda, então:
$ docker-compose run web bundle exec rake assets:precompile

Mais conteúdo relacionado

Semelhante a Ferment-IoT: um guia para IoT com microcontroladores

REDES DE COMPUTADORES - SEMANA 2.pdf
REDES DE COMPUTADORES - SEMANA 2.pdfREDES DE COMPUTADORES - SEMANA 2.pdf
REDES DE COMPUTADORES - SEMANA 2.pdfVagnerSimoesSantos
 
Webinar: Redes Mesh para Monitoramento e Controle de Sensores
Webinar: Redes Mesh para Monitoramento e Controle de SensoresWebinar: Redes Mesh para Monitoramento e Controle de Sensores
Webinar: Redes Mesh para Monitoramento e Controle de SensoresEmbarcados
 
Protocolo MQTT: Message Queuing Telemetry Transport
Protocolo MQTT: Message Queuing Telemetry TransportProtocolo MQTT: Message Queuing Telemetry Transport
Protocolo MQTT: Message Queuing Telemetry TransportNorberto Enomoto
 
IX Pylestras - SmartGrid com Python
IX Pylestras - SmartGrid com PythonIX Pylestras - SmartGrid com Python
IX Pylestras - SmartGrid com Pythonitalomaia
 
Protocolos de Sistemas Embarcados
Protocolos de Sistemas EmbarcadosProtocolos de Sistemas Embarcados
Protocolos de Sistemas EmbarcadosRomulo Fagundes
 
Apresentação - IT Specialist
Apresentação - IT SpecialistApresentação - IT Specialist
Apresentação - IT SpecialistAlan Carlos
 
Apresentação de Introdução ao Syslog
Apresentação de Introdução ao SyslogApresentação de Introdução ao Syslog
Apresentação de Introdução ao SyslogIsaque Profeta
 
Módulo 08 o que é tcp-ip
Módulo 08   o que é tcp-ipMódulo 08   o que é tcp-ip
Módulo 08 o que é tcp-ipMarília Simões
 
Projeto final m_243_dulo_4
Projeto final m_243_dulo_4Projeto final m_243_dulo_4
Projeto final m_243_dulo_4y3vg3n
 
Estudo do Protocolo ISAKMP/OAkley como Norma de Gestão de Chaves da Arquitect...
Estudo do Protocolo ISAKMP/OAkley como Norma de Gestão de Chaves da Arquitect...Estudo do Protocolo ISAKMP/OAkley como Norma de Gestão de Chaves da Arquitect...
Estudo do Protocolo ISAKMP/OAkley como Norma de Gestão de Chaves da Arquitect...Rute C. Sofia
 
Apostila Redes Industriais - Prof. Camilo A. Anauate
Apostila Redes Industriais - Prof. Camilo A. AnauateApostila Redes Industriais - Prof. Camilo A. Anauate
Apostila Redes Industriais - Prof. Camilo A. Anauate Camilo Alberto Anauate
 

Semelhante a Ferment-IoT: um guia para IoT com microcontroladores (20)

IoT: construindo ideias com nodeMCU e MQTT
IoT: construindo ideias com nodeMCU e MQTTIoT: construindo ideias com nodeMCU e MQTT
IoT: construindo ideias com nodeMCU e MQTT
 
REDES DE COMPUTADORES - SEMANA 2.pdf
REDES DE COMPUTADORES - SEMANA 2.pdfREDES DE COMPUTADORES - SEMANA 2.pdf
REDES DE COMPUTADORES - SEMANA 2.pdf
 
Webinar: Redes Mesh para Monitoramento e Controle de Sensores
Webinar: Redes Mesh para Monitoramento e Controle de SensoresWebinar: Redes Mesh para Monitoramento e Controle de Sensores
Webinar: Redes Mesh para Monitoramento e Controle de Sensores
 
Protocolo MQTT: Message Queuing Telemetry Transport
Protocolo MQTT: Message Queuing Telemetry TransportProtocolo MQTT: Message Queuing Telemetry Transport
Protocolo MQTT: Message Queuing Telemetry Transport
 
IX Pylestras - SmartGrid com Python
IX Pylestras - SmartGrid com PythonIX Pylestras - SmartGrid com Python
IX Pylestras - SmartGrid com Python
 
Protocolos modbus
Protocolos modbusProtocolos modbus
Protocolos modbus
 
Protocolos de Sistemas Embarcados
Protocolos de Sistemas EmbarcadosProtocolos de Sistemas Embarcados
Protocolos de Sistemas Embarcados
 
ffffFicha 8 Nº.docx
ffffFicha 8 Nº.docxffffFicha 8 Nº.docx
ffffFicha 8 Nº.docx
 
Apresentação - IT Specialist
Apresentação - IT SpecialistApresentação - IT Specialist
Apresentação - IT Specialist
 
Apresentação de Introdução ao Syslog
Apresentação de Introdução ao SyslogApresentação de Introdução ao Syslog
Apresentação de Introdução ao Syslog
 
Módulo 08 o que é tcp-ip
Módulo 08   o que é tcp-ipMódulo 08   o que é tcp-ip
Módulo 08 o que é tcp-ip
 
Projeto final m_243_dulo_4
Projeto final m_243_dulo_4Projeto final m_243_dulo_4
Projeto final m_243_dulo_4
 
Estudo do Protocolo ISAKMP/OAkley como Norma de Gestão de Chaves da Arquitect...
Estudo do Protocolo ISAKMP/OAkley como Norma de Gestão de Chaves da Arquitect...Estudo do Protocolo ISAKMP/OAkley como Norma de Gestão de Chaves da Arquitect...
Estudo do Protocolo ISAKMP/OAkley como Norma de Gestão de Chaves da Arquitect...
 
Snort
SnortSnort
Snort
 
Rede
RedeRede
Rede
 
Ntop
NtopNtop
Ntop
 
Apostila Redes Industriais - Prof. Camilo A. Anauate
Apostila Redes Industriais - Prof. Camilo A. AnauateApostila Redes Industriais - Prof. Camilo A. Anauate
Apostila Redes Industriais - Prof. Camilo A. Anauate
 
Factura Clix
Factura ClixFactura Clix
Factura Clix
 
Artigo Redes Jonnes
Artigo Redes JonnesArtigo Redes Jonnes
Artigo Redes Jonnes
 
Artigo Redes Jonnes
Artigo Redes JonnesArtigo Redes Jonnes
Artigo Redes Jonnes
 

Ferment-IoT: um guia para IoT com microcontroladores

  • 2. Conteúdo 1. IoT numa casca de noz 2. Introdução aos Microcontroladores 3. Breve revisão de protocolos de comunicação 4. Comparativo de sensores 5. Comparativo de atuadores 6. Estudo de Caso 7. Aplicação Real 8. Propostas de melhorias 9. Onde encontrar?
  • 3. Quem sou eu? Donato Azevedo Viana Twitter: @donatoaz LinkedIn: https://www.linkedin.com/in/donato-viana/
  • 4. Resumidademente: qualquer dispositivo que interaja via rede. 1. IoT numa casca de nóz
  • 5. Máquina de coca "conectada", primeiro dispositivo IoT? 1. IoT numa casca de nóz
  • 6. 1. IoT numa casca de nóz
  • 7. 1. IoT numa casca de nóz
  • 8. 2. Introdução a Microcontroladores 1. CPU 2. Memória 3. Periféricos
  • 9. 1 - CPU - unidade de processamento Operações aritméticas - ADDLW, SUBLW, INCF, etc Atribui um valor a um registro ou a bits de um registro - MOVLW, CLRW, BSF, etc Realiza operações booleanas - ANDLW, IORLW, XORLW, etc Chama ou retorna de sub-rotinas - GOTO, CALL, RETFIE, etc Não faz nada - NOP ;) 2. Introdução a Microcontroladores
  • 10. 2 - Memória Volátil - SRAM, DRAM Não Volátil - EEPROM, Flash (EEPROM = electrically erasable programmable read-only memmory) Antigamente: ROM, PROM, EPROM 2. Introdução a Microcontroladores
  • 11. 3 - Periféricos Timers, counters, watchdog, geradores de PWM Entradas e Saídas discretas e analógicas Entradas e saídas seriais (I²C Bus, SPI Bus, UART, CAN-Bus, etc) I²C = Inter-Integrated Circuit SPI = Serial Peripheral Communication UART = Universal Asynchronous Receiver Transceiver CAN = Controller Area Network 2. Introdução a Microcontroladores
  • 12. "Me dê uma CPU, uma memória e periféricos e micro-controlarei o mundo" -- Arquimedes 2. Introdução a Microcontroladores
  • 13. (Sob minha perspectiva) 2001 - Curso técnico de Eletrônica (COLTEC UFMG) PICs! 2. Introdução a Microcontroladores
  • 14. 2. Introdução a Microcontroladores
  • 15. 2. Introdução a Microcontroladores
  • 16. Zilog Z80… Basic Stamp... PIC18F877a… ARDUINO!! 2. Introdução a Microcontroladores
  • 17. Arduino (placa de desenvolvimento / diversão) Ambiente de Desenvolvimento Simplificado!! USB out-of-the-box!! Programador integrado!! Programável em C!! Comunidade!! Código aberto!! Much peripherals, very shields!! 2. Introdução a Microcontroladores
  • 18. Enter the chinese! Arduino clones… mais baratos, menos confiáveis. Espressif!! ESP8266 ESP01 - baratinha com wifi NodeMCU - Lua (É tetraaaaaaaaaaaaaaaaaa!!!11!!) Wifi e Bluetooth BLE Integrados - ganhou meu coração. 2. Introdução a Microcontroladores
  • 19. 2. Introdução a Microcontroladores
  • 20. 2. Introdução a Microcontroladores O ESP-01 vem com 512Kb de flash. É possível Ráqueá-lo para 4MB, o que permite: 1. OTA (Over The Air updates) 2. Coisas de maior pegada (mruby? TLS?)
  • 21. ESP32 - "Evolução do ESP8266" 1. CPUS: a. Dual core XTensa 32-bits, 240 MHZ b. ULP co-processor -- deep sleep yaaaay 2. Memórias: a. 448 kB de ROM para boot e funções core b. • 520 kB de SRAM para dados e instruções i. – 8 kB de SRAM em RTC, pode ser usada para dados; é acessada pela CPU principal durante boot do modo deep sleep 2. Introdução a Microcontroladores
  • 22. Periféricos: 12-bit SAR ADC up to 18 channels + 2 × 8-bit DACs 10 × touch sensors (capacitive sensing GPIOs) Built in Temperature sensor 4 × SPI + 2 × I²S interfaces + 2 × I²C interfaces + 3 × UART SD/SDIO/CE-ATA/MMC/eMMC host controller SDIO/SPI slave controller Ethernet MAC interface with dedicated DMA and IEEE 1588 Precision Time Protocol support CAN bus 2.0 Infrared remote controller (TX/RX, up to 8 channels) Motor PWM LED PWM (up to 16 channels) Hall effect sensor Ultra low power analog pre-amplifier 2. Introdução a Microcontroladores
  • 23. 2. Introdução a Microcontroladores
  • 24. 2. Introdução a Microcontroladores
  • 25. 气温18摄氏度 3. Breve revisão de protocolos de comunicação
  • 26. Existem diversos protocolos de comunicação. Os fatores chave a serem considerados são: 1. Restrições do dispositivo embarcado 2. Requisitos de QoS - Quality of Service 3. Arquitetura Outros fatores que podem ser avaliados: 1. É proprietário ou aberto? 2. É escalável (suporte a muitos dispositivos se comunicando concorrentemente) 3. Breve revisão de protocolos de comunicação
  • 27. Existem diversas camadas de protocolos (Ye l OS ta ), alguns já são padrões mais difundidos e aceitos, por exemplo, os protocolos de infraestrutura (IPv4/v6), os protocolos de identificação (URI), os de transporte (WiFi, Bluetooth, LoRa)... O foco aqui é discutir 2 protocolos de *comunicação de dados*, abertos, existentes: 1. MQTT 2. CoAP Lista compreensiva de protocolos: https://www.postscapes.com/internet-of-things-protocols/ 3. Breve revisão de protocolos de comunicação
  • 28. Então vamos começar a falar do "problema": Um dispositivo IoT coleta leituras de Temperatura através de um sensor, e precisa enviar esta informação para uma aplicação web. O dispositivo também possui um atuador que é comandado pela aplicação web (pelo usuário ou automaticamente) conforme alguma regra pré-estabelecida. 3. Breve revisão de protocolos de comunicação
  • 29. Situação 1: O dispositivo pode enviar em intervalos predeterminados a temperatura coletada para um servidor e paralelamente "perguntar" ao servidor se precisa atuar de alguma maneira. Desvantagens: Se a atuação for infrequente, gasta-se muito do recurso banda com essas perguntas. 3. Breve revisão de protocolos de comunicação
  • 30. Situação 2 O servidor pode ser o ente ativo, e periodicamente "perguntar" a temperatura, ou comandar uma atuação. Desvantagem: o dispositivo em campo precisa implementar um servidor e ficar constantemente "ouvindo" por perguntas. Gasta-se muito com o recurso energia desta forma. 3. Breve revisão de protocolos de comunicação
  • 31. POLLING é quando algum dos entes precisa constantemente "perguntar / comunicar" a outro(s) o seu estado. Para dispositivos IoT, via-de-regra, realizar polling (com tamanho de mensagem grande) é indesejável. Mas e mensagem "pequena"…? 3. Breve revisão de protocolos de comunicação
  • 32. MQTT Message Queueing Telemetry Transport Protocolo recente, tipo Pub/Sub (Publish/Subscribe). Ele resolve o problema de polling usando mensagens do tipo PINGREQ muito leves. A cada intervalo predeterminado (parâmetro keepalive, em segundos) o assinante envia uma mensagem PINGREQ para o árbitro para verificar se há alguma mensagem destinada a ele. Se não há, o árbitro responde com outra mensagem do tipo PINGREQ. Cada mensagem tem apenas 2 bytes, muito menos se comparado a um protocolo convencional (26 bytes para HTTP - https://stackoverflow.com/a/25065027/119958). 3. Breve revisão de protocolos de comunicação
  • 33. Arquitetura MQTT 3. Breve revisão de protocolos de comunicação
  • 34. Conceitos importantes: 1. Tópico (topic) 2. Assinante (subscriber) 3. Produtor (publisher) 4. Árbitro (broker) Arquitetura MQTT 3. Breve revisão de protocolos de comunicação
  • 35. QoS 0 "Fire and Forget" Melhor esforço. Tem apenas as garantias inerentes do protocolo de transmissão (TCP). Cliente não se importa se o broker recebeu ou não. Dados pouco sensíveis. 3. Breve revisão de protocolos de comunicação
  • 36. QoS 1 - "At least once" Cliente espera que o árbitro confirme o recebimento com uma mensagem do tipo PUBACK. 3. Breve revisão de protocolos de comunicação
  • 37. QoS 1 em ação no Wireshark 3. Breve revisão de protocolos de comunicação
  • 38. QoS 1 - atenção! Se o cliente publica uma mensagem e não recebe um PUBACK em um tempo determinado, ele reenvia -- normalmente este detalhe é transparente para nós usuários. Massss… não evita envios repetidos, porque às vezes o árbitro apenas realmente demorou para confirmar o recebimento. 3. Breve revisão de protocolos de comunicação
  • 39. QoS 2 - "At most once" No máximo uma vez, porém é o mais lento, já que 4 mensagens são usadas. 3. Breve revisão de protocolos de comunicação
  • 40. QoS 2 em ação 3. Breve revisão de protocolos de comunicação
  • 41. Cliente que não suporta QoS2 Ao enviar uma mensagem com flag de QoS = 2, o árbitro responde com uma mensagem Publish Received. Mas se o cliente não sabe interagir com esta mensagem (e portanto não responde com uma mensagem de Publish Release) o árbitro acha que o cliente não recebeu a confirmação e vai enviar incessantemente a Mensagem Publish Received. 3. Breve revisão de protocolos de comunicação
  • 42. Retenção de Mensagens Árbitro mantém a última mensagem publicada retida, e os novos assinantes sempre recebem esta mensagem ao se conectar. 3. Breve revisão de protocolos de comunicação
  • 43. Vamos fazer um exemplo ao-vivo: MQTT Broker no google cloud 3. Breve revisão de protocolos de comunicação
  • 44. CoAP - Constrained Application Protocol Protocolo mais recente que o MQTT, muito semelhante ao REST (HTTP), porém "emagrecido" para se adequar à realidade de dispositivos embarcados, que tem restrições. 3. Breve revisão de protocolos de comunicação
  • 45. Features CoAP REST para IoT - parece que você está consumindo uma API (response object, status code, content type… you name it!) Integração transparente - uma aplicação não precisa nem saber que está acessando um sensor, porque ela vai fazer um GET padrãozão. RFC 7252 - projetado para durar décadas Payload agnostic - assim como uma API, você pode transferir JSON, XML, Yaml, etc Discovery - o Tinder do IoT Observe - subscribe do CoAP 3. Breve revisão de protocolos de comunicação
  • 46. Arquitetura MQTT 3. Breve revisão de protocolos de comunicação
  • 47. 3. Breve revisão de protocolos de comunicação 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Ver| T | TKL | Code | Message ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Token (if any, TKL bytes) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options (if any) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1 1 1 1 1 1 1 1| Payload (if any) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 7: Message Format VERSION (2 bits) Por enquanto só existe a 1 TYPE (2 bits) Confirmable (0), Non-confirmable (1), Acknowledgement (2), Reset (3) TOKEN LENGTH (4 bits) Indica o tamanho do Token (0 a 8 bytes) Código (8 bits: 3 MSB + 5 LSB) Lê-se da forma: c.dd: c (0-7), dd (0-31). Exemplos: 0.01 - GET request 2.00 - Response status OK 4.04 - Response Not Found 5.00 - Internal Server Error Message ID: Usado para evitar duplicações e para associar respostas de ACK/RST ←→ CON/NCON Token: usado para associar uma requisição a uma resposta em casos de concorrência. Só não vai existir quando a implementação garantir que não haverão requisições Opções Marcador de Início de Carga (Payload) 0xFF
  • 48. CoAP Códigos +------+------------------------------+-----------+ | Code | Description | Reference | +------+------------------------------+-----------+ | 2.01 | Created | [RFC7252] | | 2.02 | Deleted | [RFC7252] | | 2.03 | Valid | [RFC7252] | | 2.04 | Changed | [RFC7252] | | 2.05 | Content | [RFC7252] | | 4.00 | Bad Request | [RFC7252] | | 4.01 | Unauthorized | [RFC7252] | | 4.02 | Bad Option | [RFC7252] | | 4.03 | Forbidden | [RFC7252] | | 4.04 | Not Found | [RFC7252] | | 4.05 | Method Not Allowed | [RFC7252] | | 4.06 | Not Acceptable | [RFC7252] | | 4.12 | Precondition Failed | [RFC7252] | | 4.13 | Request Entity Too Large | [RFC7252] | | 4.15 | Unsupported Content-Format | [RFC7252] | | 5.00 | Internal Server Error | [RFC7252] | | 5.01 | Not Implemented | [RFC7252] | | 5.02 | Bad Gateway | [RFC7252] | | 5.03 | Service Unavailable | [RFC7252] | | 5.04 | Gateway Timeout | [RFC7252] | | 5.05 | Proxying Not Supported | [RFC7252] | +------+------------------------------+-----------+
  • 49. CoAP Opções +--------+------------------+-----------+ | Number | Name | Reference | +--------+------------------+-----------+ | 0 | (Reserved) | [RFC7252] | | 1 | If-Match | [RFC7252] | | 3 | Uri-Host | [RFC7252] | | 4 | ETag | [RFC7252] | | 5 | If-None-Match | [RFC7252] | | 7 | Uri-Port | [RFC7252] | | 8 | Location-Path | [RFC7252] | | 11 | Uri-Path | [RFC7252] | | 12 | Content-Format | [RFC7252] | | 14 | Max-Age | [RFC7252] | | 15 | Uri-Query | [RFC7252] | | 17 | Accept | [RFC7252] | | 20 | Location-Query | [RFC7252] | | 35 | Proxy-Uri | [RFC7252] | | 39 | Proxy-Scheme | [RFC7252] | | 60 | Size1 | [RFC7252] | | 128 | (Reserved) | [RFC7252] | | 132 | (Reserved) | [RFC7252] | | 136 | (Reserved) | [RFC7252] | | 140 | (Reserved) | [RFC7252] | +--------+------------------+-----------+ +-------------+---------------------------------------+ | Range | Registration Procedures | +-------------+---------------------------------------+ | 0-255 | IETF Review or IESG Approval | | 256-2047 | Specification Required | | 2048-64999 | Expert Review | | 65000-65535 | Experimental use (no operational use) | +-------------+---------------------------------------+
  • 50. 3. Breve revisão de protocolos de comunicação Wiresharking CoAP
  • 51. Mas UDP não tem as garantias de entrega e ordem do TCP… Verdade, mas o protocolo TCP é mais pesado e os especificadores do CoAP entenderam que protocolos mais simples poderiam ser usados. CoAP especifica um "Stop-and-Wait" [1] simplificado, com tentativas espaçadas exponencialmente no tempo ("Exponential Backoff") [2]. [1] https://en.wikipedia.org/wiki/Stop-and-wait_ARQ [2] https://en.wikipedia.org/wiki/Exponential_backoff 3. Breve revisão de protocolos de comunicação
  • 52. 3. Breve revisão de protocolos de comunicação Stop-and-wait Exponential Back Off
  • 53. Características do sistema observado: Variável: Temperatura Dinâmica: Lenta (minutos ou até mesmo horas) Elemento atuado: geladeira (on-off) Atuação somente para resfriar: desvantagem: dinâmica de resfriamento bem diferente da de aquecimento 4. Comparativo de sensores
  • 54. 4. Comparativo de sensores
  • 55. 4. Comparativo de sensores
  • 56. 4. Comparativo de sensores
  • 57. Termopares Vantagens: Simples e relativamente baratos Robustos e tem grande range de temperaturas (depende do tipo) Desvantagens: Não lineares, precisam de circuito externo para compensação (MAX6675 faz compensação e digitalização com resolução de 12bits) 4. Comparativo de sensores
  • 58. MAX6675 + Termopar Tipo K 4. Comparativo de sensores
  • 59. Esquema de conexão -- usa protocolo SPI (Serial Peripheral Interface) - 3 pinos. OK para o ESP32, mas ruim para ESP8266-01… 4. Comparativo de sensores
  • 60. Preço relativamente baixo no ML 4. Comparativo de sensores
  • 63. Contribuição Open Source! Com 7 (and counting…) 4. Comparativo de sensores
  • 64. Porém… Não é a prova d'água out-of-the-box -- precisa de poço termométrico. Precisa de 3 pinos do micro-controlador Fiquei assustado com a possibilidade de erro de +/- 3oC 4. Comparativo de sensores
  • 65. Sensor Integrado (I.C.) DS18b20 Vantagens: Interface digital, baixo erro, usa apenas 1 pino (parasite power!) Desvantagens: (que não afetam o meu caso): baixo range -55oC a +125oC e baixo tempo de resposta (em alguns casos mais de 10 segundos, devido ao encapsulamento a prova d'água) 4. Comparativo de sensores
  • 66. 4. Comparativo de sensores
  • 67. Exemplo de como o encapsulamento pode afetar (gráfico abaixo para LM35) Encapsulamento a prova d'água do DS18b20 adiciona bastante tempo para estabilizar a leitura. 4. Comparativo de sensores
  • 68. Ausência de Biblioteca One-Wire nativa para o ESP32? Sem problemas: https://github.com/DavidAntliff/esp32-ds18b20 - versão multi-dispositivo https://github.com/feelfreelinux/ds18b20 - versão simplificada para apenas 1 sensor 4. Comparativo de sensores
  • 69. 5. Comparativo de Atuadores Tipos de relé: Eletro-mecânico Estado Sólido 4. Comparativo de atuadores
  • 70. 5. Comparativo de atuadores
  • 71. Relés eletromecânicos cargas indutivas (ex: motor do compressor de uma geladeira) Arco voltáico - danifica os contatos do relé e diminui a vida útil. 5. Comparativo de atuadores
  • 72. Mas e o diodo de "flyback"? Até funciona, mas nos relés chineses (baratos, do aliexpress), ainda assim tive problemas com agarramento (sticking). Sem diodo flyback Com diodo flyback 5. Comparativo de atuadores
  • 73. Relé de estado sólido Não possui partes mecânicas == não sofre de agarramento Dependendo da carga, pode aquecer (e muito), se necessário deve-se utilizar um dissipador + cooler Isolamento físico (opto-acoplado) É basicamente um opto-acoplador (circuito de acionamento) + um Triac (circuito de carga) 5. Comparativo de atuadores
  • 74. 5. Comparativo de atuadores
  • 75. = 5. Comparativo de atuadores
  • 76. 6. Estudo de Caso
  • 77. 6. Estudo de Caso
  • 78. 6. Estudo de Caso
  • 79. 6. Estudo de Caso
  • 80. 6. Estudo de Caso
  • 81. 6. Estudo de Caso
  • 84. Docker component: mqtt: image: 'donatoaz/mymosquitto' ports: - "1883:1883" - "9001:9001" volumes: - /home/donato/cervejator/mqtt/config:/mqtt/config:ro - /home/donato/cervejator/mqtt/data:/mqtt/data - /home/donato/cervejator/mqtt/log:/mqtt/log 7. Projeto
  • 85. donato@porter ~/mosquitto $ cat config/mosquitto.conf # Place your local configuration in /mqtt/config/conf.d/ pid_file /var/run/mosquitto.pid persistence true persistence_location /mqtt/data/ #user mosquitto allow_anonymous true port 1883 log_dest file /mqtt/log/mosquitto.log log_dest stdout log_type all connection_messages true log_timestamp true include_dir /mqtt/config/conf.d 7. Projeto
  • 86. Banco de Dados Postgresql Docker Component db: image: postgres environment: POSTGRES_DB: cervejator POSTGRES_USER: **** POSTGRES_PASSWORD: **** 7. Projeto
  • 87. Key-value Store - Redis DB Docker Component redis: image: redis:3.2 7. Projeto
  • 88. Assinante MQTT É uma Rake Task (Roda em seu próprio processo, mas tem acesso ao ambiente Rails da aplicação Web). Contém um cliente MQTT que assina ao tópico: "sensor/#" Para cada mensagem que recebe do tipo "sensor/#": 1. Cria tarefa para armazenar assíncronamente o dado -- não tem de ficar bloqueado esperando uma operação de E/S 2. Faz um broadcast do valor recebido nos Canais Active Cable para stream em tempo real no browser do cliente 7. Projeto
  • 89. Docker Component: subscriber: build: context: . dockerfile: Dockerfile.subscriber restart: always environment: RAILS_ENV: "production" REDIS_URL: "redis://redis:6379" MQTT_BROKER_HOST: "mqtt" MQTT_BROKER_PORT: "1883" command: bundle exec rake mqtt:subscriber volumes: - /home/donato/cervejator:/web depends_on: - redis - db - mqtt 7. Projeto
  • 90. Background Jobs - Resque Processamento Assíncrono de Tarefas: 1. Execução de escritas no banco de dados - PersistDataJob class PersistDataJob < ApplicationJob queue_as :readings def perform(datum) Datum.create(datum) end end 7. Projeto
  • 91. Escalonador de malhas de controle $ cat config/schedule.yml development: &development ScheduleControlLoopsJob: description: 'Polls control loops' queue: 'control_loops' every: - '20s' test: <<: *development production: <<: *development class ScheduleControlLoopsJob < ApplicationJob queue_as :control_loops def perform ControlLoop.all.each do |cl| next unless cl.mode == "auto" if Time.now >= cl.next_run ControlLoopJob.perform_later(cl.id) end if cl.missed_deadline? ActiveJob::Base.logger.error "Control Loop ##{cl.id}:#{cl.name} is missed deadline!" end end end end 7. Projeto
  • 92. Background Jobs - Resque Processamento Assíncrono de Tarefas: 2. Execução das malhas de controle com envio de mensagem MQTTT class ControlLoopJob < ApplicationJob queue_as :run_control_loops def perform(control_loop_id) ctrl = ControlLoop.find(control_loop_id) action = ctrl.run return if action == :inactive cli = MQTT::Client.connect(host: ENV['MQTT_BROKER_HOST'], username: 'mosquitto', port: ENV['MQTT_BROKER_PORT']) cli.publish("actuator/#{ctrl.actuator.write_key}", action, false, 1) cli.disconnect() ctrl.update_attribute(:next_run, Time.now + ctrl.sampling_rate.seconds) end end 7. Projeto
  • 93. Stream de dados em tempo real via websockets usando Action Cable Server side (ruby): class SensorChannel < ApplicationCable::Channel def subscribed sensor = Sensor.find(params[:id]) stream_for sensor, coder: ActiveSupport::JSON do |message| transmit message end end end class ActuatorChannel < ApplicationCable::Channel def subscribed actuator = Actuator.find(params[:id]) stream_for actuator, coder: ActiveSupport::JSON do |message| transmit message end end end 7. Projeto
  • 94. App.cable.subscriptions.create { channel: "SensorChannel", id: sensor_id }, received: (data) -> @addDataToChart data Stream de dados em tempo real via websockets usando Action Cable Client side (coffeescript): 7. Projeto
  • 96. initialize_gpio Configurando as entradas e saídas do ESP32 void initialize_gpio(void) { gpio_pad_select_gpio(ACTUATOR_GPIO); gpio_set_direction(ACTUATOR_GPIO, GPIO_MODE_OUTPUT); ds18b20_init(14); } GPIO = General Purpose Input/Output 7. Projeto
  • 97. Esp_event_loop_init Evita esperas bloqueadas, a própria lib do ESP-IDF se encarrega de criar uma task que chama este callback sempre que há um novo evento. static esp_err_t event_handler(void *ctx, system_event_t *event) { switch (event->event_id) { case SYSTEM_EVENT_STA_START: ESP_LOGI(TAG, "System started, going to connect to wifi."); wifi_connect(); break; case SYSTEM_EVENT_STA_GOT_IP: ESP_LOGI(TAG, "Got IP, conn to MQTT. %s : %d, user: %s, pass: %s", MQTT_HOST, MQTT_PORT, MQTT_USER, MQTT_PASS); esp_mqtt_start(MQTT_HOST, MQTT_PORT, "esp-mqtt", "", ""); break; case SYSTEM_EVENT_STA_DISCONNECTED: ESP_LOGI(TAG, "WiFi lost, stop MQTTT and attempt a reconnect."); esp_mqtt_stop(); esp_wifi_connect(); break; default: break; } return ESP_OK; } 7. Projeto
  • 98. typedef enum { SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */ SYSTEM_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */ SYSTEM_EVENT_STA_START, /**< ESP32 station start */ SYSTEM_EVENT_STA_STOP, /**< ESP32 station stop */ SYSTEM_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */ SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */ SYSTEM_EVENT_STA_GOT_IP, /**< ESP32 station got IP from connected AP */ SYSTEM_EVENT_STA_LOST_IP, /**< ESP32 station lost IP and the IP is reset to 0 */ SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */ SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */ } system_event_id_t; 7. Projeto
  • 99. Inicialização da lib MQTT esp_mqtt_init(mqtt_status_cb, mqtt_message_cb, 256, 2000); Status Call Back Function Chamado sempre que o status (conectado, desconectado) muda Status Call Back Function Chamado sempre que é recebida uma mensagem Buffer Size para leitura/escrita de payloads Timeout para comandos enviados ao árbitro (em mS) 7. Projeto
  • 100. Callback de mensagens recebidas (atuador) static void mqtt_message_cb(const char *topic, uint8_t *payload, size_t len) { printf("incomingt%s:%s (%d)n", topic, payload, (int)len); if (strcmp((char *) payload,"on") == 0) { ESP_LOGI(TAG, "Setting pin %d to high", ACTUATOR_GPIO); gpio_set_level(ACTUATOR_GPIO, 1); } else if (strcmp((char *) payload, "off") == 0) { ESP_LOGI(TAG, "Setting pin %d to low", ACTUATOR_GPIO); gpio_set_level(ACTUATOR_GPIO, 0); } else { ESP_LOGI(TAG, "Received an unknown actuator command"); } } 7. Projeto
  • 101. Callback de Status: Se conectado, começa a publicar. Se desconectado, para de publicar e tenta conectar novamente... static void mqtt_status_cb(esp_mqtt_status_t status) { switch (status) { case ESP_MQTT_STATUS_CONNECTED: ESP_LOGI(TAG, "Cool, we got a CONNECT ACK from broker!"); esp_mqtt_subscribe(ACTUATOR_WRITE_KEY, 0); xTaskCreatePinnedToCore(process, "process", 8192, NULL, 10, &task, 1); break; case ESP_MQTT_STATUS_DISCONNECTED: ESP_LOGI(TAG, "Shoot, MQTT disconnected! Going to retry... Stopping publishing task."); vTaskDelete(task); vTaskDelay(5000 / portTICK_PERIOD_MS); esp_mqtt_start(MQTT_HOST, MQTT_PORT, "esp-mqtt", "", ""); break; } } 7. Projeto
  • 103. 8. Aplicação Real (Mostrar em tempo real)
  • 105. 9. Propostas de Melhoria Usar o EMQTT (Erlang) ao invés do Mosquitto
  • 106. 9. Propostas de Melhoria Usar CoAP, de modo que o aplicativo web seja mais passivo e os dispositivos implementem e exponham o que quiserem (aplicativo web vira um "Registry" -- https://www.monterail.com/blog/2016/iot-with-elixir-and-coap-part-1-example-on-how-to-easily- prototype-and-build-an-iot-platform
  • 107. 9. Propostas de Melhoria
  • 108. Usar AnyCable ao invés de action cable https://evilmartians.com/chronicles/anycable-actioncable-on-steroids https://github.com/anycable/anycable-go 9. Propostas de Melhoria
  • 109. 10. Onde Encontrar? with 'github.com/donatoaz' do esp8266-esp01-MAX6675 - conectando termopar ao esp8266 cervejator - aplicação dockerizada apresentada Esp32-mqtt-cervejator - cliente mqtt para o esp32 end @donatoaz (twitter)
  • 111. Referências MQTT, Docker e Wireshark https://github.com/toke/docker-mosquitto https://cloud.google.com/community/tutorials/docker- compose-on-container-optimized-os https://docs.docker.com/compose/compose-file/com pose-file-v2/#container_name https://mosquitto.org/man/mosquitto-conf-5.html
  • 113. Lib MQTT para ESP32 https://github.com/tuanpmt/esp_mqtt https://github.com/256dpi/esp-mqtt
  • 114. Docker cheatsheet $ docker-compose up -- o BD ainda não existe, então: $ docker-compose run web bundle exec rake db:create db:migrate db:seed -- Por algum motivo, o yarn install não instalou as paradas, então: $ docker-compose run web yarn add jquery jquery-ujs amcharts lodash -- Os ativos estáticos também não existem ainda, então: $ docker-compose run web bundle exec rake assets:precompile