Versão 3.0
This commit is contained in:
214
README.md
214
README.md
@@ -1,50 +1,198 @@
|
||||
# Atividade 2 - Amaro
|
||||
# Atividade 3 - Streaming MQTT para ThingSpeak
|
||||
|
||||
Um projeto de um ESP32 conectado a três sensores para monitoramento inteligente de cozinha industrial:
|
||||
Sistema IoT embarcado em **ESP32** que monitora temperatura, umidade e gás com detecção avançada de incêndio, publicando dados simultaneamente em múltiplas plataformas cloud.
|
||||
|
||||
## Sensores
|
||||
- **DHT22**: Temperatura e Umidade
|
||||
- **MQ2**: Qualidade do ar / Detecção de gás
|
||||
- **DS1307**: RTC para timestamp
|
||||
## Visão Geral
|
||||
|
||||
## Atuadores
|
||||
- **Alarme Sonoro** (GPIO 4): Alerta para detecção de gás/incêndio
|
||||
- **Coifa/Exaustor** (GPIO 17): Remoção de gases e umidade
|
||||
- **Ar-condicionado** (GPIO 16): Controle de temperatura
|
||||
```
|
||||
ESP32 (DHT22 + MQ2)
|
||||
↓
|
||||
├─→ MQTT Broker (77.37.69.84:1883)
|
||||
│ ├─→ Ubidots (Dashboard CEO)
|
||||
│ └─→ NodeRed (Dashboard Local)
|
||||
│
|
||||
└─→ ThingSpeak Write API
|
||||
└─→ Armazenamento em Cloud + Analytics
|
||||
```
|
||||
|
||||
## Sistema de Integração MQTT
|
||||
## Requisitos da Atividade
|
||||
|
||||
### Broker
|
||||
- **Host**: 77.37.69.84:1883
|
||||
- **Tópico Publicação**: `cozinha` (JSON com tmp, umi, gas, alarme)
|
||||
- **Tópicos Subscrição**: `cozinha/max_tmp`, `cozinha/max_umi` (configuração remota)
|
||||
- ✅ Canal ThingSpeak com 4 campos
|
||||
- ✅ Publicação MQTT no broker
|
||||
- ✅ Integração ThingSpeak via Write API
|
||||
- ✅ Visualização de dados em gráficos
|
||||
- ✅ Testes de latência/estabilidade
|
||||
- ✅ Documentação técnica completa
|
||||
- ✅ Vídeo de demonstração
|
||||
|
||||
### Dashboards
|
||||
## Configuração Rápida
|
||||
|
||||
1. **Ubidots** (Cloud)
|
||||
- Device: `cozinha`
|
||||
- Histórico: 30+ dias
|
||||
- URL: https://ubidots.com
|
||||
### 1. Obter Credenciais ThingSpeak
|
||||
|
||||
2. **NodeRed** (Local)
|
||||
- URL: http://77.37.69.84:1880/dashboard/page1
|
||||
- Controle remoto de limiares via sliders
|
||||
Pegue suas credenciais do canal do Thingspeak no menu API Keys
|
||||
|
||||
|
||||
### 2. Atualizar Código
|
||||
|
||||
Edite [src/esp32-ntp-clock.ino](src/esp32-ntp-clock.ino):
|
||||
|
||||
```cpp
|
||||
// Linha ~35
|
||||
const unsigned long THINGSPEAK_CHANNEL_ID = SEU_CHANNEL_ID; // Substitua
|
||||
const char* THINGSPEAK_API_KEY = "SEU_API_KEY"; // Substitua
|
||||
```
|
||||
|
||||
### 3. Compilar e Enviar
|
||||
|
||||
```bash
|
||||
# Compilar com PlatformIO
|
||||
pio run
|
||||
|
||||
# Enviar para o ESP32
|
||||
pio run -t upload
|
||||
|
||||
# Monitorar logs
|
||||
pio device monitor --baud 115200
|
||||
```
|
||||
|
||||
## ThingSpeak Setup
|
||||
|
||||
### Criar Canal
|
||||
|
||||
1. Acesse https://thingspeak.com/channels
|
||||
2. **New Channel** com este formato:
|
||||
|
||||
| Field | Nome | Tipo | Unidade |
|
||||
|-------|------|------|---------|
|
||||
| 1 | `temperatura` | Float | °C |
|
||||
| 2 | `umidade` | Float | % |
|
||||
| 3 | `gas_adc` | Integer | ADC (0-1023) |
|
||||
| 4 | `alarme_status` | Integer | Enum (0-4) |
|
||||
|
||||
## Variáveis Publicadas
|
||||
|
||||
### MQTT (Tópico: `cozinha`)
|
||||
|
||||
```json
|
||||
{
|
||||
"tmp": 26.50, // °C
|
||||
"umi": 65.30, // %
|
||||
"gas": 912, // ADC
|
||||
"alarme": 0 // 0=NOMINAL, 1=GAS, 2=TEMP_ALTA, 3=UMIDADE_ALTA, 4=INCENDIO
|
||||
}
|
||||
```
|
||||
|
||||
### ThingSpeak Write API
|
||||
|
||||
```
|
||||
POST /update
|
||||
Parameters:
|
||||
api_key: [SEU_WRITE_API_KEY]
|
||||
field1: temperatura (°C)
|
||||
field2: umidade (%)
|
||||
field3: gas_adc (0-1023)
|
||||
field4: alarme_status (0-4)
|
||||
```
|
||||
|
||||
## Verificação de Dados
|
||||
|
||||
### Dashboard ThingSpeak
|
||||
|
||||
```bash
|
||||
# Abra no navegador:
|
||||
https://thingspeak.com/channels/SEU_CHANNEL_ID
|
||||
```
|
||||
|
||||
Você deverá ver:
|
||||
- 4 gráficos em tempo real
|
||||
- Histórico de dados
|
||||
- Últimas entradas
|
||||
|
||||
### MQTT (Linha de Comando)
|
||||
|
||||
```bash
|
||||
# Subscrever ao tópico
|
||||
mosquitto_sub -h 77.37.69.84 -t cozinha
|
||||
|
||||
# Resultado esperado:
|
||||
{"tmp": 26.50, "umi": 65.30, "gas": 912, "alarme": 0}
|
||||
{"tmp": 26.51, "umi": 65.29, "gas": 913, "alarme": 0}
|
||||
...
|
||||
```
|
||||
|
||||
## 🧪 Testes Implementados
|
||||
|
||||
### Teste 1: Validação de Credenciais
|
||||
```bash
|
||||
bash test_thingspeak.sh
|
||||
```
|
||||
Valida se Channel ID e API Key funcionam **antes** de enviar para o ESP32.
|
||||
|
||||
### Teste 2: Latência MQTT
|
||||
```bash
|
||||
bash test_mqtt_latency.sh
|
||||
```
|
||||
Mede tempo de entrega de mensagens (esperado: ~100-200ms).
|
||||
|
||||
### Teste 3: Logs do Device
|
||||
```bash
|
||||
pio device monitor --baud 115200 | grep ThingSpeak
|
||||
```
|
||||
Monitora sucesso/falha de cada publicação.
|
||||
|
||||
## Resultados Esperados
|
||||
|
||||
Após compilação bem-sucedida:
|
||||
|
||||
```
|
||||
[WiFi] Conectado!
|
||||
[MQTT] Conectado!
|
||||
[ThingSpeak] Inicializado
|
||||
[MQTT] Publicando: {"tmp": 26.50, "umi": 65.30, "gas": 912, "alarme": 0}
|
||||
[ThingSpeak] Dados enviados com sucesso
|
||||
```
|
||||
|
||||
**A cada 15 segundos:**
|
||||
- Nova leitura dos sensores
|
||||
- Publicação MQTT no broker
|
||||
- Envio para ThingSpeak via HTTP
|
||||
|
||||
## Arquivos do Projeto
|
||||
|
||||
```
|
||||
├── src/
|
||||
│ └── esp32-ntp-clock.ino # Código principal
|
||||
├── Relatorio/
|
||||
│ └── atividade3.qmd # Documentação formal (PDF)
|
||||
├── tst/
|
||||
│ └── test_mqtt_latency.sh # Teste de latência MQTT
|
||||
├── platformio.ini # Configuração PlatformIO
|
||||
├── README.md # Este arquivo
|
||||
└── test_thingspeak.sh # Script validação ThingSpeak
|
||||
```
|
||||
|
||||
## Links Úteis
|
||||
|
||||
- **ThingSpeak**: https://thingspeak.com/
|
||||
- **PlatformIO**: https://platformio.org/
|
||||
- **MQTT Broker**: mosquitto.amarojr.com
|
||||
- **NodeRed**: http://nodered.amarojr.com/dashboard/page1
|
||||
|
||||
## Documentação
|
||||
|
||||
Relatório técnico completo disponível em `Relatorio/relatorio.pdf` com:
|
||||
- Arquitetura de sistema
|
||||
- Fluxo de dados MQTT
|
||||
- Validação de testes
|
||||
- Guia de operação dos dashboards
|
||||
Para documentação formal completa, consulte:
|
||||
- [Relatório Técnico](Relatorio/relatorio.qmd)
|
||||
|
||||
## Compilando
|
||||
## Vídeo Demonstração
|
||||
|
||||
Utilizei o [PlatformIO](https://platformio.org). Para compilar:
|
||||
Video postado no [youtube](https://youtu.be/8xOyGy04oZo)
|
||||
|
||||
```
|
||||
pio run
|
||||
```
|
||||
---
|
||||
|
||||
**Status**: Operacional
|
||||
**Versão**: 3.0
|
||||
**Última atualização**: 2026-02-19
|
||||
**Autor**: Amaro Lopes
|
||||
|
||||
## Simulação
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 58 KiB |
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Sistema de Monitoramento Inteligente de Cozinha com ESP32"
|
||||
subtitle: "Integração MQTT com Ubidots para IoT Industrial"
|
||||
subtitle: "Integração MQTT com ThingSpeak para IoT Industrial"
|
||||
author: "Amaro Lopes"
|
||||
institute: "Faculdade de Tecnologia FIAP"
|
||||
date: today
|
||||
@@ -15,6 +15,7 @@ format:
|
||||
geometry:
|
||||
- margin=1in
|
||||
fontfamily: libertinus
|
||||
mermaid-format: png
|
||||
include-before-body:
|
||||
text: |
|
||||
\frontmatter
|
||||
@@ -28,9 +29,9 @@ execute:
|
||||
|
||||
# Introdução
|
||||
|
||||
Este projeto implementa um **sistema inteligente de monitoramento para cozinha industrial** utilizando um microcontrolador ESP32 conectado a múltiplos sensores. O sistema detecta condições anormais de operação e ativa atuadores para garantir segurança, integrando-se com a plataforma Ubidots para monitoramento remoto via dashboard interativo, com fallback para um dashboard nodered.
|
||||
Este projeto implementa um **sistema inteligente de monitoramento para cozinha industrial** utilizando um microcontrolador ESP32 conectado a múltiplos sensores. O sistema detecta condições anormais de operação e ativa atuadores para garantir segurança, integrando-se com a plataforma **ThingSpeak** para monitoramento remoto via dashboard interativo.
|
||||
|
||||
A integração é realizada através de um broker MQTT em **77.37.69.84** que faz forward automático dos dados para a plataforma Ubidots, permitindo visualização em tempo real e histórico de dados com widgets interativos. Alternativamente, um dashboard NodeRed está disponível em **77.37.69.84:1880/dashboard/page1** para monitoramento.
|
||||
A integração é realizada através de um broker MQTT em **77.37.69.84** que recebe publicações de telemetria do ESP32 e encaminha os dados para a plataforma ThingSpeak (Canal ID: **3249180**), permitindo visualização em tempo real, histórico de dados com gráficos interativos e alertas configuráveis.
|
||||
|
||||
## Contexto
|
||||
|
||||
@@ -48,9 +49,9 @@ Este sistema fornece monitoramento 24/7 com resposta automática a situações c
|
||||
## Objetivos Gerais
|
||||
1. Monitorar três parâmetros críticos em ambiente de cozinha industrial
|
||||
2. Detectar anomalias e ativar sistemas de proteção automaticamente
|
||||
3. Integrar dados com plataforma IoT profissional (Ubidots)
|
||||
3. Integrar dados com plataforma IoT profissional em nuvem (ThingSpeak) com dashboard web
|
||||
4. Permitir configuração remota de limiares via MQTT
|
||||
5. Garantir transmissão confiável de dados em tempo real
|
||||
5. Garantir transmissão confiável de dados em tempo real com múltiplos canais (MQTT + HTTP)
|
||||
|
||||
## Parâmetros Monitorados
|
||||
|
||||
@@ -67,59 +68,45 @@ Este sistema fornece monitoramento 24/7 com resposta automática a situações c
|
||||
|
||||
# Diagrama de Arquitetura
|
||||
|
||||
```{mermaid}
|
||||
%%| fig-width: 7
|
||||
graph TB
|
||||
subgraph "Camada de Sensores"
|
||||
DHT22["<b>DHT22</b><br/>Temperatura &<br/>Umidade<br/>GPIO 32"]
|
||||
MQ2["<b>MQ2</b><br/>Qualidade do Ar<br/>(Gás)<br/>GPIO 33 ADC"]
|
||||
RTC["<b>RTC DS1307</b><br/>Timer para verificação de incêndio<br/>I2C"]
|
||||
end
|
||||
|
||||
subgraph "Camada de Processamento"
|
||||
ESP32["<b>ESP32 DevKit V4</b><br/>Dual-core 240MHz<br/>WiFi + BLE"]
|
||||
LOGIC["Lógica de<br/>Detecção de<br/>Alarmes"]
|
||||
end
|
||||
|
||||
subgraph "Camada de Atuadores"
|
||||
ALARM["<b>Alarme Sonoro</b><br/>Sirene/>GPIO 4"]
|
||||
COIFA["<b>Coifa/Exaustor</b><br/>Motor 220V<br/>GPIO 17"]
|
||||
AC["<b>A/C</b><br/>Unidade comercial<br/>GPIO 16"]
|
||||
end
|
||||
|
||||
subgraph "Rede MQTT"
|
||||
WiFi["<b>WiFi</b><br/>Wokwi-GUEST<br/>2.4GHz"]
|
||||
MQTT["<b>Broker MQTT</b><br/>77.37.69.84:1883<br/>Mosquitto"]
|
||||
end
|
||||
|
||||
subgraph "Cloud - Ubidots"
|
||||
UBIDOTS["<b>Plataforma Ubidots</b><br/>Dashboard<br/>Histórico de Dados<br/>Alertas"]
|
||||
NODERED["<b>NodeRed</b><br/>Dashboard Fallback<br/>77.37.69.84:1880/dashboard/page1"]
|
||||
end
|
||||
|
||||
DHT22 --> ESP32
|
||||
MQ2 --> ESP32
|
||||
RTC --> ESP32
|
||||
ESP32 --> LOGIC
|
||||
LOGIC --> ALARM
|
||||
LOGIC --> COIFA
|
||||
LOGIC --> AC
|
||||
ESP32 -->|Publica| WiFi
|
||||
WiFi --> MQTT
|
||||
MQTT -->|Subscreve| ESP32
|
||||
MQTT -->|Forward| UBIDOTS
|
||||
MQTT --> NODERED
|
||||
**Componentes e Fluxo do Sistema:**
|
||||
|
||||
```
|
||||
CAMADA DE SENSORES
|
||||
├─ DHT22 (GPIO 32): Temperatura & Umidade
|
||||
├─ MQ2 (GPIO 33): Qualidade do Ar (Gás)
|
||||
└─ RTC DS1307 (I2C): Timer para verificação de incêndio
|
||||
|
||||
CAMADA DE PROCESSAMENTO
|
||||
├─ ESP32 DevKit V4 (Dual-core 240MHz, WiFi + BLE)
|
||||
└─ Lógica de Detecção de Alarmes
|
||||
|
||||
CAMADA DE ATUADORES
|
||||
├─ Alarme Sonoro (GPIO 4): Sirene
|
||||
├─ Coifa/Exaustor (GPIO 17): Motor 220V
|
||||
└─ Ar-condicionado (GPIO 16): Unidade comercial
|
||||
|
||||
REDE MQTT
|
||||
├─ WiFi (Wokwi-GUEST, 2.4GHz)
|
||||
└─ Broker MQTT (77.37.69.84:1883)
|
||||
|
||||
CLOUD - THINGSPEAK
|
||||
├─ Plataforma ThingSpeak (Canal ID: 3249180)
|
||||
├─ Dashboard interativo
|
||||
├─ Histórico de dados
|
||||
└─ Alertas por email
|
||||
```
|
||||
|
||||
## Fluxo de Dados Simplificado
|
||||
|
||||
1. **Leitura**: Sensores capturam dados continuamente (a cada 2s)
|
||||
2. **Processamento**: ESP32 verifica limiares e detecta alarmes
|
||||
3. **Publicação**: Dados publicados em tópico MQTT `cozinha`
|
||||
4. **Roteamento**: Broker em 77.37.69.84 recebe e roteia para múltiplos dashboards
|
||||
5. **Integração Cloud**: Ubidots consome via bridge MQTT automático
|
||||
6. **Integração Fallback**: NodeRed consome dados em tempo real
|
||||
7. **Visualização**: Dashboards exibem em tempo real com widgets
|
||||
1. **Leitura**: Sensores (DHT22, MQ2) são lidos a cada iteração do loop
|
||||
2. **Processamento**: ESP32 verifica limiares e detecta alarmes (máxima prioridade: incêndio → gás → temperatura → umidade)
|
||||
3. **Publicação**: A cada 15 segundos, dados publicados em **dois canais**:
|
||||
- MQTT (tópico `cozinha`) com JSON completo
|
||||
- HTTP (ThingSpeak) com campos individuais
|
||||
4. **Disseminação MQTT**: Broker 77.37.69.84 roteia dados para clientes inscritos (NodeRed, CLI, dashboards)
|
||||
5. **Armazenamento Cloud**: ThingSpeak recebe via HTTP e armazena com histórico de 15 dias
|
||||
6. **Monitoramento Remoto**: NodeRed Dashboard consome MQTT em tempo real; ThingSpeak exibe gráficos e alertas
|
||||
7. **Controle Local**: Atuadores (alarme, coifa, A/C) ativados baseado no estado de alarme
|
||||
|
||||
# Descrição dos Componentes
|
||||
|
||||
@@ -152,12 +139,13 @@ graph TB
|
||||
|
||||
## Publicação: ESP32 → Broker (Tópico: `cozinha`)
|
||||
|
||||
**Intervalo**: 2 segundos
|
||||
**Intervalo**: 15 segundos
|
||||
**Tipo**: JSON
|
||||
**Exemplo**:
|
||||
|
||||
```json
|
||||
{
|
||||
"ts": 1771518275555419000,
|
||||
"tmp": 28.50,
|
||||
"umi": 65.20,
|
||||
"gas": 850,
|
||||
@@ -191,7 +179,7 @@ O sistema recebe comandos de configuração remota em tempo real, provenientes d
|
||||
| NodeRed / CLI | `cozinha/max_tmp` | Float | 20 a 60 | 30.0 | Limite máximo de temperatura (°C) - Reconfigurável |
|
||||
| NodeRed / CLI | `cozinha/max_umi` | Float | 30 a 90 | 70.0 | Limite máximo de umidade (%) - Reconfigurável |
|
||||
|
||||
A configuração pode ser feita através dos sliders do **NodeRed Dashboard** (http://77.37.69.84:1880/dashboard/page1), como visto na apresentação passada.
|
||||
A configuração pode ser feita através dos sliders do **NodeRed Dashboard** (http://nodered.amarojr.com/dashboard/page1), como visto na apresentação passada.
|
||||
|
||||
**Exemplo de comandos para configuração:**
|
||||
|
||||
@@ -250,52 +238,50 @@ $$\text{Incêndio} = (\Delta T > 5°C) \land (\Delta UR < -10\%) \text{ em 30 se
|
||||
|
||||
## Sequência de Operação Completa
|
||||
|
||||
```{mermaid}
|
||||
%%| fig-width: 7.5
|
||||
sequenceDiagram
|
||||
participant DHT as DHT22<br/>(Sensor)
|
||||
participant MQ as MQ2<br/>(Sensor)
|
||||
participant ESP as ESP32<br/>(Processador)
|
||||
participant WiFi as WiFi<br/>
|
||||
participant Broker as Broker MQTT<br/>77.37.69.84
|
||||
participant Ubidots as Ubidots<br/>(Cloud)
|
||||
participant Dashboard as Dashboard<br/>(Visualização)
|
||||
|
||||
loop A cada 2 segundos
|
||||
DHT->>ESP: Temperatura, Umidade
|
||||
MQ->>ESP: ADC (Gás)
|
||||
ESP->>ESP: Detecta Alarmes
|
||||
ESP->>WiFi: JSON payload
|
||||
WiFi->>Broker: PUBLISH cozinha
|
||||
Broker->>Ubidots: Forward automático
|
||||
Ubidots->>Dashboard: Atualiza widgets
|
||||
end
|
||||
```
|
||||
**Fluxo temporal (a cada 15 segundos):**
|
||||
|
||||
## Integração MQTT com Ubidots
|
||||
1. DHT22 envia temperatura e umidade para ESP32
|
||||
2. MQ2 envia leitura ADC (gás) para ESP32
|
||||
3. ESP32 detecta alarmes baseado em limiares
|
||||
4. ESP32 forma payload JSON e envia em **duas vias simultâneas**:
|
||||
- **Via A (MQTT)**: Publica JSON no broker MQTT tópico `cozinha` para disseminação em tempo real
|
||||
- **Via B (HTTP)**: Envia campos individuais para ThingSpeak via HTTP com Write API Key (biblioteca ThingSpeak)
|
||||
5. Broker MQTT em 77.37.69.84 roteia mensagens para clientes inscritos (NodeRed, dashboards, CLI)
|
||||
6. ThingSpeak recebe dados via HTTP direto do ESP32 e atualiza dashboard e gráficos em tempo real
|
||||
7. Ambos os dashboards (MQTT + ThingSpeak) exibem dados com widgets
|
||||
8. Ciclo repete a cada 15 segundos
|
||||
|
||||
**Tipo de Integração**: Bridge MQTT com Forward Automático
|
||||
## Integração com ThingSpeak (HTTP Direto)
|
||||
|
||||
**Configuração do Forward**:
|
||||
**Tipo de Integração**: HTTP direto via Biblioteca ThingSpeak (NÃO é MQTT bridge)
|
||||
|
||||
- **Source Broker**: 77.37.69.84:1883
|
||||
- **Tópico Source**: `cozinha`
|
||||
- **Destination**: Ubidots Cloud
|
||||
- **Autenticação**: Token do device Ubidots
|
||||
**Configuração da Integração**:
|
||||
|
||||
**Processamento no Ubidots**:
|
||||
- **Origem**: ESP32 (após leitura de sensores)
|
||||
- **Método**: HTTP POST com Write API Key
|
||||
- **Destino**: ThingSpeak Cloud
|
||||
- **Canal ID**: 3249180
|
||||
- **Autenticação**: Write API Key (AAAQPGQ90E2JG0UH)
|
||||
- **Intervalo de Publicação**: 15 segundos
|
||||
- **Implementação**: Biblioteca Arduino ThingSpeak com `ThingSpeak.setField()` e `ThingSpeak.writeFields()`
|
||||
|
||||
- Cada variável JSON é extraída e armazenada
|
||||
- Histórico de 30+ dias
|
||||
- Alertas configuráveis por variável
|
||||
**Fluxo Dual de Dados**:
|
||||
|
||||
O sistema implementa **dois canais de comunicação paralelos e independentes**:
|
||||
|
||||
| Canal | Tecnologia | Destino | Propósito |
|
||||
|-------|-----------|---------|------------|
|
||||
| **Canal 1** | MQTT | Broker 77.37.69.84 | Publicação em tempo real para disseminação a múltiplos clientes |
|
||||
| **Canal 2** | HTTP | ThingSpeak Cloud | Armazenamento profissional com dashboard web, alertas e análises |
|
||||
|
||||
**Processamento no ThingSpeak**:
|
||||
|
||||
- 4 campos de dados mapeados via HTTP (temperatura, umidade, gás, alarme)
|
||||
- Histórico de dados configurável (padrão: 15 dias)
|
||||
- Alertas por email configuráveis por campo
|
||||
- Dashboard com widgets em tempo real
|
||||
|
||||
**Processamento no NodeRed**:
|
||||
|
||||
- Consumo direto de mensagens MQTT em tempo real
|
||||
- Acesso em: **http://77.37.69.84:1880/dashboard/page1**
|
||||
- Controle remoto de limiares via sliders
|
||||
- Visualização gráfica em tempo real
|
||||
- Gráficos com análise de tendências
|
||||
- API REST para consultas de dados históricos
|
||||
|
||||
|
||||
# Ciclo de Operação
|
||||
@@ -304,44 +290,70 @@ sequenceDiagram
|
||||
|
||||
### Parte 1: Leitura e Processamento
|
||||
|
||||
```{mermaid}
|
||||
%%| fig-width: 6.5
|
||||
flowchart LR
|
||||
A["INÍCIO<br/>Loop"] --> B{"MQTT<br/>OK?"}
|
||||
B -->|Não| C["Reconecta"]
|
||||
C --> D["Lê Sensores"]
|
||||
B -->|Sim| D
|
||||
D --> E["DHT22"]
|
||||
D --> F["MQ2"]
|
||||
D --> G["RTC"]
|
||||
E --> H["Detecta<br/>Alarmes"]
|
||||
F --> H
|
||||
G --> H
|
||||
H --> I["Publica"]
|
||||
```
|
||||
INÍCIO (Loop)
|
||||
|
|
||||
V
|
||||
MQTT OK?
|
||||
|--- Não --> Reconecta WiFi/MQTT
|
||||
| |
|
||||
| V
|
||||
|--- Sim --> Lê Sensores
|
||||
├─ DHT22 (Temperatura/Umidade)
|
||||
├─ MQ2 (Gás)
|
||||
└─ RTC (Timestamp)
|
||||
|
|
||||
V
|
||||
Detecta Alarmes
|
||||
|
|
||||
V
|
||||
Publica em DOIS CANAIS:
|
||||
├─ Via MQTT: tópico 'cozinha' (JSON completo)
|
||||
└─ Via HTTP: ThingSpeak Fields (campos individuais)
|
||||
|
|
||||
V
|
||||
Ativa Atuadores
|
||||
|
|
||||
V
|
||||
Aguarda 15s
|
||||
|
|
||||
V
|
||||
(Volta ao início)
|
||||
```
|
||||
|
||||
### Parte 2: Decisão de Alarmes
|
||||
|
||||
```{mermaid}
|
||||
%%| fig-width: 6.5
|
||||
flowchart LR
|
||||
H["Detecta<br/>Alarmes"] --> G{"Incêndio?"}
|
||||
G -->|Sim| S4["Estado = 4"]
|
||||
G -->|Não| G2{"Gás<br>>940?"}
|
||||
G2 -->|Sim| S1["Estado = 1"]
|
||||
G2 -->|Não| T{"Temp<br/>Alta?"}
|
||||
T -->|Sim| S2["Estado = 2"]
|
||||
T -->|Não| U{"Umidade<br/>Alta?"}
|
||||
U -->|Sim| S3["Estado = 3"]
|
||||
U -->|Não| S0["Estado = 0"]
|
||||
S4 --> M["Publica<br/>MQTT"]
|
||||
S1 --> M
|
||||
S2 --> M
|
||||
S3 --> M
|
||||
S0 --> M
|
||||
M --> A["Ativa<br/>Atuadores"]
|
||||
A --> B["Aguarda 2s"]
|
||||
B --> H
|
||||
```
|
||||
Detecta Alarmes
|
||||
|
|
||||
V
|
||||
Incêndio (ΔT>5°C + ΔUR<-10%)?
|
||||
|--- SIM --> Estado = 4 (INCENDIO)
|
||||
| Ativa: Alarme + Coifa + A/C
|
||||
|
|
||||
|--- NÃO --> Gás > 940 ADC?
|
||||
|--- SIM --> Estado = 1 (GAS)
|
||||
| Ativa: Alarme + Coifa
|
||||
|
|
||||
|--- NÃO --> Temperatura > 30°C?
|
||||
|--- SIM --> Estado = 2 (TEMP_ALTA)
|
||||
| Ativa: Ar-condicionado
|
||||
|
|
||||
|--- NÃO --> Umidade > 70%?
|
||||
|--- SIM --> Estado = 3 (UMIDADE_ALTA)
|
||||
| Ativa: Coifa
|
||||
|
|
||||
|--- NÃO --> Estado = 0 (NOMINAL)
|
||||
Desativa tudo
|
||||
|
|
||||
V
|
||||
Publica MQTT
|
||||
|
|
||||
V
|
||||
Ativa Atuadores
|
||||
|
|
||||
V
|
||||
(Aguarda 15s)
|
||||
```
|
||||
# Validação e Testes
|
||||
|
||||
@@ -351,207 +363,385 @@ A validação do sistema foi realizada através dos seguintes testes:
|
||||
|
||||
### Teste 1: Conectividade WiFi
|
||||
|
||||
- Conexão com SSID Wokwi-GUEST
|
||||
- Obtenção de IP via DHCP
|
||||
**Objetivo**: Verificar conexão com rede WiFi Wokwi-GUEST
|
||||
|
||||
**Procedimento**:
|
||||
- Inicializar ESP32
|
||||
- Aguardar conexão com WiFi
|
||||
- Confirmar obtenção de IP
|
||||
|
||||
**Resultado Esperado**:
|
||||
```
|
||||
[WiFi] Conectando.....
|
||||
[WiFi] Conectado!
|
||||
```
|
||||
|
||||
**Status**: PASSOU
|
||||
|
||||
---
|
||||
|
||||
### Teste 2: Conectividade MQTT
|
||||
|
||||
- Conexão com broker 77.37.69.84:1883
|
||||
- Publicação de mensagens a cada 2s
|
||||
- Recebimento de comandos de configuração
|
||||
**Objetivo**: Verificar conexão com broker MQTT em 77.37.69.84:1883
|
||||
|
||||
### Teste 3: Leitura de Sensores
|
||||
**Procedimento**:
|
||||
- Após WiFi conectado, tentar conexão MQTT
|
||||
- Subscrever tópicos `cozinha/max_tmp` e `cozinha/max_umi`
|
||||
- Publicar mensagens a cada 15 segundos
|
||||
|
||||
- DHT22: Temperatura entre 15-35°C (simulado)
|
||||
- DHT22: Umidade entre 40-80% (simulado)
|
||||
- MQ2: ADC entre 0-1023 (simulado)
|
||||
|
||||
### Teste 4: Detecção de Alarmes
|
||||
|
||||
- Temperatura > 30°C ativa ar-condicionado
|
||||
- Umidade > 70% ativa coifa
|
||||
- Gás > 940 ativa alarme + coifa
|
||||
- Padrão de incêndio (ΔT>5°C + ΔUR<-10%) ativa todos
|
||||
|
||||
### Teste 5: Integração Ubidots
|
||||
|
||||
- Dados recebidos no dashboard
|
||||
- Histórico armazenado
|
||||
- Widgets atualizados em tempo real
|
||||
|
||||
## Monitoramento de Dados
|
||||
|
||||
**Captura do Monitor Serial** (origin dos dados):
|
||||
**Resultado Esperado**:
|
||||
```
|
||||
[SETUP] Iniciando sistema...
|
||||
[DHT] Inicializado
|
||||
[WiFi] Conectando.....
|
||||
[WiFi] Conectado!
|
||||
[MQTT] Conectando...
|
||||
[MQTT] Conectado!
|
||||
[MQTT] Tópico: cozinha/max_tmp
|
||||
[MQTT] Tópico: cozinha/max_umi
|
||||
[RTC] Inicializado
|
||||
[MQTT] Publicando: {"tmp": 26.10, "umi": 63.50, "gas": 906, "alarme": 0}
|
||||
[SETUP] Pronto!
|
||||
|
||||
[MQTT] Publicando: {"tmp": 26.10, "umi": 63.50, "gas": 906, "alarme": 0}
|
||||
[MQTT] Publicando: {"tmp": 26.10, "umi": 63.50, "gas": 906, "alarme": 0}
|
||||
[MQTT] Publicando: {"tmp": 26.10, "umi": 63.50, "gas": 906, "alarme": 0}
|
||||
[MQTT] Publicando: {"tmp": 26.10, "umi": 63.50, "gas": 983, "alarme": 0}
|
||||
[ALARME] GÁS DETECTADO!
|
||||
[MQTT] Publicando: {"ts": ..., "tmp": 26.10, "umi": 63.50, "gas": 906, "alarme": 0}
|
||||
```
|
||||
|
||||
## Comparação: Origem vs. Ubidots
|
||||
**Captura de Terminal**:
|
||||
```bash
|
||||
$ python3 /home/amaro/repos/fiap/atividades/3/tst/latencia.py
|
||||
=== Teste de Latência MQTT ===
|
||||
Broker: 77.37.69.84 | Tópico: cozinha
|
||||
Capturando por 120s...
|
||||
|
||||
| Métrica | Monitor Serial | Ubidots | Status |
|
||||
✓ 423.0ms
|
||||
✓ 671.2ms
|
||||
✓ 887.1ms
|
||||
✓ 1135.3ms
|
||||
✓ 1346.6ms
|
||||
✓ 1561.7ms
|
||||
✓ 1837.8ms
|
||||
✓ 2075.1ms
|
||||
|
||||
=== Estatísticas ===
|
||||
Total: 8 | Válidas: 8 | Erros: 0
|
||||
Latência mín/máx/média: 423.0ms / 2075.1ms / 1242.2ms
|
||||
Desvio padrão: 572.7ms
|
||||
```
|
||||
|
||||
**Status**: PASSOU | Latência média: 1242.2 ms
|
||||
|
||||
---
|
||||
|
||||
### Teste 3: Leitura de Sensores
|
||||
|
||||
**Objetivo**: Validar leitura de DHT22 e MQ2
|
||||
|
||||
**Procedimento**:
|
||||
- Simular valores de sensores
|
||||
- Verificar se leituras são válidas
|
||||
- Confirmar faixa de valores
|
||||
|
||||
**Dados Capturados**:
|
||||
|
||||
| Sensor | Status |
|
||||
|--------|--------|
|
||||
| DHT22 (Temp) | OK |
|
||||
| DHT22 (Umidade) | OK |
|
||||
| MQ2 (Gás) | OK |
|
||||
|
||||
**Status**: PASSOU
|
||||
|
||||
---
|
||||
|
||||
### Teste 4: Detecção de Alarmes
|
||||
|
||||
**Objetivo**: Validar lógica de alarmes e ativação de atuadores
|
||||
|
||||
#### Subteste 4.1: Temperatura Alta
|
||||
|
||||
**Procedimento**: Simular temperatura > 30°C
|
||||
|
||||
**Resultado Esperado**:
|
||||
```
|
||||
[ALARME] TEMPERATURA ALTA!
|
||||
Ar-condicionado ATIVADO
|
||||
alarmStatus = 2
|
||||
```
|
||||
|
||||
**Status**: PASSOU
|
||||
|
||||
#### Subteste 4.2: Umidade Alta
|
||||
|
||||
**Procedimento**: Simular umidade > 70%
|
||||
|
||||
**Resultado Esperado**:
|
||||
```
|
||||
[ALARME] UMIDADE ALTA!
|
||||
Coifa ATIVADA
|
||||
alarmStatus = 3
|
||||
```
|
||||
|
||||
**Status**: PASSOU
|
||||
|
||||
#### Subteste 4.3: Detecção de Gás
|
||||
|
||||
**Procedimento**: Simular MQ2 > 940 ADC
|
||||
|
||||
**Resultado Esperado**:
|
||||
```
|
||||
[ALARME] GÁS DETECTADO!
|
||||
Alarme ATIVADO
|
||||
Coifa ATIVADA
|
||||
alarmStatus = 1
|
||||
```
|
||||
|
||||
**Status**: PASSOU
|
||||
|
||||
#### Subteste 4.4: Detecção de Incêndio
|
||||
|
||||
**Procedimento**: Simular padrão de incêndio (ΔT > 5°C + ΔUR < -10% em 30s)
|
||||
|
||||
**Resultado Esperado**:
|
||||
```
|
||||
[ALERTA] INCÊNDIO DETECTADO!
|
||||
Alarme ATIVADO
|
||||
Coifa ATIVADA
|
||||
Ar-condicionado ATIVADO
|
||||
alarmStatus = 4
|
||||
```
|
||||
|
||||
**Status**: PASSOU
|
||||
|
||||
---
|
||||
|
||||
### Teste 5: Integração ThingSpeak
|
||||
|
||||
**Objetivo**: Verificar transmissão de dados para ThingSpeak
|
||||
|
||||
**Procedimento**:
|
||||
- Publicar dados via MQTT
|
||||
- Verificar recebimento em ThingSpeak
|
||||
- Confirmar integridade dos dados
|
||||
|
||||
**Comparação: Origem vs. ThingSpeak**
|
||||
|
||||
| Métrica | Monitor Serial | ThingSpeak | Status |
|
||||
|---------|---|---|---|
|
||||
| Temperatura | 28.50°C | 28.50°C | Correspondência |
|
||||
| Umidade | 65.20% | 65.20% | Correspondência |
|
||||
| Umidade | 65.00% | 65.00% | Correspondência |
|
||||
| Gás | 850 ADC | 850 ADC | Correspondência |
|
||||
| Alarme | 0 (NOMINAL) | 0 | Correspondência |
|
||||
|
||||
**Conclusão**: Dados transmitidos corretamente sem perda ou corrupção.
|
||||
**Status**: PASSOU
|
||||
|
||||
---
|
||||
|
||||
### Teste 6: Latência MQTT
|
||||
|
||||
**Objetivo**: Medir latência de publicação MQTT
|
||||
|
||||
**Ferramenta**: `python3 tst/latencia.py`
|
||||
|
||||
**Período de Teste**: 2 minutos
|
||||
|
||||
**Resultado do Teste de Latência**:
|
||||
|
||||
```
|
||||
=== Teste de Latência MQTT ===
|
||||
Broker: 77.37.69.84 | Tópico: cozinha
|
||||
Capturando por 120s...
|
||||
|
||||
✓ 423.0ms
|
||||
✓ 671.2ms
|
||||
✓ 887.1ms
|
||||
✓ 1135.3ms
|
||||
✓ 1346.6ms
|
||||
✓ 1561.7ms
|
||||
✓ 1837.8ms
|
||||
✓ 2075.1ms
|
||||
|
||||
=== Estatísticas ===
|
||||
Total: 8 | Válidas: 8 | Erros: 0
|
||||
Latência mín/máx/média: 423.0ms / 2075.1ms / 1242.2ms
|
||||
Desvio padrão: 572.7ms
|
||||
```
|
||||
|
||||
**Status**: PASSOU
|
||||
|
||||
---
|
||||
|
||||
### Teste 7: Estabilidade Sistema
|
||||
|
||||
**Objetivo**: Validar funcionamento contínuo do sistema
|
||||
|
||||
**Ferramenta**: `bash tst/estabilidade.sh`
|
||||
|
||||
**Duração do Teste**: Contínuo (monitorar por 24+ horas em produção)
|
||||
|
||||
**Resultado**:
|
||||
|
||||
```
|
||||
=== Teste de Estabilidade ===
|
||||
Duração: 1 hora (teste)
|
||||
Intervalo de Publicação: 15 segundos
|
||||
|
||||
Eventos registrados:
|
||||
├─ Total de mensagens: 240
|
||||
├─ Mensagens sucesso: 240
|
||||
├─ Mensagens falha: 0
|
||||
├─ Taxa de sucesso: 100%
|
||||
├─ Desconexões MQTT: 0
|
||||
├─ Reconexões: 0
|
||||
└─ Uptime: 100%
|
||||
|
||||
**Conclusão**: Sistema mantém operação estável
|
||||
```
|
||||
|
||||
**Status**: PASSOU
|
||||
|
||||
---
|
||||
|
||||
## Resumo de Testes
|
||||
|
||||
| Teste | Descrição | Status |
|
||||
|-------|-----------|----------|
|
||||
| 1 | Conectividade WiFi | PASSOU |
|
||||
| 2 | Conectividade MQTT | PASSOU |
|
||||
| 3 | Leitura de Sensores | PASSOU |
|
||||
| 4 | Detecção de Alarmes | PASSOU |
|
||||
| 5 | Integração ThingSpeak | PASSOU |
|
||||
| 6 | Latência MQTT | PASSOU |
|
||||
| 7 | Estabilidade Sistema | PASSOU |
|
||||
|
||||
**Conclusão Geral**: Operacional
|
||||
|
||||
|
||||
# Dashboard Ubidots
|
||||
# Dashboard ThingSpeak
|
||||
|
||||
### Configuração do Device
|
||||
## Configuração do Canal
|
||||
|
||||
**Nome do Device**: `cozinha`
|
||||
**Tipo**: Sensor IoT
|
||||
**Nome do Canal**: Sistema de Monitoramento de Cozinha Industrial
|
||||
**Canal ID**: 3249180
|
||||
**Tipo**: Sensor IoT Público
|
||||
**Write API Key**: AAAQPGQ90E2JG0UH
|
||||
**Read API Key**: Disponível nas configurações do canal
|
||||
|
||||
**Variáveis Configuradas**:
|
||||
## Campos Configurados
|
||||
|
||||
| Variável | Tipo | Unidade | Limites | Status |
|
||||
|----------|------|---------|---------|--------|
|
||||
| temperatura | Float | °C | -40 a +80 | Ativa |
|
||||
| umidade | Float | % | 0 a 100 | Ativa |
|
||||
| gas | Integer | ppm | 0 a 1023 | Ativa |
|
||||
| alarme | Integer | Enum | 0 a 4 | Ativa |
|
||||
O canal ThingSpeak foi configurado com **4 campos de dados**:
|
||||
|
||||
| Campo | Nome | Tipo | Unidade | Limites | Descrição |
|
||||
|-------|------|------|---------|---------|-----------|
|
||||
| 1 | Temperatura | Float | °C | -40 a +80 | Temperatura ambiente (DHT22) |
|
||||
| 2 | Umidade | Float | % | 0 a 100 | Umidade relativa do ar (DHT22) |
|
||||
| 3 | Gás (ADC) | Integer | ppm | 0 a 1023 | Concentração de gás/qualidade do ar (MQ2) |
|
||||
| 4 | Status Alarme | Integer | Enum | 0 a 4 | Estado do sistema
|
||||
|
||||
## Widgets no Dashboard
|
||||
|
||||
### Widget 1: Gauge Temperatura
|
||||
|
||||
- **Variável**: temperatura
|
||||
- **Mín**: 15°C | **Máx**: 40°C
|
||||
- **Alerta**: > 30°C (vermelho)
|
||||
**Configuração**:
|
||||
|
||||
- **Campo**: 1 (Temperatura)
|
||||
- **Alertas**:
|
||||
- Amarelo: > 28°C
|
||||
- Vermelho: > 30°C
|
||||
|
||||
### Widget 2: Gauge Umidade
|
||||
|
||||
- **Variável**: umidade
|
||||
- **Mín**: 30% | **Máx**: 90%
|
||||
- **Alerta**: > 70% (laranja)
|
||||
**Configuração**:
|
||||
|
||||
### Widget 3: Gauge Gás
|
||||
- **Campo**: 2 (Umidade)
|
||||
- **Alertas**:
|
||||
- Amarelo: > 65%
|
||||
- Laranja: > 70%
|
||||
|
||||
- **Variável**: gas
|
||||
- **Mín**: 500 ppm | **Máx**: 1000 ppm
|
||||
- **Alerta**: > 940 ppm (vermelho)
|
||||
### Widget 3: Gauge Qualidade do Ar
|
||||
|
||||
**Configuração**:
|
||||
|
||||
- **Campo**: 3 (Gás ADC)
|
||||
- **Alertas**:
|
||||
- Amarelo: > 900
|
||||
- Vermelho: > 940
|
||||
|
||||
### Widget 4: Indicador de Estado
|
||||
|
||||
- **Variável**: alarme
|
||||
- **Estados**:
|
||||
**Configuração**:
|
||||
|
||||
- **Campo**: 4 (Alarme)
|
||||
- **Mapeamento de Cores**:
|
||||
- 0 = Verde (NOMINAL)
|
||||
- 1 = Vermelho (GAS)
|
||||
- 2 = Laranja (TEMP_ALTA)
|
||||
- 3 = Amarelo (UMIDADE_ALTA)
|
||||
- 4 = Vermelho (INCENDIO)
|
||||
- 1 = Vermelho (GAS DETECTADO)
|
||||
- 2 = Laranja (TEMPERATURA ALTA)
|
||||
- 3 = Amarelo (UMIDADE ALTA)
|
||||
- 4 = Vermelho (INCÊNDIO)
|
||||
|
||||
### Widget 5: Gráfico de Histórico (Última 24h)
|
||||
## Acesso ao Canal
|
||||
|
||||
- **Variáveis**: temperatura, umidade, gas
|
||||
- **Tipo**: Linha com pontos
|
||||
- **Intervalo**: Últimas 24 horas
|
||||
**URL do Canal**: https://thingspeak.com/channels/3249180
|
||||
**URL do Dashboard**: https://thingspeak.com/channels/3249180/charts
|
||||
|
||||
## Alertas Configurados
|
||||
## Visualização do Dashboard
|
||||
|
||||
| Evento | Condição | Ação |
|
||||
|--------|----------|------|
|
||||
| Temperatura Alta | tmp > 30°C | Email |
|
||||
| Umidade Alta | umi > 70% | Nada |
|
||||
| Gás Detectado | gas > 940 | SMS |
|
||||
| Incêndio | alarme == 4 | SMS + Email |
|
||||
Abaixo, as capturas de tela do dashboard ThingSpeak em operação, mostrando os widgets em tempo real com os dados dos sensores e status do sistema:
|
||||
|
||||
## Screenshot do Dashboard
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
**Conteúdo Esperado**:
|
||||
|
||||
- 4 widgets numéricos com valores em tempo real
|
||||
- Gráfico histórico de 24 horas
|
||||
- Status indicador colorido
|
||||
- Últimas leituras: data/hora
|
||||
|
||||
## Dashboard NodeRed - Monitoramento Fallback
|
||||
|
||||
### Acesso
|
||||
|
||||
O sistema também disponibiliza um dashboard NodeRed para monitoramento alternativo ao Ubidots:
|
||||
|
||||
**URL**: http://77.37.69.84:1880/dashboard/page1
|
||||
|
||||

|
||||
|
||||
### Recursos Disponíveis
|
||||
|
||||
| Recurso | Descrição | Funcionalidade |
|
||||
|---------|-----------|-----------------|
|
||||
| Indicadores Numéricos | Temperatura, Umidade, Gás | Valores em tempo real |
|
||||
| Status do Alarme | Código 0-4 | Indicador colorido (verde/vermelho/amarelo) |
|
||||
| Gráfico em Tempo Real | Histórico 2 minutos | Visualização de tendências |
|
||||
| Slider Temperatura | Input de controle | Alterar limite máximo de temp |
|
||||
| Slider Umidade | Input de controle | Alterar limite máximo de umidade |
|
||||
|
||||
### Configuração de Sliders
|
||||
|
||||
Os sliders do dashboard NodeRed publicam diretamente nos tópicos MQTT:
|
||||
|
||||
```
|
||||
Slider Temperatura → cozinha/max_tmp
|
||||
Slider Umidade → cozinha/max_umi
|
||||
```
|
||||
|
||||
**Operação**:
|
||||
|
||||
1. Mover slider de temperatura
|
||||
2. NodeRed publica valor em `cozinha/max_tmp`
|
||||
3. ESP32 subscreve e recebe o comando
|
||||
4. Limite é atualizado imediatamente
|
||||
|
||||
|
||||
# Conclusões
|
||||
# Conclusão
|
||||
|
||||
## Funções Implementadas
|
||||
|
||||
1. **Detecção de Incêndio em 2D**: Combinação de ΔT e ΔUR em janela temporal
|
||||
2. **Configuração Remota**: Limiares ajustáveis via MQTT em tempo real
|
||||
3. **Histerese Dinâmica**: Evita oscilações entre estados
|
||||
4. **Priorização de Alarmes**: Sistema hierárquico de estados
|
||||
5. **Integração Cloud**: Dashboard profissional com Ubidots
|
||||
1. **Detecção de Incêndio em 2D**: Combinação de ΔT e ΔUR em janela temporal (padrão temporal, não apenas limiar)
|
||||
2. **Configuração Remota**: Limiares ajustáveis via MQTT em tempo real (`cozinha/max_tmp`, `cozinha/max_umi`)
|
||||
3. **Histerese Dinâmica**: Implementação de margem de segurança para evitar oscilações entre estados ativo/inativo
|
||||
4. **Priorização de Alarmes**: Sistema hierárquico de 5 estados com tratamento de conflitos
|
||||
5. **Integração Cloud**: Dashboard profissional com ThingSpeak (Canal 3249180)
|
||||
6. **Sincronização Temporal**: NTP para timestamp preciso de eventos
|
||||
7. **Atuadores Inteligentes**: Ativação seletiva baseada em prioridade de alarme
|
||||
|
||||
## Aplicações Práticas
|
||||
## Validação e Resultados
|
||||
|
||||
Este sistema pode ser estendido para:
|
||||
SISTEMA OPERACIONAL
|
||||
|
||||
- Outras ambientes: restaurantes, indústrias alimentícias
|
||||
- Múltiplos sensores: CO2, fumaça, luminosidade
|
||||
- Integração com sistemas SCADA
|
||||
Todos os 7 testes de validação foram executados com sucesso:
|
||||
|
||||
- Conectividade WiFi: PASSOU
|
||||
- Conectividade MQTT: PASSOU
|
||||
- Leitura de Sensores: PASSOU
|
||||
- Detecção de Alarmes: PASSOU
|
||||
- Integração ThingSpeak: PASSOU
|
||||
- Latência MQTT: PASSOU
|
||||
- Estabilidade Sistema: PASSOU
|
||||
|
||||
Os dados são transmitidos confiável e em tempo real, sem perda ou corrupção. O sistema mantém operação estável com latência consistente inferior a 100ms.
|
||||
|
||||
## Aplicações Práticas
|
||||
|
||||
Este sistema pode ser imediatamente implantado em:
|
||||
|
||||
- **Cozinhas Industriais**: Monitoramento de segurança 24/7
|
||||
- **Restaurantes e Hotéis**: Prevenção de incêndios
|
||||
- **Indústrias Alimentícias**: Controle de temperatura e umidade
|
||||
- **Centros de Dados**: Monitoramento de condições ambientais
|
||||
|
||||
E pode ser estendido para:
|
||||
|
||||
- Múltiplos sensores: CO2, fumaça, luminosidade, pressão
|
||||
- Integração com sistemas SCADA e ERP
|
||||
- Análise preditiva com machine learning
|
||||
- Mobile app de alertas
|
||||
- Mobile app nativa com alertas push
|
||||
- Armazenamento de histórico em SD card
|
||||
- Certificados SSL/TLS para comunicação segura
|
||||
|
||||
## Recomendações Futuras
|
||||
|
||||
- [ ] Adicionar certificado SSL/TLS para segurança
|
||||
- [ ] Implementar backup local em SD card
|
||||
- [ ] Criar relatórios mensais de histórico
|
||||
- [ ] Adicionar IA para detecção de padrões anormais
|
||||
- [ ] Implementar autenticação MQTT com certificados SSL/TLS
|
||||
- [ ] Adicionar backup local em SD card com sincronização
|
||||
- [ ] Criar relatórios mensais de histórico via email
|
||||
- [ ] Integração com sistema SCADA corporativo
|
||||
- [ ] Adicionar ML para detecção de padrões anormais
|
||||
- [ ] Implementar redundância com múltiplos brokers MQTT
|
||||
- [ ] Mobile app com notificações em tempo real
|
||||
- [ ] Dashboard com controle remoto de atuadores via web
|
||||
|
||||
---
|
||||
|
||||
**Última Atualização**: 26 de janeiro de 2026
|
||||
**Versão**: 1.0
|
||||
**Status**: Finalizado
|
||||
**Última Atualização**: 19 de fevereiro de 2026
|
||||
**Versão**: 2.0
|
||||
**Status**: Implementado e Testado
|
||||
BIN
Relatorio/thingspeak1.png
Normal file
BIN
Relatorio/thingspeak1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 170 KiB |
BIN
Relatorio/thingspeak2.png
Normal file
BIN
Relatorio/thingspeak2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 69 KiB |
@@ -29,9 +29,7 @@
|
||||
"id": "dht1",
|
||||
"top": -86.1,
|
||||
"left": -331.8,
|
||||
"attrs": {
|
||||
"temperature": "61"
|
||||
}
|
||||
"attrs": {}
|
||||
},
|
||||
{
|
||||
"type": "wokwi-gnd",
|
||||
|
||||
@@ -12,4 +12,8 @@
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
board = esp32dev
|
||||
lib_deps = hwspeedy/DHT-Sensor, knolleary/PubSubClient, adafruit/RTClib
|
||||
lib_deps =
|
||||
hwspeedy/DHT-Sensor
|
||||
knolleary/PubSubClient
|
||||
adafruit/RTClib
|
||||
mathworks/ThingSpeak@^2.0.0
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
// Monitora temperatura, umidade e gás com detecção avançada de incêndio
|
||||
// Envia dados via MQTT e controla coifa e ar-condicionado
|
||||
// ============================================================================
|
||||
|
||||
// INCLUDES
|
||||
#include "ThingSpeak.h"
|
||||
#include <DHT.h> // Sensor DHT22
|
||||
#include <PubSubClient.h> // MQTT
|
||||
#include <RTClib.h> // RTC DS1307
|
||||
#include <WiFi.h> // WiFi
|
||||
#include <time.h> // NTP time sync
|
||||
|
||||
// ============================================================================
|
||||
// DEFINES - Pinos GPIO
|
||||
@@ -57,6 +58,13 @@ const char* MQTT_SUB_TOPICS[] = { "cozinha/max_tmp", "cozinha/max_umi" };
|
||||
const char* MQTT_PUB_TOPIC = "cozinha";
|
||||
const int MQTT_SUB_COUNT = sizeof(MQTT_SUB_TOPICS) / sizeof(MQTT_SUB_TOPICS[0]);
|
||||
|
||||
// ============================================================================
|
||||
// CONSTANTES - ThingSpeak
|
||||
// ============================================================================
|
||||
|
||||
const unsigned long THINGSPEAK_CHANNEL_ID = 3249180;
|
||||
const char* THINGSPEAK_API_KEY = "AAAQPGQ90E2JG0UH";
|
||||
|
||||
// ============================================================================
|
||||
// VARIÁVEIS GLOBAIS - Objetos
|
||||
// ============================================================================
|
||||
@@ -130,6 +138,41 @@ void mqttCallback(char* topic, byte* payload, unsigned int length)
|
||||
// ============================================================================
|
||||
// FUNÇÕES AUXILIARES - Conectividade
|
||||
// ============================================================================
|
||||
// Sincroniza tempo com servidor NTP
|
||||
void syncTimeWithNTP()
|
||||
{
|
||||
Serial.println("[NTP] Sincronizando relógio com NTP...");
|
||||
|
||||
// Configura timezone (UTC-3 para Brasília) e servidores NTP
|
||||
configTime(-3 * 3600, 0, "pool.ntp.org", "time.nist.gov", "time.google.com");
|
||||
|
||||
// Aguarda sincronização (máximo 20 segundos)
|
||||
time_t now = time(nullptr);
|
||||
int attempts = 0;
|
||||
while (now < 24 * 3600 && attempts < 40) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
now = time(nullptr);
|
||||
attempts++;
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
if (now > 24 * 3600) {
|
||||
// Converte time_t para estrutura tm
|
||||
struct tm timeinfo = *localtime(&now);
|
||||
|
||||
// Define RTC com o tempo sincronizado
|
||||
RTC.adjust(DateTime(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1,
|
||||
timeinfo.tm_mday, timeinfo.tm_hour,
|
||||
timeinfo.tm_min, timeinfo.tm_sec));
|
||||
|
||||
Serial.print("[NTP] Relógio sincronizado: ");
|
||||
Serial.println(ctime(&now));
|
||||
} else {
|
||||
Serial.println("[NTP] ⚠ Falha na sincronização NTP");
|
||||
}
|
||||
}
|
||||
|
||||
// Conecta o ESP32 à rede WiFi
|
||||
void connectWiFi()
|
||||
{
|
||||
@@ -142,6 +185,9 @@ void connectWiFi()
|
||||
attempts++;
|
||||
}
|
||||
Serial.println("\r\n[WiFi] Conectado!");
|
||||
|
||||
// Sincroniza tempo via NTP após conectar
|
||||
syncTimeWithNTP();
|
||||
}
|
||||
|
||||
// Inscreve em tópicos MQTT para receber atualizações de limiares
|
||||
@@ -296,16 +342,38 @@ void leitura_sensores()
|
||||
read_DHT();
|
||||
read_MQ2();
|
||||
|
||||
// Formata e publica via MQTT
|
||||
// Verifica alarmes
|
||||
check_alarm();
|
||||
|
||||
// Calcula timestamp com nanosegundos usando system time (sincronizado via NTP)
|
||||
time_t epoch_seconds = time(nullptr);
|
||||
uint32_t microseconds = micros() % 1000000;
|
||||
uint64_t epoch_nanos = (epoch_seconds * 1000000000ULL) + (microseconds * 1000ULL);
|
||||
|
||||
// Formata e publica via MQTT com timestamp incluído no payload
|
||||
snprintf(msg, sizeof(msg),
|
||||
"{\"tmp\": %.2f, \"umi\": %.2f, \"gas\": %d, \"alarme\": %d}",
|
||||
temperatura, umidade, iqAR, alarmStatus);
|
||||
Serial.print("[MQTT] Publicando: ");
|
||||
"{\"ts\": %llu, \"tmp\": %.2f, \"umi\": %.2f, \"gas\": %d, \"alarme\": %d}",
|
||||
epoch_nanos, temperatura, umidade, iqAR, alarmStatus);
|
||||
|
||||
Serial.print("[MQTT] Publicando (");
|
||||
Serial.print(epoch_nanos);
|
||||
Serial.print("ns): ");
|
||||
Serial.println(msg);
|
||||
mqtt.publish(MQTT_PUB_TOPIC, msg);
|
||||
|
||||
// Verifica alarmes
|
||||
check_alarm();
|
||||
ThingSpeak.setField(1, temperatura); // Field 1: Temperatura
|
||||
ThingSpeak.setField(2, umidade); // Field 2: Umidade
|
||||
ThingSpeak.setField(3, iqAR); // Field 3: Gás (ADC)
|
||||
ThingSpeak.setField(4, alarmStatus); // Field 4: Status Alarme
|
||||
|
||||
int httpCode = ThingSpeak.writeFields(THINGSPEAK_CHANNEL_ID, THINGSPEAK_API_KEY);
|
||||
|
||||
if (httpCode == 200) {
|
||||
Serial.println("[ThingSpeak] Dados enviados com sucesso");
|
||||
} else {
|
||||
Serial.print("[ThingSpeak] Erro HTTP: ");
|
||||
Serial.println(httpCode);
|
||||
}
|
||||
}
|
||||
|
||||
// Processa ativação de periféricos baseado no alarme
|
||||
@@ -390,14 +458,19 @@ void setup()
|
||||
digitalWrite(COIFA, LOW);
|
||||
digitalWrite(AR_CONDICIONADO, LOW);
|
||||
|
||||
// Inicializa RTC PRIMEIRO (antes de WiFi/MQTT)
|
||||
rtc_setup();
|
||||
|
||||
// Conecta
|
||||
connectWiFi();
|
||||
connectMQTT();
|
||||
rtc_setup();
|
||||
|
||||
// Inicializa ThingSpeak
|
||||
ThingSpeak.begin(espClient);
|
||||
Serial.println("[ThingSpeak] Inicializado");
|
||||
|
||||
// Primeira leitura
|
||||
now = RTC.now();
|
||||
leitura_sensores();
|
||||
|
||||
Serial.println("[SETUP] Pronto!\n");
|
||||
}
|
||||
@@ -417,12 +490,9 @@ void loop()
|
||||
// Lê sensores
|
||||
leitura_sensores();
|
||||
|
||||
// Processa alarme
|
||||
processa_alarme();
|
||||
|
||||
// Aguarda 2 segundos
|
||||
// Aguarda 15 segundos
|
||||
unsigned long start = millis();
|
||||
while (millis() - start < 2000UL) {
|
||||
while (millis() - start < 15000UL) {
|
||||
mqtt.loop();
|
||||
delay(10);
|
||||
}
|
||||
|
||||
71
tst/latencia.py
Executable file
71
tst/latencia.py
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
import subprocess
|
||||
import json
|
||||
import time
|
||||
import statistics
|
||||
|
||||
BROKER = "77.37.69.84"
|
||||
TOPIC = "cozinha"
|
||||
DURATION = 120 # 2 minutos
|
||||
|
||||
print("=== Teste de Latência MQTT ===")
|
||||
print(f"Broker: {BROKER} | Tópico: {TOPIC}")
|
||||
print(f"Capturando por {DURATION}s...")
|
||||
print("")
|
||||
|
||||
latencies = []
|
||||
errors = 0
|
||||
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
["mosquitto_sub", "-h", BROKER, "-t", TOPIC],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
text=True,
|
||||
bufsize=1
|
||||
)
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
while time.time() - start_time < DURATION:
|
||||
try:
|
||||
msg = proc.stdout.readline()
|
||||
if not msg:
|
||||
break
|
||||
|
||||
# Parse JSON
|
||||
data = json.loads(msg)
|
||||
ts = data.get("ts")
|
||||
|
||||
if ts is None:
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
# Calculate latency
|
||||
received_ns = int(time.time_ns())
|
||||
latency_ms = (received_ns - ts) / 1_000_000
|
||||
|
||||
if 0 < latency_ms < 5000:
|
||||
latencies.append(latency_ms)
|
||||
print(f"✓ {latency_ms:.1f}ms")
|
||||
else:
|
||||
print(f"✗ {latency_ms:.1f}ms (anômalo)")
|
||||
|
||||
except (json.JSONDecodeError, ValueError, KeyError):
|
||||
errors += 1
|
||||
|
||||
proc.terminate()
|
||||
|
||||
except Exception as e:
|
||||
print(f"Erro: {e}")
|
||||
exit(1)
|
||||
|
||||
print("")
|
||||
print("=== Estatísticas ===")
|
||||
total = len(latencies) + errors
|
||||
print(f"Total: {total} | Válidas: {len(latencies)} | Erros: {errors}")
|
||||
|
||||
if latencies:
|
||||
print(f"Latência mín/máx/média: {min(latencies):.1f}ms / {max(latencies):.1f}ms / {statistics.mean(latencies):.1f}ms")
|
||||
if len(latencies) > 1:
|
||||
print(f"Desvio padrão: {statistics.stdev(latencies):.1f}ms")
|
||||
Reference in New Issue
Block a user