Firmware seguro para dispositivos IoT basado en ESP32-C3, escrito en Rust con ESP-IDF.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ESP32-C3 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
β β WiFi β β Secure β β Device Client β β
β β Module β β Storage β β (HTTP Polling) β β
β β β β (NVS) β β β β
β ββββββββ¬βββββββ ββββββββ¬βββββββ βββββββββββββ¬ββββββββββββββ β
β β β β β
β ββββββββββββββββββΌββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββ β
β β Main Loop β β
β β - Poll commands cada 5s β β
β β - Enviar telemetria cada 60s β β
β β - Ejecutar comandos recibidos β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β HTTPS
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β core.leonobitech.com β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β POST /api/devices/register - Registrar dispositivo β
β POST /api/devices/:id/telemetry - Enviar telemetria β
β GET /api/devices/:id/commands/pending - Obtener comandos β
β POST /api/devices/:id/commands/:id/ack - Confirmar comando β
β POST /api/devices/:id/status - Enviar estado β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β ESP32-C3 β β Usuario β β Backend β
β (Sin config)β β (Movil/PC) β β β
ββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββ¬ββββββββ
β β β
β Inicia SoftAP β β
β "Leonobitech-Setup"β β
β Pass: "setup1234" β β
ββββββββββββββββββββββ€ β
β Conecta WiFi β β
β β β
ββββββββββββββββββββββ€ β
β GET 192.168.4.1 β β
β β β
ββββββββββββββββββββββΊ β
β Portal HTML β β
β β β
ββββββββββββββββββββββ€ β
β POST /configure β β
β {ssid, password, β β
β deviceId, apiKey}β β
β β β
β Guarda en NVS β β
β (encriptado) β β
β β β
β ββββββ RESTART βββββ β
β β β
ββββββββββββββββ ββββββββββββββββ
β ESP32-C3 β β Backend β
ββββββββ¬ββββββββ ββββββββ¬ββββββββ
β β
β Conecta WiFi (credenciales NVS) β
β β
ββββββββ POST /register βββββββββββββββββββββββΊ
β {device_id, firmware_version} β
βββββββββββββββββββββββββββββββββββββββββββββββ
β {status: "success"} β
β β
β β
β ββββββββββ LOOP PRINCIPAL ββββββββββ β
β β
β [Cada 5s] β
ββββββββ GET /commands/pending ββββββββββββββββΊ
βββββββββββββββββββββββββββββββββββββββββββββββ
β {commands: [...]} β
β β
β [Si hay comando] β
β Ejecuta comando β
ββββββββ POST /commands/:id/ack βββββββββββββββΊ
β {success: true, message: "..."} β
β β
β [Cada 60s] β
ββββββββ POST /telemetry ββββββββββββββββββββββΊ
β {free_heap, wifi_rssi, uptime} β
β β
hardware/
βββ .cargo/
β βββ config.toml # Configuracion de Cargo para ESP32
βββ .github/
β βββ workflows/
β βββ rust_ci.yml # CI/CD con GitHub Actions
βββ src/
β βββ main.rs # Entry point y loop principal
β βββ wifi.rs # Conexion WiFi WPA2/WPA3
β βββ provisioning.rs # Portal SoftAP para configuracion
β βββ secure_storage.rs # NVS encriptado para credenciales
β βββ device_client.rs # Cliente HTTP para backend
β βββ http_client.rs # Cliente HTTP generico (legacy)
βββ Cargo.toml # Dependencias Rust
βββ build.rs # Script de build
βββ sdkconfig.defaults # Configuracion ESP-IDF
βββ rust-toolchain.toml # Version de Rust (nightly)
βββ README.md
| Comando | Descripcion | Parametros |
|---|---|---|
get_status |
Solicita estado completo del dispositivo | - |
led_on |
Enciende LED | - |
led_off |
Apaga LED | - |
set_brightness |
Ajusta brillo | {level: 0-100} |
restart |
Reinicia dispositivo | - |
factory_reset |
Borra credenciales y reinicia | - |
| Modo | Config | Secure Boot | Flash Encryption | Uso |
|---|---|---|---|---|
| Development | sdkconfig.defaults |
No | No | CI, desarrollo local |
| Production | sdkconfig.defaults.production |
Si | Si | Dispositivos finales |
- Verifica firma del firmware antes de ejecutar
- Previene ejecucion de firmware no autorizado
- Generar clave:
espsecure.py generate_signing_key --version 2 secure_boot_signing_key.pem - IMPORTANTE:
secure_boot_signing_key.pemNO debe commitearse
- Encripta contenido de la flash
- Protege firmware y datos almacenados
- Habilitado solo con
sdkconfig.defaults.production
- Credenciales WiFi encriptadas en NVS
- API Key hasheada antes de almacenar
- Zeroization de credenciales en memoria despues de uso
- Solo HTTPS con certificados de CA bundle
- Headers
x-device-idyx-api-keypara autenticacion - API Key hasheada con HMAC-SHA512 en backend
# Instalar Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Instalar toolchain ESP32
cargo install espup
espup install
# Configurar variables de entorno
. $HOME/export-esp.sh# Build debug (development)
cargo build
# Build release (development/CI - sin Secure Boot)
cargo build --release
# Build release PRODUCTION (con Secure Boot)
# Requiere: secure_boot_signing_key.pem
SDKCONFIG_DEFAULTS=sdkconfig.defaults.production cargo build --release
# Flash al dispositivo
cargo run --releaseEditar sdkconfig.defaults para ajustar:
- Tamano de particiones
- Configuracion WiFi
- Opciones de seguridad
Datos enviados cada 60 segundos:
{
"device_id": "esp32-001",
"free_heap": 245760,
"wifi_rssi": -52,
"uptime_secs": 3600,
"sensors": null
}El firmware se comunica con core.leonobitech.com:
| Endpoint | Metodo | Descripcion |
|---|---|---|
/api/devices/register |
POST | Registro inicial |
/api/devices/:id/telemetry |
POST | Envio de telemetria |
/api/devices/:id/commands/pending |
GET | Obtener comandos |
/api/devices/:id/commands/:cmdId/ack |
POST | Confirmar ejecucion |
/api/devices/:id/status |
POST | Enviar estado completo |
- leonobitech/backend - API Backend (Express + Prisma)
- leonobitech/frontend - Dashboard (Next.js)
Propietario - Leonobitech