Why Bluetooth Low Energy?
I chose BLE as the communication protocol for several reasons:
- Universal compatibility: Every modern smartphone has BLE built-in
- No pairing required: Users can connect instantly without entering codes
- Low power consumption: Critical for battery-operated devices
- Real-time notifications: Push data to connected clients automatically
- Multiple connections: Phone AND robot display can connect simultaneously
- Industry standard: Well-documented with robust libraries
Service & Characteristics Architecture
BLE uses a hierarchical structure of Services and Characteristics. I designed
my protocol to be intuitive and extensible:
📡 BLE Device: "WaterBottle"
│
└── 📦 Service: Hydration Monitor
UUID: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
│
├── 📊 Characteristic: Current Weight
│ UUID: beb5483e-36e1-4688-b7f5-ea07361b26a8
│ Properties: READ, NOTIFY
│ Data: String (grams)
│
├── 💧 Characteristic: Water Consumed
│ UUID: beb5483e-36e1-4688-b7f5-ea07361b26a9
│ Properties: READ, NOTIFY
│ Data: String (grams)
│
├── 📈 Characteristic: Percentage Remaining
│ UUID: beb5483e-36e1-4688-b7f5-ea07361b26aa
│ Properties: READ, NOTIFY
│ Data: String (0-100)
│
└── 🎛️ Characteristic: Control Commands
UUID: beb5483e-36e1-4688-b7f5-ea07361b26ab
Properties: READ, WRITE, NOTIFY
Data: String (single char commands)
💡 Design Decision: UUIDs
Notice how the UUIDs are almost identical except for the last two digits
(a8, a9, aa, ab)? This makes them easy to identify in BLE scanning tools
while maintaining uniqueness. The base UUID was generated randomly to avoid
conflicts with other BLE devices.
Notification vs Polling
BLE supports two ways to get data from devices:
| Method |
How It Works |
Best For |
| Polling (READ) |
App requests data on demand |
One-time checks, debugging |
| Notifications (NOTIFY) |
Device pushes updates automatically |
Real-time monitoring, live data |
My system uses notifications by default, pushing updates every
1 second to all subscribed clients. This is more efficient than having the phone
constantly poll for new data.
Firmware Implementation
Here's how the BLE server broadcasts data in the ESP32 firmware:
// Called every 1 second in main loop
void updateBLE() {
// Format current weight as string
String currentStr = String(currentWeight, 1);
pCharCurrent->setValue(currentStr.c_str());
pCharCurrent->notify(); // Push to all subscribers
// Format water consumed
String consumedStr = String(waterConsumed, 1);
pCharConsumed->setValue(consumedStr.c_str());
pCharConsumed->notify();
// Format percentage (integer)
String percentStr = String(percentRemaining);
pCharPercent->setValue(percentStr.c_str());
pCharPercent->notify();
}
For complete BLE server and client implementation details, see the
BLE Communication section
of my Final Project page.