BLE ESP32 Client mit versch. ServiceUUIDs

Hallo,
ich bin schon seit einiger Zeit dabei mein Problem zu lösen.
Ich möchte gern mit einem ESP32 die Werte eines Akkus über Bluetooth auslesen.
Dafür gibt es auch eine App bzw. auch eine Web Anwendung welche mit Chrome funktioniert.
Die Werte des Akkus kann man aus verschiedenen Registern auslesen.
Nun habe ich es hinbekommen mit einem BLE Scanner diese Werte auch auszulesen.
Es gibt eine Service UUID und eine Characteristic UUID. Darüber sende ich die Abfrage
für das entsprechende Register.
Um die Antwort des Akkus auszulesen muss ich auf das Feld Notification tippen bzw. es
eingeschalten lassen. Dafür gibt es aber nun eine weitere Service UUID sowie eine
entsprechende Characteristic UUID.
Die Anwendungen für den ESP32 welche ich bisher gefunden habe, z.B. BLE UART client
haben allerdings nur eine Service UUID sowie eine TX- und eine RX-Characteristic UUID.
Gibt es für diesen Fall eventuell auch ein Beispielprogramm bzw. kann mir da jemand helfen?

Vielen Dank schon mal für jegliche Unterstützung.

Mit freundlichen Grüßen Jürgen

Da es hier bislang unheimlich viele Antworten gab, habe ich das mal versucht :blush:

Grundlagen:
Getting Started with ESP32 Bluetooth Low Energy (BLE) on Arduino IDE
ESP32 BLE Server and Client (Bluetooth Low Energy)

In der Vorlage laufen Temperatur und Feuchtigkeit unter einer ServiceUUID. Ich habe nun Temperatur und Feuchtigkeit auf zwei ServiceUUIDs aufgeteilt. Das ist sinnfrei, zeigt aber die Verwendung von zwei ServiceUUIDs. Die Anzeige in Fahrenheit habe ich rausgeworfen und die dafür benutzte UUID als zweite ServiceUUID verwendet, so mußte ich mir keine generieren.

// ESP32 BLE Server
  
/*********
  Rui Santos
  Complete instructions at https://RandomNerdTutorials.com/esp32-ble-server-client/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/

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

//BLE server name
#define bleServerName "BME280_ESP32"

float temp;
float hum;

// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;

bool deviceConnected = false;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define TMP_SERVICE_UUID "91bad492-b950-4226-aa2b-4ede9fa42f59"
#define HUM_SERVICE_UUID "f78ebbff-c8b7-4107-93de-889a6a06d408"

// Temperature Characteristic and Descriptor
BLECharacteristic bmeTemperatureCelsiusCharacteristics("cba1d466-344c-4be3-ab3f-189f80dd7518", BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor bmeTemperatureCelsiusDescriptor(BLEUUID((uint16_t)0x2902));

// Humidity Characteristic and Descriptor
BLECharacteristic bmeHumidityCharacteristics("ca73b3ba-39f6-4ab3-91ae-186dc9577d99", BLECharacteristic::PROPERTY_NOTIFY);
BLEDescriptor bmeHumidityDescriptor(BLEUUID((uint16_t)0x2903));

//Setup callbacks onConnect and onDisconnect
class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
  };
  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};

void setup() {
  // Start serial communication 
  Serial.begin(115200);

  // Create the BLE Device
  BLEDevice::init(bleServerName);

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *tmp_bmeService = pServer->createService(TMP_SERVICE_UUID);
  BLEService *hum_bmeService = pServer->createService(HUM_SERVICE_UUID);

  // Create BLE Characteristics and Create a BLE Descriptor
  // Temperature
  tmp_bmeService->addCharacteristic(&bmeTemperatureCelsiusCharacteristics);
  bmeTemperatureCelsiusDescriptor.setValue("BME temperature Celsius");
  bmeTemperatureCelsiusCharacteristics.addDescriptor(&bmeTemperatureCelsiusDescriptor);

  // Humidity
  hum_bmeService->addCharacteristic(&bmeHumidityCharacteristics);
  bmeHumidityDescriptor.setValue("BME humidity");
  bmeHumidityCharacteristics.addDescriptor(new BLE2902());
  
  // Start the service
  tmp_bmeService->start();
  hum_bmeService->start();

  // Start advertising
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(TMP_SERVICE_UUID);
  pAdvertising->addServiceUUID(HUM_SERVICE_UUID);
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
  if (deviceConnected) {
    if ((millis() - lastTime) > timerDelay) {
      // Read temperature as Celsius (the default)
      temp = random(150, 300) / 10.0;
      // Read humidity
      hum = random(500, 900) / 10.0;
  
      //Notify temperature reading from BME sensor
      static char temperatureCTemp[6];
      dtostrf(temp, 6, 2, temperatureCTemp);
      //Set temperature Characteristic value and notify connected client
      bmeTemperatureCelsiusCharacteristics.setValue(temperatureCTemp);
      bmeTemperatureCelsiusCharacteristics.notify();
      Serial.print("Temperature Celsius: ");
      Serial.print(temp);
      Serial.print(" °C");
      
      //Notify humidity reading from BME
      static char humidityTemp[6];
      dtostrf(hum, 6, 2, humidityTemp);
      //Set humidity Characteristic value and notify connected client
      bmeHumidityCharacteristics.setValue(humidityTemp);
      bmeHumidityCharacteristics.notify();   
      Serial.print(" - Humidity: ");
      Serial.print(hum);
      Serial.println(" %");
      
      lastTime = millis();
    }
  }
}
// ESP32 BLE Client

/*********
  Rui Santos
  Complete instructions at https://RandomNerdTutorials.com/esp32-ble-server-client/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/

#include "BLEDevice.h"
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>

//BLE Server name (the other ESP32 name running the server sketch)
#define bleServerName "BME280_ESP32"

/* UUID's of the service, characteristic that we want to read*/
// BLE Service
static BLEUUID tmp_bmeServiceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59");
static BLEUUID hum_bmeServiceUUID("f78ebbff-c8b7-4107-93de-889a6a06d408");


// BLE Characteristics
//Temperature Celsius Characteristic
static BLEUUID temperatureCharacteristicUUID("cba1d466-344c-4be3-ab3f-189f80dd7518");

// Humidity Characteristic
static BLEUUID humidityCharacteristicUUID("ca73b3ba-39f6-4ab3-91ae-186dc9577d99");

//Flags stating if should begin connecting and if the connection is up
static boolean doConnect = false;
static boolean connected = false;

//Address of the peripheral device. Address will be found during scanning...
static BLEAddress *pServerAddress;

//Characteristicd that we want to read
static BLERemoteCharacteristic* temperatureCharacteristic;
static BLERemoteCharacteristic* humidityCharacteristic;

//Activate notify
const uint8_t notificationOn[] = {0x1, 0x0};
const uint8_t notificationOff[] = {0x0, 0x0};

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

//Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

//Variables to store temperature and humidity
char* temperatureChar;
char* humidityChar;

//Flags to check whether new temperature and humidity readings are available
boolean newTemperature = false;
boolean newHumidity = false;

//Connect to the BLE Server that has the name, Service, and Characteristics
bool connectToServer(BLEAddress pAddress) {
  BLEClient* pClient = BLEDevice::createClient();

  // Connect to the remove BLE Server.
  pClient->connect(pAddress);
  Serial.println(" - Connected to server");

  // Obtain a reference to the service we are after in the remote BLE server.
  BLERemoteService* tmp_pRemoteService = pClient->getService(tmp_bmeServiceUUID);
  if (tmp_pRemoteService == nullptr) {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(tmp_bmeServiceUUID.toString().c_str());
    return (false);
  }

  // Obtain a reference to the service we are after in the remote BLE server.
  BLERemoteService* hum_pRemoteService = pClient->getService(hum_bmeServiceUUID);
  if (hum_pRemoteService == nullptr) {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(hum_bmeServiceUUID.toString().c_str());
    return (false);
  }

  // Obtain a reference to the characteristics in the service of the remote BLE server.
  temperatureCharacteristic = tmp_pRemoteService->getCharacteristic(temperatureCharacteristicUUID);
  humidityCharacteristic = hum_pRemoteService->getCharacteristic(humidityCharacteristicUUID);

  if (temperatureCharacteristic == nullptr || humidityCharacteristic == nullptr) {
    Serial.print("Failed to find our characteristic UUID");
    return false;
  }
  Serial.println(" - Found our characteristics");

  //Assign callback functions for the Characteristics
  temperatureCharacteristic->registerForNotify(temperatureNotifyCallback);
  humidityCharacteristic->registerForNotify(humidityNotifyCallback);
  return true;
}

//Callback function that gets called, when another device's advertisement has been received
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      if (advertisedDevice.getName() == bleServerName) { //Check if the name of the advertiser matches
        advertisedDevice.getScan()->stop(); //Scan can be stopped, we found what we are looking for
        pServerAddress = new BLEAddress(advertisedDevice.getAddress()); //Address of advertiser is the one we need
        doConnect = true; //Set indicator, stating that we are ready to connect
        Serial.println("Device found. Connecting!");
      }
    }
};

//When the BLE Server sends a new temperature reading with the notify property
static void temperatureNotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,
                                      uint8_t* pData, size_t length, bool isNotify) {
  //store temperature value
  temperatureChar = (char*)pData;
  newTemperature = true;
}

//When the BLE Server sends a new humidity reading with the notify property
static void humidityNotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,
                                   uint8_t* pData, size_t length, bool isNotify) {
  //store humidity value
  humidityChar = (char*)pData;
  newHumidity = true;
}

//function that prints the latest sensor readings in the OLED display
void printReadings() {

  display.clearDisplay();
  // display temperature
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.print("Temperature: ");
  display.setTextSize(2);
  display.setCursor(0, 10);
  display.print(temperatureChar);
  display.setTextSize(1);
  display.cp437(true);
  display.write(167);
  display.setTextSize(2);
  Serial.print("Temperature:");
  Serial.print(temperatureChar);
  //Temperature Celsius
  display.print("C");
  Serial.print(" °C");

  //display humidity
  display.setTextSize(1);
  display.setCursor(0, 35);
  display.print("Humidity: ");
  display.setTextSize(2);
  display.setCursor(0, 45);
  display.print(humidityChar);
  display.print("%");
  display.display();
  Serial.print(" Humidity:");
  Serial.print(humidityChar);
  Serial.println(" %");
}

void setup() {
  //OLED display setup
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE, 0);
  display.setCursor(0, 25);
  display.print("BLE Client");
  display.display();

  //Start serial communication
  Serial.begin(115200);
  Serial.println("Starting Arduino BLE Client application...");

  //Init BLE device
  BLEDevice::init("");

  // Retrieve a Scanner and set the callback we want to use to be informed when we
  // have detected a new device.  Specify that we want active scanning and start the
  // scan to run for 30 seconds.
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->start(30);
}

void loop() {
  // If the flag "doConnect" is true then we have scanned for and found the desired
  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are
  // connected we set the connected flag to be true.
  if (doConnect == true) {
    if (connectToServer(*pServerAddress)) {
      Serial.println("We are now connected to the BLE Server.");
      //Activate the Notify property of each Characteristic
      temperatureCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true);
      humidityCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true);
      connected = true;
    } else {
      Serial.println("We have failed to connect to the server; Restart your device to scan for nearby BLE server again.");
    }
    doConnect = false;
  }
  //if new temperature readings are available, print in the OLED
  if (newTemperature && newHumidity) {
    newTemperature = false;
    newHumidity = false;
    printReadings();
  }
  delay(1000); // Delay a second between loops.
}

Serieller Monitor Server:

14:39:12.278 -> Waiting a client connection to notify...
14:40:14.012 -> Temperature Celsius: 23.00 °C - Humidity: 85.50 %
14:40:44.048 -> Temperature Celsius: 28.10 °C - Humidity: 65.40 %
14:41:14.037 -> Temperature Celsius: 26.60 °C - Humidity: 65.40 %
14:41:44.021 -> Temperature Celsius: 15.40 °C - Humidity: 72.40 %
14:42:14.044 -> Temperature Celsius: 27.10 °C - Humidity: 74.30 %

Serieller Monitor Client:

14:40:13.146 -> Starting Arduino BLE Client application...
14:40:13.912 -> Device found. Connecting!
14:40:14.059 ->  - Connected to server
14:40:14.714 ->  - Found our characteristics
14:40:14.814 -> We are now connected to the BLE Server.
14:40:44.850 -> Temperature: 28.10 °C Humidity: 65.40 %
14:41:14.887 -> Temperature: 26.60 °C Humidity: 65.40 %
14:41:44.924 -> Temperature: 15.40 °C Humidity: 72.40 %
14:42:14.947 -> Temperature: 27.10 °C Humidity: 74.30 %

grafik

Ich hoffe, es hilft Dir, ich habe was über Bluetooth Low Energy gelernt :slightly_smiling_face:

Hallo,

Vielen Dank für die Unterstützung.
Ich werde mich gleich mal damit beschäftigen...

Gruß Jürgen

Hallo,

was mir gerade aufgefallen ist,
kann denn ein Client auch Daten an den Server senden?
Das wäre ja wichtig für mich.

Gruß Jürgen

das geht auch.
Ich lese auch mit einem Esp32 ein BMS aus, Dabei muß ich die verschiedenen Telegramme anfordern.
Ich habe mit dem Code angefangen, da er meiner Batterie sehr nahe kam.

Gruß Gisbert

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.