BLE Receive Arduino IDE VS MicroPython

Hi everyone!
I developed an app in Thunkable X and coded in Arduino IDE, enabling communication between them via BLE. Sending and receiving data worked well for both the app and my ESP32.

However, I decided to explore a different approach and rewrote my code in MicroPython. Now, I can successfully send data from the app to my ESP32, but encountering an issue when sending data back from ESP32 to the app. A BLE terminal works fine with both the Arduino IDE and MicroPython codes, but in Thunkable, only the Arduino code works for receiving data.

Both codes have the same TX UUID set as NOTIFY and READ (see pictures below), so it’s unclear why the problem persists.

I have included my codes and screenshots of the BLE scanner to illustrate the UUID properties for both codes are the same. Any assistance you can provide would be greatly appreciated. Thank you!

Arduino IDE code (BLE part):

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

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

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      rxValue = pCharacteristic->getValue();

      if (rxValue.length() > 0) {
        Serial.print("Received Value: ");

        for (int i = 0; i < rxValue.length(); i++) {


        rxValueString = rxValue.c_str();
        verwerkt = 1;
  // Create the BLE Device
  BLEDevice::init("ChickMate"); // Give it a name

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

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
  pCharacteristic->addDescriptor(new BLE2902());
  pCharacteristic->setCallbacks(new MyCallbacks());

  BLECharacteristic *pCharacteristic = pService->createCharacteristic(

  pCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service

  // Start advertising
  Serial.println("Waiting a client connection to notify...");

MicroPyton code (BLE part):

ble_msg = ""

class ESP32_BLE():
    def __init__(self, name):
        # Create internal objects for the onboard LED
        # blinking when no BLE device is connected
        # stable ON when connected
        self.led = Pin(2, Pin.OUT)
        self.timer1 = Timer(0)
        = name
        self.ble = ubluetooth.BLE()

    def connected(self):
        print("BLE device connected succesfully")

    def disconnected(self):        
        self.timer1.init(period=100, mode=Timer.PERIODIC, callback=lambda t: self.led.value(not self.led.value()))
        print("No BLE device connected")

    def ble_irq(self, event, data):
        global ble_msg
        if event == 1: #_IRQ_CENTRAL_CONNECT:
                       # A central has connected to this peripheral

        elif event == 2: #_IRQ_CENTRAL_DISCONNECT:
                         # A central has disconnected from this peripheral.
        elif event == 3: #_IRQ_GATTS_WRITE:
                         # A client has written to this characteristic or descriptor.          
            buffer = self.ble.gatts_read(self.rx)
            ble_msg = buffer.decode('UTF-8').strip()
    def register(self):        
        # Nordic UART Service (NUS)
        NUS_UUID = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'
        RX_UUID = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E'
        TX_UUID = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E'
        #NUS_UUID = '0000AAAA-0000-1000-8000-00805F9B34FB'
        #RX_UUID = '0000AAAA-0002-1000-8000-00805F9B34FB'
        #TX_UUID = '0000AAAA-0001-1000-8000-00805F9B34FB'
        BLE_NUS = ubluetooth.UUID(NUS_UUID)
        BLE_RX = (ubluetooth.UUID(RX_UUID), ubluetooth.FLAG_WRITE)
        BLE_TX = (ubluetooth.UUID(TX_UUID), ubluetooth.FLAG_READ) # Add the READ property here
        BLE_UART = (BLE_NUS, (BLE_TX, BLE_RX,))
        SERVICES = (BLE_UART, )
        ((self.tx, self.rx,), ) = self.ble.gatts_register_services(SERVICES)

    def send(self, data):
        self.ble.gatts_notify(0, self.tx, data)

    def advertiser(self):
        name = bytes(, 'UTF-8')
        adv_data = bytearray(b'\x02\x01\x02') + bytearray((len(name) + 1, 0x09)) + name
        self.ble.gap_advertise(100, adv_data)



I have a similar problem and was wondering if you solved your problem yet?
If not I may have an idea, so let me know.

I had the same problem. What worked for me is knowing that Thunktable doesn’t support Notify data, just Write data.

to send data from ESP32 to app I use this function:

def write(self, data, ntfy = False):
self._ble.gatts_write(self._tx_handle, data)
for conn_handle in self._connections:
self._ble.gatts_notify(conn_handle, self._tx_handle)

try using gatts_write instead of gatts_notify.

1 Like