Page 1 of 1

BLE server for Battery Service application

Posted: Thu Oct 11, 2018 8:26 am
by Aswinth
Hi,
I am using Arduino to program ESP32.

I am very new to BLE but have been working with Arduino for a long time. My knowledge on BLE is limited to https://www.youtube.com/watch?v=2mePPqiocUE this video.

My idea here is to program the ESP32 as a server which uses GAT services to display the battery level on my phone (client) when the bluetooth connection is paired. I am partially successful with the below code

Code: Select all

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

byte percentage = byte(62);
byte level[1] = {percentage};

bool _BLEClientConnected = false;

#define BatteryService BLEUUID((uint16_t)0x180F)
BLECharacteristic BatteryLevelCharacteristic(BLEUUID((uint16_t)0x2A19), BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor BatteryLevelDescriptor(BLEUUID((uint16_t)0x2901));

class MyServerCallbacks : public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      _BLEClientConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      _BLEClientConnected = false;
    }
};


void InitBLE() {
  BLEDevice::init("BLE Battery");
  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pBattery = pServer->createService(BatteryService);

  pBattery->addCharacteristic(&BatteryLevelCharacteristic);
  BatteryLevelDescriptor.setValue("Percentage 0 - 100");
  BatteryLevelCharacteristic.addDescriptor(&BatteryLevelDescriptor);
  BatteryLevelCharacteristic.addDescriptor(new BLE2902());

  pServer->getAdvertising()->addServiceUUID(BatteryService);

  pBattery->start();
  // Start advertising
  pServer->getAdvertising()->start();
}

void setup() {
  Serial.begin(115200);
  Serial.println("Battery Level Indicator - BLE");
  InitBLE();
}

void loop() {

  BatteryLevelCharacteristic.setValue(level, 1);
  BatteryLevelCharacteristic.notify();
  delay(2000);
  
  percentage++;
  level[1] = (byte)percentage;
  Serial.println(level[1]);

}
In the above code I have hard coded the battery percentage to be 62% and then increment the value for every 2 seconds. I expected the program to display the battery level on the status bar of my phone just like my bluetooth headphones but it did not happen.

I am using nRF mobile application to monitor the BLE server and there I am able to receive the data that was initialized, I am not getting it to update for every 2 sec, it stays at 62% as shown below.

Image

I am also a bit confused on the characteristic function Read and Notify. What does it mean why is notify optional? Also since we are writing the battery level from server to client should it not be write instead of Read?

Re: BLE server for Battery Service application

Posted: Thu Oct 11, 2018 12:31 pm
by chegewara
For battery service i prefer to add those descriptors:
https://github.com/nkolban/esp32-snippe ... pp#L38-L45

It allows me to send value from 0-100 and client like nRF connect take cares how to parse it.

I dont know exactly what you want to achieve, but basically battery level service and characteristic are to inform client device (in most case its client, in your case smartphone) what battery level i on peripheral peer device (again, in most case usage its GATT server, in your case esp32). In such case you will use notifications to send value depend how you program esp32, every constant time period or when battery level is changed, many options. In addition you have read permission on characteristic. This means you can read value on demand, but you have to implement characteristic callback with onRead function.

Re: BLE server for Battery Service application

Posted: Thu Oct 11, 2018 12:49 pm
by Aswinth
Hi,
Thanks for your reply.

I am trying to achieve something like this Image.

Why do we need to add HID service for this?

Code: Select all

void loop() {

  BatteryLevelCharacteristic.setValue(level, 1);
  BatteryLevelCharacteristic.notify();
  delay(2000);
  
  percentage++;
  level[1] = (byte)percentage;
  Serial.println(level[1]);

}
As far as my understanding goes, the above code should update the battery value in my nRF application, can you please tell me why it is not happening?