Skip to content

d0773d/esp32_S3_wifi_provisioning_using_c_example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ESP32-S3 WiFi Provisioning over Secure BLE# ESP32-S3 WiFi Provisioning over Secure BLE

Note: Full documentation has been moved to the docs/ folder.This project implements WiFi provisioning for ESP32-S3 using a secure, bonded BLE connection. The device receives WiFi credentials via JSON over BLE, connects to the network, and saves the credentials to NVS upon successful connection. Real-time status updates are sent to the provisioning app via BLE notifications.

Quick Start## Features


# Build the project- ✅ **JSON-based Credentials**: Receives WiFi credentials in JSON format: `{"ssid":"network","password":"pass"}`

idf.py build- ✅ **Real-time Notifications**: Sends provisioning status updates to mobile app via BLE notifications

- ✅ **NVS Storage**: Saves WiFi credentials to Non-Volatile Storage after successful connection

# Flash to ESP32-S3- ✅ **Auto-reconnect**: Automatically connects to stored WiFi on subsequent boots

idf.py -p COM3 flash monitor- ✅ **Comprehensive Error Handling**: Detailed error codes for authentication failures, timeouts, etc.

```- ✅ **State Machine**: Tracks provisioning progress through well-defined states

- ✅ **Power Efficient**: Disables BLE after successful provisioning

## Project Structure

## Architecture

esp32_S3/### Components

├── main/ # Application source code

│ ├── main.c # Main application entry point1. BLE Provisioning (ble_provisioning.c/h)

│ ├── ble_provisioning.c # BLE GATT server implementation - GATT server with custom service

│ ├── wifi_manager.c # WiFi connection and NVS storage - WiFi credentials characteristic (write)

│ └── provisioning_state.c # State machine - Provisioning status characteristic (notify)

├── docs/ # Documentation - Secure bonding implementation

│ ├── README.md # Complete project documentation

│ ├── KOTLIN_INTEGRATION.md # Mobile app integration guide2. WiFi Manager (wifi_manager.c/h)

│ └── UUID_MAPPING.md # BLE UUID reference - WiFi connection handling

├── config/ # Configuration files - Event-driven architecture

│ ├── sdkconfig.defaults # Default ESP-IDF configuration - NVS credential storage

│ └── partitions.csv # Flash partition table - Connection retry logic

├── test/ # Test files and examples

│ ├── test_credentials.json3. Provisioning State Machine (provisioning_state.c/h)

│ └── test_credentials_examples.txt - State tracking and transitions

└── build/ # Build artifacts (generated) - Status code definitions




## Features4. **Main Application** (`main.c`)

   - System initialization

- ✅ Secure BLE Communication with bonding/pairing   - Component orchestration

- ✅ JSON-based WiFi credentials   - Stored credential handling

- ✅ Real-time status notifications

- ✅ NVS credential storage### BLE Service Structure

- ✅ Auto-reconnect on boot

- ✅ Comprehensive error handling**Service UUID**: `00467768-6228-2272-4663-277478268000`



## Documentation| Characteristic | UUID | Properties | Description |

|----------------|------|------------|-------------|

- **[Complete Guide](docs/README.md)** - Full project documentation, architecture, and usage| State | `00467768-6228-2272-4663-277478268001` | Read | Current provisioning state |

- **[Kotlin Integration](docs/KOTLIN_INTEGRATION.md)** - Android app development guide| WiFi Credentials | `00467768-6228-2272-4663-277478268002` | Write | Receives JSON with SSID and password |

- **[UUID Mapping](docs/UUID_MAPPING.md)** - BLE service and characteristic reference| Status | `00467768-6228-2272-4663-277478268003` | Read, Notify | Sends status updates to app |



## Device Information### Provisioning States



- **Device Name**: `ESP32_WiFi_Prov`| State | Description |

- **Service UUID**: `00467768-6228-2272-4663-277478268000`|-------|-------------|

- **Security**: LE Secure Connections with MITM protection| `IDLE` | Waiting for BLE connection |

| `BLE_CONNECTED` | Client connected, waiting for credentials |

## License| `CREDENTIALS_RECEIVED` | Valid credentials received |

| `WIFI_CONNECTING` | Attempting WiFi connection |

This project is provided as-is for educational and commercial use.| `WIFI_CONNECTED` | Connected to WiFi, saving credentials |

| `PROVISIONED` | Successfully provisioned |

---| `WIFI_FAILED` | WiFi connection failed |

| `ERROR` | Error occurred during provisioning |

**Version**: 1.0.0  

**Date**: November 2025### Status Codes


- `SUCCESS`: Operation successful
- `ERROR_INVALID_JSON`: Malformed JSON data
- `ERROR_MISSING_SSID`: SSID field missing
- `ERROR_MISSING_PASSWORD`: Password field missing
- `ERROR_WIFI_TIMEOUT`: Connection timeout
- `ERROR_WIFI_AUTH_FAILED`: Wrong password
- `ERROR_WIFI_NO_AP_FOUND`: SSID not found
- `ERROR_STORAGE_FAILED`: NVS write failed

## Prerequisites

- ESP-IDF v5.0 or later
- ESP32-S3 development board
- USB cable for flashing and monitoring

## Building and Flashing

### 1. Set up ESP-IDF environment

```powershell
# If not already set up, install ESP-IDF and configure the environment
# Follow: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/

# Activate ESP-IDF environment
. $env:IDF_PATH\export.ps1

2. Configure the project

cd c:\Code\esp32_S3
idf.py set-target esp32s3
idf.py menuconfig

Recommended menuconfig settings:

  • Component config → Bluetooth → Enable Bluetooth
  • Component config → Bluetooth → Bluedroid Enable
  • Component config → Bluetooth → Enable BLE only
  • Component config → Bluetooth → Enable secure connections

3. Build the project

idf.py build

4. Flash to ESP32-S3

idf.py -p COM3 flash monitor

Replace COM3 with your actual serial port.

Usage

First Boot (No Stored Credentials)

  1. Device starts and initializes BLE provisioning
  2. BLE advertising begins with device name: ESP32_WiFi_Prov
  3. Connect to the device from your provisioning app
  4. Device will request bonding/pairing (Just Works method)
  5. Send WiFi credentials via JSON to the WiFi Credentials characteristic:
{
  "ssid": "YourNetworkName",
  "password": "YourPassword"
}
  1. Monitor status updates via notifications on the Provisioning Status characteristic
  2. Upon successful connection, credentials are saved to NVS
  3. BLE provisioning service stops automatically

Subsequent Boots (With Stored Credentials)

  1. Device reads stored credentials from NVS
  2. Automatically connects to the stored WiFi network
  3. BLE provisioning is NOT started (power saving)
  4. If connection fails, BLE provisioning starts as fallback

Status Notification Format

The app receives JSON notifications with the following structure:

{
  "state": "WIFI_CONNECTED",
  "status": "SUCCESS",
  "message": "192.168.1.100",
  "timestamp": 12345
}

Mobile App Development Guide

BLE Connection Flow

  1. Scan for devices advertising the provisioning service
  2. Connect to the ESP32 device
  3. Pair/Bond - Accept the pairing request
  4. Discover services and characteristics
  5. Subscribe to notifications on the Status characteristic (00467768-6228-2272-4663-277478268003)
  6. Write JSON credentials to the WiFi Credentials characteristic (00467768-6228-2272-4663-277478268002)
  7. Monitor status notifications until PROVISIONED or ERROR state

Example Mobile App Code (Kotlin)

// UUIDs matching your app
val WIFI_SERVICE_UUID = UUID.fromString("00467768-6228-2272-4663-277478268000")
val STATE_CHAR_UUID = UUID.fromString("00467768-6228-2272-4663-277478268001")
val WIFICREDS_CHAR_UUID = UUID.fromString("00467768-6228-2272-4663-277478268002")
val STATUS_CHAR_UUID = UUID.fromString("00467768-6228-2272-4663-277478268003")

// 1. Connect and bond
device.connect()
device.createBond()

// 2. Discover services
val service = device.getService(WIFI_SERVICE_UUID)
val wifiCredChar = service.getCharacteristic(WIFICREDS_CHAR_UUID)
val statusChar = service.getCharacteristic(STATUS_CHAR_UUID)

// 3. Subscribe to notifications
statusChar.setNotificationEnabled(true)
statusChar.onNotificationReceived { data ->
    val status = JSONObject(String(data))
    Log.d("Provision", "Status: ${status.getString("state")} - ${status.getString("message")}")
    
    when (status.getString("state")) {
        "PROVISIONED" -> {
            Log.i("Provision", "Success! Device IP: ${status.getString("message")}")
            device.disconnect()
        }
        "ERROR", "WIFI_FAILED" -> {
            Log.e("Provision", "Error: ${status.getString("status")} - ${status.getString("message")}")
        }
    }
}

// 4. Send credentials
val credentials = JSONObject().apply {
    put("ssid", "MyNetwork")
    put("password", "MyPassword123")
}

wifiCredChar.write(credentials.toString().toByteArray())

Security Considerations

Current Implementation

  • BLE Bonding: Enabled with MITM protection
  • Pairing Method: Just Works (no PIN required)
  • Encryption: All BLE communication encrypted after pairing
  • NVS Encryption: Enabled in sdkconfig (optional)

Production Recommendations

  1. ✅ 128-bit UUIDs: Already implemented - matches your Kotlin app UUIDs
  2. Passkey Entry: Change ESP_IO_CAP_NONE to ESP_IO_CAP_OUT and display a PIN
  3. Certificate Pinning: Validate mobile app certificate before accepting credentials
  4. Rate Limiting: Add delays between failed connection attempts
  5. Secure Storage: Enable NVS encryption with unique keys per device
  6. OTA Updates: Implement secure firmware updates
  7. Timeout: Add timeout for provisioning mode

Clearing Stored Credentials

To reset the device and clear stored WiFi credentials:

// Call this function from your code
wifi_manager_clear_credentials();

Or erase NVS flash completely:

idf.py -p COM3 erase-flash

Troubleshooting

Device not advertising

  • Check BLE is enabled in menuconfig
  • Verify idf.py set-target esp32s3 was run
  • Check logs for initialization errors

Cannot pair/bond

  • Ensure mobile app supports BLE bonding
  • Check device has enough memory
  • Try erasing flash and reflashing

WiFi connection fails

  • Verify SSID and password are correct
  • Check WiFi network is 2.4GHz (ESP32 doesn't support 5GHz)
  • Ensure WPA2-PSK authentication
  • Check distance to access point

Not receiving notifications

  • Ensure characteristic notifications are subscribed
  • Verify bonding completed successfully
  • Check MTU size (default 517 bytes)

Logging

The project uses ESP-IDF logging with the following tags:

  • MAIN: Main application
  • BLE_PROV: BLE provisioning
  • WIFI_MGR: WiFi manager
  • PROV_STATE: State machine

Set log level in menuconfig or via code:

esp_log_level_set("BLE_PROV", ESP_LOG_DEBUG);

Power Consumption

  • BLE Advertising: ~50-80mA
  • BLE Connected: ~60-100mA
  • WiFi Connected: ~80-150mA
  • Deep Sleep (not implemented): ~10μA

After provisioning, BLE is disabled to save power.

Future Enhancements

  • Add support for WPA3 networks
  • Implement AP mode fallback provisioning
  • Add device reset button (GPIO long press)
  • Support multiple WiFi credential storage
  • Add web-based provisioning interface
  • Implement cloud provisioning
  • Add MQTT connectivity check
  • Battery level monitoring and reporting

License

This project is provided as-is for educational and commercial use.

References


Project: ESP32-S3 WiFi BLE Provisioning
Version: 1.0.0
Date: November 2025

About

No description, website, or topics provided.

Resources

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors