Partilhar: Classroom Teams WhatsApp
aulify · Sebenta
UC · Unidade de Competência · UC00643

Internet of Things (UC00643)

ESP32, MQTT, dashboards e dispositivos conectados
25h · 2.25 pontos crédito Curso: T. Desenv. Software, T. Sist. Comp. Redes ↗ Referencial oficial SNQ
Índice

Há um pacote premium desta unidade: um PowerPoint editável de 100 ou mais diapositivos, um manual em PDF e dois testes com correção. Esta sebenta continua gratuita.

Introdução

Internet of Things (IoT) é o universo de dispositivos físicos conectados à internet: lâmpadas, frigoríficos, contadores de electricidade, sensores agrícolas, trackers GPS, máquinas industriais, anéis fitness, carros. Em 2026 há mais de 30 mil milhões de devices IoT no mundo — e cresce.

Esta UC é o passo natural depois de Arduino básico (UC02842). Vamos pegar nos artefactos tangíveis e conectá-los à internet, enviar dados para dashboards, controlá-los remotamente, integrar com smart home. Foco em ESP32 (microcontrolador com WiFi e Bluetooth integrados), MQTT (protocolo IoT standard) e plataformas cloud acessíveis.

Em 25 horas vais conseguir construir uma estação ambiental que envia dados para a internet, com dashboard visual e controlo remoto.

1. IoT em contexto

O que é

Internet of Things: objectos físicos com sensores, software e conectividade que trocam dados pela rede. Não é um produto único — é um paradigma.

Características:

Onde está

Casa:

Indústria (IIoT — Industrial IoT):

Cidades (Smart cities):

Saúde:

Stack típico

[Sensor]──┐
[Sensor]──┼──[MCU+conectividade]──[Rede]──[Cloud broker]──[Storage/BD]
[Actuator]┘                                                      │
                                                          [Dashboard/App]
                                                          [ML/Analytics]
                                                          [Alertas]

Esta UC

Foco no que dá para construir em casa/escola com componentes baratos:

2. ESP32 / ESP8266 — hardware

ESP8266 vs ESP32

ESP8266 (Espressif, 2014):

ESP32 (Espressif, 2016):

Esta UC usa ESP32 (mais capaz, ainda barato, futuro-proof). Recomendo ESP32 DevKit V1 / NodeMCU-32S (US$5-10).

Variantes ESP32 modernas

Setup no Arduino IDE

  1. File → Preferences:
  2. Additional Boards Manager URL: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  3. Tools → Board → Boards Manager:
  4. Procura "esp32" by Espressif → Install (~200MB).
  5. Liga ESP32 USB.
  6. Tools → Board → ESP32 → ESP32 Dev Module (genérico).
  7. Tools → Port → seleccionar.

Drivers USB: alguns boards usam CP2102 (Silicon Labs) ou CH340 (WCH). Se PC não detectar, instala driver apropriado.

PlatformIO alternativa

Para projectos sérios. platformio.ini:

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps =
    knolleary/PubSubClient
    adafruit/DHT sensor library

Pinos especiais

Cuidado: nem todos os GPIO são iguais.

Para sensores analógicos: usar ADC1 (32, 33, 34, 35, 36, 39).

3. Hello WiFi

Connect a rede

#include <WiFi.h>

const char* SSID = "TP-Link_AB12";
const char* PASS = "minha-pass";

void setup() {
  Serial.begin(115200);

  WiFi.begin(SSID, PASS);
  Serial.print("A conectar");

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());
  Serial.print("RSSI: ");
  Serial.println(WiFi.RSSI());   // força sinal dBm
}

void loop() {}

Baud rate típico ESP32: 115200.

Status checks

WiFi.status() == WL_CONNECTED   // bom
WiFi.RSSI()                      // -50 forte, -80 fraco
WiFi.localIP()                   // ex: 192.168.1.123
WiFi.macAddress()                // ex: AA:BB:CC:DD:EE:FF
WiFi.SSID()                      // rede actual

WiFi.h functions úteis

WiFi.disconnect();      // desconectar
WiFi.reconnect();       // re-tentar
WiFi.setHostname("estacao-aulify");

// Static IP em vez de DHCP
IPAddress local(192, 168, 1, 200);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
WiFi.config(local, gateway, subnet);

4. HTTP

HTTP GET (consumir API)

#include <WiFi.h>
#include <HTTPClient.h>

void loop() {
  if (WiFi.status() != WL_CONNECTED) return;

  HTTPClient http;
  http.begin("http://wttr.in/Lisbon?format=%t");

  int code = http.GET();
  if (code == 200) {
    String body = http.getString();
    Serial.println(body);
  } else {
    Serial.print("Erro: ");
    Serial.println(code);
  }

  http.end();
  delay(60000);   // cada 60s
}

HTTPS (TLS)

#include <WiFiClientSecure.h>
#include <HTTPClient.h>

WiFiClientSecure client;

void setup() {
  // ...
  client.setInsecure();   // skip cert validation (dev only)
  // ou: client.setCACert(rootCACertificate);
}

void loop() {
  HTTPClient http;
  http.begin(client, "https://api.example.com/data");
  int code = http.GET();
  // ...
}

HTTP POST

HTTPClient http;
http.begin("http://meu-server.pt/api/sensor");
http.addHeader("Content-Type", "application/json");

float temp = 21.5;
float humid = 60.0;

String body = "{\"temp\":";
body += temp;
body += ",\"humid\":";
body += humid;
body += "}";

int code = http.POST(body);
Serial.println(code);
http.end();

Quando usar HTTP vs MQTT

5. MQTT

O que é

MQTT (Message Queuing Telemetry Transport): protocolo pub/sub criado por IBM nos anos 90 para sensores. Hoje é o standard de facto em IoT.

Modelo:

Publisher ─publish─→ Broker ─subscribe→ Subscriber
                       ↑
                       │
                  routing por topic

Topics são strings hierárquicas: casa/sala/temperatura. Subscribers ouvem topics (ou wildcards: casa/+/temperatura, casa/#).

Broker

Pode ser:

ESP32 + MQTT (PubSubClient)

Library popular: PubSubClient by Nick O'Leary.

#include <WiFi.h>
#include <PubSubClient.h>

const char* SSID = "wifi";
const char* PASS = "pass";
const char* BROKER = "broker.hivemq.com";
const int   PORT = 1883;

WiFiClient espClient;
PubSubClient mqtt(espClient);

void setupWiFi() {
  WiFi.begin(SSID, PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
}

void reconnectMQTT() {
  while (!mqtt.connected()) {
    String id = "aulify-" + String(random(0xffff), HEX);
    if (mqtt.connect(id.c_str())) {
      mqtt.subscribe("aulify/cmd");
    } else {
      delay(5000);
    }
  }
}

void onMessage(char* topic, byte* payload, unsigned int len) {
  String msg;
  for (int i = 0; i < len; i++) msg += (char)payload[i];
  Serial.print(topic);
  Serial.print(" → ");
  Serial.println(msg);
}

void setup() {
  Serial.begin(115200);
  setupWiFi();
  mqtt.setServer(BROKER, PORT);
  mqtt.setCallback(onMessage);
}

unsigned long ultimaPub = 0;

void loop() {
  if (!mqtt.connected()) reconnectMQTT();
  mqtt.loop();

  if (millis() - ultimaPub > 5000) {
    ultimaPub = millis();
    float t = 20.0 + (random(100) / 10.0);   // dummy
    char buf[10];
    dtostrf(t, 4, 2, buf);
    mqtt.publish("aulify/sala/temp", buf);
  }
}

Topic design

Princípios:

Exemplos:

QoS levels

Para sensores enviando todos os 5s: QoS 0 chega. Para comandos críticos (abrir porta): QoS 1 ou 2.

Retained messages

Servidor "guarda" última mensagem do topic. Novos subscribers recebem-na imediatamente.

mqtt.publish("aulify/estado", "online", true);  // retained=true

6. Dashboards cloud

ThingSpeak

MathWorks. Open source on-premise possível. Free: 8 canais, 3M msgs/ano, update mínimo 15s.

Workflow:

  1. thingspeak.com → sign up.
  2. Channels → New Channel → "Sala de aula" → fields: temp, humid, luz.
  3. API Keys tab → copy Write API Key.
  4. ESP32 envia via HTTP GET:
String url = "http://api.thingspeak.com/update?api_key=YOUR_KEY";
url += "&field1=" + String(temp);
url += "&field2=" + String(humid);
http.begin(url);
http.GET();
  1. Dashboard auto-actualiza com gráficos.
  2. Matlab Analytics integrado para análise.

Adafruit IO

Adafruit. Free: 10 feeds, 30 data points/min, 30 dias storage.

io.adafruit.com → sign up → Feeds → New Feed.

Trabalha com MQTT ou REST:

#include <Adafruit_MQTT.h>
#include <Adafruit_MQTT_Client.h>

#define AIO_SERVER "io.adafruit.com"
#define AIO_PORT 1883
#define AIO_USER "teu-username"
#define AIO_KEY  "aio_xxx..."

WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_PORT, AIO_USER, AIO_KEY);

Adafruit_MQTT_Publish tempFeed(&mqtt, AIO_USER "/feeds/temperatura");

void loop() {
  if (!mqtt.connected()) mqtt.connect();

  float t = 21.5;
  tempFeed.publish(t);
  delay(10000);
}

Dashboards no site: drag-drop blocks (line chart, gauge, slider, toggle).

Blynk

Foca em app mobile + dashboards. Free tier limitado (4 widgets por device).

Vantagem: UI mobile pré-construída. Tu controlas LEDs/relés do telemóvel.

Self-hosted: Grafana + InfluxDB

Stack profissional open source:

Mais setup mas zero limites e zero dependência de cloud.

7. Home Assistant

Plataforma open source de smart home, self-hosted (Raspberry Pi, Docker, NUC).

Casos de uso:

Setup rápido com Docker

docker run -d --name homeassistant --restart unless-stopped \
  -v ~/ha-config:/config \
  --network=host \
  ghcr.io/home-assistant/home-assistant:stable

Abrir http://localhost:8123 → onboarding.

Integração MQTT

Settings → Devices & Services → Add Integration → MQTT → conectar a broker.

ESP32 publica em home/sala/temp. HA descobre como sensor.

YAML config

# configuration.yaml
mqtt:
  sensor:
    - name: "Temperatura sala"
      state_topic: "home/sala/temp"
      unit_of_measurement: "°C"

  switch:
    - name: "Luz exterior"
      command_topic: "home/exterior/luz/cmd"
      state_topic: "home/exterior/luz/state"
      payload_on: "ON"
      payload_off: "OFF"

ESP32 ouve home/exterior/luz/cmd e liga relé.

Automations

# automations.yaml
- alias: "Aviso temp alta"
  trigger:
    platform: numeric_state
    entity_id: sensor.temperatura_sala
    above: 28
  action:
    service: notify.mobile_app
    data:
      message: "Está calor: {{ states.sensor.temperatura_sala.state }}°C"

8. Deep sleep — bateria dura meses

ESP32 consumo:

Estratégia para sensores em bateria:

  1. Acordar.
  2. Conectar WiFi.
  3. Ler sensor.
  4. Enviar via MQTT/HTTP.
  5. Dormir 5-15 min.
  6. Repetir.
#include "esp_sleep.h"

#define uS_PER_SEC 1000000ULL

void deepSleepMin(int minutos) {
  Serial.println("A dormir...");
  Serial.flush();
  esp_sleep_enable_timer_wakeup(minutos * 60 * uS_PER_SEC);
  esp_deep_sleep_start();
  // nunca volta
}

void setup() {
  Serial.begin(115200);

  // WiFi + sensor + MQTT
  connectWiFi();
  float t = readSensor();
  publishMQTT(t);

  deepSleepMin(15);
}

void loop() {}   // não chega aqui

Bateria 2500mAh em deep sleep contínuo: ~10 anos teóricos (na prática ~1 ano com wake-ups).

RTC memory

Variáveis em RTC_DATA_ATTR sobrevivem deep sleep:

RTC_DATA_ATTR int bootCount = 0;

void setup() {
  bootCount++;
  Serial.println(bootCount);
  deepSleepMin(1);
}

9. OTA — actualizar firmware via WiFi

Após primeiro upload USB, podes actualizar via rede:

#include <ArduinoOTA.h>

void setupOTA() {
  ArduinoOTA.setHostname("estacao-aulify");
  ArduinoOTA.setPassword("ota-pass");

  ArduinoOTA.onStart([]() {
    Serial.println("OTA iniciado");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("OTA completo");
  });

  ArduinoOTA.begin();
}

void setup() {
  connectWiFi();
  setupOTA();
}

void loop() {
  ArduinoOTA.handle();   // tem que ser chamado regularmente

  // restante código
}

Arduino IDE → Tools → Port → vai aparecer estacao-aulify at 192.168.x.x (Network).

OTA é obrigatório em devices que vais instalar fora do alcance fácil.

10. Segurança

Riscos comuns

Em 2016, botnet Mirai infectou milhões de devices IoT com defaults — usou-os para DDoS massivos.

Mitigações

#include <WiFiClientSecure.h>

WiFiClientSecure client;
client.setCACert(rootCA);
PubSubClient mqtt(client);
mqtt.setServer("io.adafruit.com", 8883);   // porta TLS

GDPR e privacy

Devices IoT podem recolher PII (presença, hábitos, voice). Cuidado:

11. Protocolos alternativos

Bluetooth Low Energy (BLE)

ESP32 suporta BLE nativo. Para devices pessoais (wearables, beacons), perto da pessoa.

#include <BLEDevice.h>
#include <BLEServer.h>

BLEServer* server = BLEDevice::createServer();
BLEService* svc = server->createService("...");
BLECharacteristic* ch = svc->createCharacteristic(...);
svc->start();
server->getAdvertising()->start();

Phones podem detectar via apps tipo nRF Connect.

LoRa / LoRaWAN

Para longas distâncias (km) e muito baixo consumo — agricultura, smart cities.

Não usa WiFi: rádio sub-GHz. Bandwidth muito baixo (uns bytes por minuto).

Hardware: módulos SX1276/SX1278, RFM95.

Zigbee / Z-Wave / Matter

Mesh networks para smart home. Standards seguidos pela maioria dos devices comerciais. Matter (2022+) é o novo unificador.

ESP32-C6 e ESP32-H2 suportam 802.15.4 (base Zigbee/Thread/Matter).

NB-IoT / LTE-M (4G IoT)

Conectividade celular específica para IoT — baixo consumo, ideal para trackers GPS em qualquer sítio. Custos de SIM por device.

12. Boas práticas em produção

Robustez

#include <esp_task_wdt.h>

void setup() {
  esp_task_wdt_init(10, true);   // 10s timeout
  esp_task_wdt_add(NULL);
}

void loop() {
  esp_task_wdt_reset();   // "estou vivo"
  // resto
}

Logging

Serial.println() durante dev. Em produção:

Configuração

Não hardcode WiFi pass / API keys no código (vão para Git!).

Soluções:

#include <WiFiManager.h>

WiFiManager wm;

void setup() {
  if (!wm.autoConnect("AulifyIoT")) {
    ESP.restart();
  }
  // chega aqui = conectado
}

Primeiro arranque cria hotspot "AulifyIoT"; conectas-te com telemóvel, escolhes WiFi, e ESP guarda credenciais.

13. Próximos passos

Glossário

Recursos

IoT é uma das áreas mais excitantes para makers e engenheiros. Combina hardware, software, redes, cloud, e tem aplicações em qualquer indústria. Aprender ESP32 + MQTT abre portas para smart home, agricultura, monitorização ambiental, retail, healthcare e indústria. Começa pequeno (uma estação meteorológica), itera, e em pouco tempo tens projectos genuinamente úteis.