I am working with ESP32-C3.
I created a BLE GATT Server, I want to exchange data with it bidirectionally.
I am using nRF Connect android app for debugging.
Charactrictic #1 is used to send data from ESP to nRF Connect. It works fine.
Charactrictic #2 is used to receive data from nRF Connect on ESP32.
It doesn't work: connection, data = await recv_char.written(timeout_ms=_ADV_INTERVAL_MS)
awaits infinitely and never returns. Even when I make a write in NRF Connect. Below is my code, mostly copy-pasted from examples. Please help me find the mistake in data reception on the ESP32 side.
import sys
sys.path.append('')
import asyncio
import aioble
import bluetooth
import machine
import time
led = machine.Pin(8, machine.Pin.OUT)
GATT_UUID = bluetooth.UUID(0x1802)
GATT_CHAR_UUID = bluetooth.UUID("90D3D001-C950-4DD6-9410-2B7AEB1DD7D8")
RECV_CHAR_UUID = bluetooth.UUID("90D3D002-C950-4DD6-9410-2B7AEB1DD7D8")
_ADV_INTERVAL_MS = 250_000
# Register GATT server, the service and characteristics
ble_service = aioble.Service(GATT_UUID)
sensor_characteristic = aioble.Characteristic(ble_service, GATT_CHAR_UUID, read=True, notify=True, write=True,
capture=True)
recv_char = aioble.Characteristic(ble_service, RECV_CHAR_UUID, write=True, notify=True, capture=True)
# Register service(s)
aioble.register_services(ble_service)
def _decode_data(data):
try:
if data is not None:
# Decode the UTF-8 data
number = int.from_bytes(data, 'big')
return number
except Exception as e:
print("Error decoding temperature:", e)
return None
async def peripheral_task():
while True:
try:
async with await aioble.advertise(_ADV_INTERVAL_MS, name="MYNAME",
services=[GATT_UUID], ) as connection:
print("Connection from", connection.device)
await connection.disconnected()
except asyncio.CancelledError:
# Catch the CancelledError
print("Peripheral task cancelled")
except Exception as e:
print("Error in peripheral_task:", e)
finally:
# Ensure the loop continues to the next iteration
await asyncio.sleep_ms(100)
async def wait_for_write():
while True:
try:
connection, data = await recv_char.written(timeout_ms=_ADV_INTERVAL_MS)
# Here it fails ^
print('OLOLO')
print(data)
# print(type)
data = _decode_data(data)
print('Connection: ', connection)
print('Data: ', data)
if data == 1:
print('Turning LED ON')
led.value(1)
elif data == 0:
print('Turning LED OFF')
led.value(0)
else:
print('Unknown command')
except asyncio.CancelledError:
# Catch the CancelledError
print("Wait4Write task cancelled")
except Exception as e:
print("Error in Wait4write_task:", e)
finally:
# Ensure the loop continues to the next iteration
await asyncio.sleep_ms(500)
def _encode_data(data):
return str(data).encode('utf-8')
async def sensor_task():
while True:
value = b'Hello World!'
sensor_characteristic.write(_encode_data(value), send_update=True)
# print('New value written: ', value)
await asyncio.sleep_ms(1000)
# Run tasks
async def ble_main():
t1 = asyncio.create_task(peripheral_task())
t2 = asyncio.create_task(sensor_task())
t3 = asyncio.create_task(wait_for_write())
await asyncio.gather(t1, t2, t3)
I tried various methods of sending data in nRF Connect, also tried to send and receive data in one charactristic. Then I split sending and receiving into 2 distinct characteristics. No effect.
I solved my own problem.
The mistake was:
GATT_UUID = bluetooth.UUID(0x1802)
I changed that UUID to a 128-bit unique one, and it worked. Hope this post helps someone.