انتقل إلى المحتوى الرئيسي

ESP32-S3 — Zephyr RTOS BLE Gateway

The ESP32-S3 serves as a BLE-to-MQTT edge gateway. It aggregates BLE advertisements from nRF52840 sensors, runs on-device TFLite Micro anomaly inference, and publishes telemetry/alerts to the MQTT broker.

Role in the Architecture

Technical Specifications

FeatureDetail
MCUESP32-S3 (Xtensa LX7 dual-core, 240MHz)
RAM512KB SRAM + 8MB PSRAM
RTOSZephyr RTOS
LanguageC (Zephyr SDK)
ConnectivityWiFi 802.11 b/g/n + BLE 5.0
Device IDesp32s3_gw_01
Telemetry interval10 seconds
Attestation interval5 minutes

Why Zephyr RTOS?

FeatureZephyrFreeRTOSESP-IDF Native
BLE Mesh supportNative (Bluetooth Mesh)LimitedLimited
TFLite MicroBuilt-in moduleManual portManual port
Hardware abstractionDevicetree + KconfigMinimalESP-specific
OTA updatesMCUboot integrationManualESP OTA
Upstream supportLinux FoundationAmazonEspressif

Zephyr's built-in BLE Mesh stack and TFLite Micro module make it ideal for an edge AI gateway.

System Architecture

// main.c — Entry point
void main(void) {
// Initialize subsystems
mqtt_client_init(); // Connect to Mosquitto
ble_scanner_init(); // Start BLE scanning
edge_inference_init(); // Load TFLite model
ota_manager_init(); // Enable OTA updates
attestation_init(); // Prepare attestation

// Start periodic timers
k_timer_start(&telemetry_timer, K_MSEC(TELEMETRY_INTERVAL_MS), K_MSEC(TELEMETRY_INTERVAL_MS));
k_timer_start(&attestation_timer, K_MSEC(ATTESTATION_INTERVAL_MS), K_MSEC(ATTESTATION_INTERVAL_MS));

// Publish startup status
mqtt_publish(TOPIC_STATUS, status_payload, MQTT_QOS_1_AT_LEAST_ONCE);

// Main loop — process BLE events
while (1) {
k_sleep(K_MSEC(100));
}
}

Telemetry Pipeline

Every 10 seconds:

Telemetry Handler

static void telemetry_timer_handler(struct k_timer *timer) {
// 1. Aggregate BLE sensor data from all nRF52 nodes
struct sensor_aggregate agg;
ble_scanner_aggregate(&agg);

// 2. Run TFLite Micro anomaly detection
float anomaly_score = edge_inference_predict(
agg.temperature,
agg.motion_count,
agg.ble_node_count
);

// 3. Build telemetry payload
snprintk(payload, sizeof(payload),
"{\"device_id\":\"%s\","
"\"temperature\":%.1f,"
"\"motion_count\":%d,"
"\"ble_nodes\":%d,"
"\"anomaly_score\":%.3f}",
DEVICE_ID, agg.temperature, agg.motion_count,
agg.ble_node_count, anomaly_score);

// 4. Publish telemetry (QoS 1 — At Least Once)
mqtt_publish(TOPIC_TELEMETRY, payload, MQTT_QOS_1_AT_LEAST_ONCE);

// 5. Alert if anomaly detected
if (anomaly_score > CONFIG_AURORA_ANOMALY_THRESHOLD) {
snprintk(alert_payload, sizeof(alert_payload),
"{\"device_id\":\"%s\","
"\"alert_type\":\"anomaly_detected\","
"\"severity\":\"high\","
"\"anomaly_score\":%.3f,"
"\"details\":\"Edge ML anomaly threshold exceeded\"}",
DEVICE_ID, anomaly_score);

// QoS 2 — Exactly Once (critical alert must not be duplicated)
mqtt_publish(TOPIC_ALERT, alert_payload, MQTT_QOS_2_EXACTLY_ONCE);
}
}

Edge AI Inference

The ESP32-S3 runs a TensorFlow Lite Micro model for on-device anomaly detection:

Model: Autoencoder (reconstruction-based anomaly detection)
Input: [temperature, motion_count, ble_node_count] — 3 features
Output: anomaly_score (0.0 = normal, 1.0 = anomalous)
Size: ~15KB (quantized INT8)
Inference time: ~2ms on ESP32-S3

Why edge inference? Sending all telemetry to the cloud for analysis adds latency and bandwidth cost. By running inference on-device, the ESP32-S3 can detect anomalies in real-time and only send alerts for significant events.

MQTT Topics

TopicQoSDirectionContent
aurora/sensors/esp32s3_gw_01/telemetry1PublishSensor readings + anomaly score
aurora/sensors/esp32s3_gw_01/alerts2PublishAnomaly alerts
aurora/sensors/esp32s3_gw_01/status1PublishDevice status (startup, heartbeat)
aurora/command/esp32s3_gw_01/action1SubscribeCommands from SOC

BLE Scanning

The ESP32-S3 scans for BLE advertisements from nRF52840 nodes:

void ble_scanner_init(void) {
struct bt_le_scan_param scan_param = {
.type = BT_LE_SCAN_TYPE_PASSIVE,
.options = BT_LE_SCAN_OPT_NONE,
.interval = BT_GAP_SCAN_FAST_INTERVAL,
.window = BT_GAP_SCAN_FAST_WINDOW,
};
bt_le_scan_start(&scan_param, scan_callback);
}

static void scan_callback(const bt_addr_le_t *addr, int8_t rssi,
uint8_t adv_type, struct net_buf_simple *buf) {
// Parse manufacturer-specific data from nRF52840 nodes
// Extract: temperature, motion_detected, tamper_status, battery_mv
// Update aggregate sensor data
}

Attestation

Every 5 minutes, the ESP32-S3 performs firmware attestation:

static void attestation_timer_handler(struct k_timer *timer) {
// 1. Compute SHA-256 of firmware partition
char firmware_hash[65];
compute_firmware_sha256(firmware_hash);

// 2. Sign attestation payload
// Uses software ECDSA (ESP32-S3 lacks hardware crypto accelerator)

// 3. Publish to attestation topic
mqtt_publish(TOPIC_STATUS, attestation_payload, MQTT_QOS_2_EXACTLY_ONCE);
}

Build System

# Configure for ESP32-S3
west build -b esp32s3_devkitm firmware/esp32s3

# Flash
west flash

# Monitor serial output
west espressif monitor

Kconfig Options

# prj.conf
CONFIG_BT=y
CONFIG_BT_OBSERVER=y
CONFIG_MQTT_LIB=y
CONFIG_MQTT_LIB_TLS=y
CONFIG_WIFI=y
CONFIG_AURORA_ANOMALY_THRESHOLD=0.7