bleak
bleak copied to clipboard
Immediate disconnect after successful connection With esp as server and raspi as client
- bleak version: 0.22.2
- Python version: 3.8
- Operating System: Ubuntu 22.04 server
- BlueZ version (
bluetoothctl -v
) in case of Linux: 5.53
Description
I am attemtpting to connect my raspberry pi (as a client) to the esp (as a server). As there might be multiple esp/raspi talking to the main esp, i chose the server multi-connect code for the esp for testing.
What happens is that the raspi and esp would immediately disconnect after connecting.
From my understanding, the initial connection is successful, because the onConnect() callback was triggered on the esp side.
The following code runs on my raspi:
import asyncio
from bleak import BleakClient, BleakScanner
# Add your device's address here.
# Can be UUID or MAC address
address = 'EC:DA:3B:67:6E:FD'
async def main():
device = await BleakScanner.find_device_by_address(address)
print(f"device found: {device}")
async with BleakClient(device) as client:
print(f'Client connection = {client.is_connected}') # prints True or False
if __name__ == "__main__":
asyncio.run(main())
The following code is running on my esp32s3
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
Based on Neil Kolban example for IDF:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
updated by chegewara
Create a BLE server that, once we receive a connection, will send periodic
notifications. The service advertises itself as:
4fafc201-1fb5-459e-8fcc-c5c9c331914b And has a characteristic of:
beb5483e-36e1-4688-b7f5-ea07361b26a8
The design of creating the BLE server is:
1. Create a BLE Server
2. Create a BLE Service
3. Create a BLE Characteristic on the Service
4. Create a BLE Descriptor on the characteristic
5. Start the service.
6. Start advertising.
A connect hander associated with the server starts a background task that
performs notification every couple of seconds.
*/
#include <Arduino.h>
#include <BLE2902.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
BLEDevice::startAdvertising();
};
void onDisconnect(BLEServer* pServer) { deviceConnected = false; }
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("ESP32");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService* pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE);
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Descriptor
pCharacteristic->addDescriptor(new BLE2902());
// Start the service
pService->start();
// Start advertising
BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(
0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
// notify changed value
if (deviceConnected) {
pCharacteristic->setValue((uint8_t*)&value, 4);
pCharacteristic->notify();
value++;
delay(10); // bluetooth stack will go into congestion, if too many packets
// are sent, in 6 hours test i was able to go as low as 3ms
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
What I Did
-
For the mac address using in the raspi code, i have confirmed that it is indeed correct with nRF android app and bluetoothctl on raspi.
-
Connecting to the esp with my android phone is successful
Logs
ESP Serial output On esp, this is the serial output
Waiting a client connection to notify...
start advertising (When the raspi code is ran)
start advertising
Strangely, the start advertising
line was shown for 2 times.
Raspi output
python3 src/bluetooth_sender/testing.py
device found: EC:DA:3B:67:6E:FD: ESP32
Traceback (most recent call last):
File "src/bluetooth_sender/testing.py", line 18, in <module>
asyncio.run(main())
File "/usr/lib/python3.8/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
return future.result()
File "src/bluetooth_sender/testing.py", line 14, in main
async with BleakClient(device) as client:
File "/usr/local/lib/python3.8/dist-packages/bleak/__init__.py", line 570, in __aenter__
await self.connect()
File "/usr/local/lib/python3.8/dist-packages/bleak/__init__.py", line 615, in connect
return await self._backend.connect(**kwargs)
File "/usr/local/lib/python3.8/dist-packages/bleak/backends/bluezdbus/client.py", line 273, in connect
await self.get_services(
File "/usr/local/lib/python3.8/dist-packages/bleak/backends/bluezdbus/client.py", line 661, in get_services
self.services = await manager.get_services(
File "/usr/local/lib/python3.8/dist-packages/bleak/backends/bluezdbus/manager.py", line 666, in get_services
await self._wait_for_services_discovery(device_path)
File "/usr/local/lib/python3.8/dist-packages/bleak/backends/bluezdbus/manager.py", line 799, in _wait_for_services_discovery
raise BleakError("failed to discover services, device disconnected")
bleak.exc.BleakError: failed to discover services, device disconnected