# Simple BLE OTA
A drop-in ESP32 component that adds Over-The-Air (OTA) firmware update capability via Bluetooth Low Energy.
## Features
- **High Performance**: 40+ KB/s transfer speeds
- **Data Integrity**: CRC32 verification prevents corrupted firmware
- **Error Reporting**: Real-time notifications for failures
- **Drop-in Integration**: Single function call to enable OTA
- **Non-intrusive**: Works alongside existing BLE services
- **Python Client**: Included client for easy firmware uploads
## Quick Start
### 1. Add Component
Add to your project's `idf_component.yml`:
```yaml
dependencies:
simple_ble_ota:
version: "^0.1.0"
```
Or clone directly into your `components/` directory.
### 2. Initialize in Code
```c
#include "simple_ble_ota.h"
void app_main(void)
{
// Initialize NVS, NimBLE, etc. (your existing code)
// Add Simple BLE OTA service
ESP_ERROR_CHECK(simple_ble_ota_init());
// Continue with your application...
}
```
### 3. Upload Firmware
Use the included Python client:
```bash
python3 simple-ble-ota-client.py firmware.bin
```
## Requirements
- **ESP-IDF**: >= 5.4.0
- **BLE Stack**: NimBLE only
- **Python Client**: `pip install bleak`
## Protocol
The component implements a custom protocol over BLE GATT:
- **Service UUID**: `487d0950-41b9-4c57-ad09-a46ac47e2150`
- **Control Point**: `487d0950-41b9-4c57-ad09-a46ac47e2151` (Write + Notify)
- **Data**: `487d0950-41b9-4c57-ad09-a46ac47e2152` (Write + Write-No-Response)
### Commands
1. **START (0x01)**: `[0x01][size_bytes_0-3]` - Begin OTA with firmware size
2. **DATA**: Chunked firmware data (244 bytes optimal)
3. **COMPLETE (0x02)**: `[0x02][crc32_bytes_0-3]` - Finalize with CRC verification
4. **ERROR (0xFF)**: `[0xFF][error_code]` - Error notifications from ESP32
## Integration Notes
### BLE Stack Initialization
This component requires NimBLE to be initialized before calling `simple_ble_ota_init()`:
```c
// Example BLE initialization
nimble_port_init();
ble_hs_cfg.sync_cb = ble_app_on_sync;
ble_svc_gap_device_name_set("MyDevice");
ble_svc_gap_init();
ble_svc_gatt_init();
// Now add Simple BLE OTA
simple_ble_ota_init();
// Start NimBLE
nimble_port_freertos_init(nimble_host_task);
```
### Existing Services
The component adds its service without affecting existing GATT services. You can add other services before or after calling `simple_ble_ota_init()`.
### Device Naming
The component does not set the BLE device name. Use your existing method:
```c
ble_svc_gap_device_name_set("MyDevice");
```
## Python Client
### Installation
```bash
pip install bleak
```
### Usage
```bash
# Basic usage
python3 simple-ble-ota-client.py firmware.bin
# Custom device name
python3 simple-ble-ota-client.py firmware.bin "MyDevice"
# Show help
python3 simple-ble-ota-client.py --help
```
### Client Features
- Automatic device discovery by name
- Progress tracking with throughput display
- CRC32 integrity verification
- Comprehensive error handling
- Batched transfers for optimal performance
## API Reference
### Functions
#### `esp_err_t simple_ble_ota_init(void)`
Initializes the Simple BLE OTA service and adds it to the GATT server.
**Prerequisites:**
- NimBLE stack initialized
- BLE host synced
- GATT server running
**Returns:**
- `ESP_OK`: Success
- `ESP_ERR_INVALID_STATE`: BLE not initialized
- `ESP_FAIL`: Failed to add service
#### `bool simple_ble_ota_is_active(void)`
Check if an OTA update is currently in progress.
**Returns:**
- `true`: OTA update active
- `false`: OTA idle
## Error Codes
The ESP32 reports errors via BLE notifications:
- `0x01`: CRC mismatch (data corruption)
- `0x02`: Partition full (insufficient space)
- `0x03`: OTA begin failed
- `0x04`: OTA write failed
- `0x05`: OTA end failed
- `0xFF`: Unknown error
## Performance
- **Transfer Speed**: 40+ KB/s typical
- **Chunk Size**: 244 bytes (optimal for BLE MTU)
- **Flow Control**: Batched writes with periodic synchronization
- **Memory Usage**: Minimal - uses ESP-IDF OTA buffers
## Troubleshooting
### Common Issues
**"NimBLE stack not initialized"**
- Ensure `nimble_port_init()` is called before `simple_ble_ota_init()`
**Device not discoverable**
- Set device name with `ble_svc_gap_device_name_set()`
- Start advertising after initialization
**Connection fails**
- Check device name matches Python client parameter
- Ensure BLE advertising is active
- Verify no firewall blocking Bluetooth
**Transfer fails**
- Check partition table has OTA partitions
- Ensure sufficient flash space
- Verify firmware size is correct
### Debug Logging
Enable component logging:
```c
esp_log_level_set("SIMPLE_BLE_OTA", ESP_LOG_DEBUG);
```
## License
MIT License - see LICENSE file for details.
## Publish to Registry
```sh
$ compote registry login --profile "staging" --registry-url "https://components-staging.espressif.com" --default-namespace kodira
$ compote component upload --profile "staging" --name simple_ble_ota
```
idf.py add-dependency "kodira/simple_ble_ota^0.1.0"