WIO terminal as BLE client, scan reports "serviceUUID: <NULL>"

Trying to get my WIO terminal to act as a BLE client (think it is called “central” in bluetooth lingo)
To get something going I start with a BLE-scan example. I have tried a few, they all have the same problem: serviceUUID: <NULL>

Here is a chunk of output when running the code:

BLE Advertised Device found: Name: , Address: ab:74:31:fd:cd:6f
BLE Advertised Device found: Name: , Address: 90:20:2c:a4:98:44, serviceUUID: <NULL>
BLE Advertised Device found: Name: , Address: 13:21:be:02:0f:48
BLE Advertised Device found: Name: , Address: f8:e8:88:af:b0:76
BLE Advertised Device found: Name: , Address: b5:72:7f:3e:09:48, serviceUUID: <NULL>
BLE Advertised Device found: Name: , Address: da:d3:96:1f:43:16
BLE Advertised Device found: Name: , Address: ab:51:0f:68:c0:51, serviceUUID: <NULL>
BLE Advertised Device found: Name: , Address: 03:e0:b9:bd:28:f3
BLE Advertised Device found: Name: , Address: 84:db:f5:af:fc:71, serviceUUID: <NULL>, serviceUUID: <NULL>, serviceUUID: <NULL>, serviceUUID: <NULL>
BLE Advertised Device found: Name: , Address: 19:3e:57:8e:bf:ec
BLE Advertised Device found: Name: , Address: 2d:ab:9f:36:07:06
BLE Advertised Device found: Name: , Address: 2e:1f:20:0f:4b:4b, serviceUUID: <NULL>
BLE Advertised Device found: Name: , Address: 74:82:e5:4a:e4:46
BLE Advertised Device found: Name: , Address: 4b:bf:58:27:66:d5
BLE Advertised Device found: Name: , Address: 22:97:91:95:cc:f9
BLE Advertised Device found: Name: MOGUL-Device, Address: 65:32:fc:2a:5f:f8, serviceUUID: <NULL>
BLE Advertised Device found: Name: , Address: 68:27:d3:4b:66:d8

Notice when ever a device report it has services the UUID is <NULL>. I know for sure that MOGUL-Device has a valid service, verified with the nRF Connect app.

I have tried both in Arduino-IDE and PlatformIO+vscode. And the two BLE-scan programs are

Anybody know how to get the scan to actually find some service UUID’s too?

I don’t think scan is the only thing not working, I have tried just to connect to a peripheral even when scan couldn’t find a service, but then it just goes haywire when I then try to use the service I know is there.

1 Like

I am experiencing the same issue with the BLE scanner on the SEEED Wio Terminal. It cannot discover services.

I have spent a significant amount of time trying to resolve this issue, but I have not been successful. Discovering custom UUIDs to communicate with peripherals is a basic and critical feature, yet the SEEED BLE scanner fails to discover or submit the UUID services of peripherals.

I have tried multiple approaches, including discovering services both before and after connection, adding delays after connection, and implementing retries in the code. I even attempted to explicitly send messages to services without discovery, but all these efforts failed. It seems there may be a major issue with either the SEEED BLE hardware or its libraries.

Since I purchased the SEEED Wio Terminal specifically for BLE scanning and testing, it will be rendered useless for my purposes if this problem cannot be resolved.

For examle, I can not find UUID of STM32 OTA write which is:
serviceUUID = “0000FE20-CC7A-482A-984A-7F2ED5B3E58F”; // Primary Service
and
“0000FE22-8E22-4541-9D4C-21EDAE82ED19”; // Write Without Response

But with an old MCU like nrf52832, I can easily connect and discover services and send/recive data trought them.

Hi there,

You sure its BLE 5.0 or is it BLE Classic? it makes a difference, for example some older Iphones won’t find a BLE 5.0 device, unless compatibility mode.

HTH
GL :slight_smile: PJ :v:

I tested several peripherals that have 128-bit custom UUIDs for different Services, Seed can not find any of them. With nrf-Connect App on the ios, I can see those are fine, but Seed can not find them. Also, with nrf52 MCU series, I can find them and connect to the peripherals and then discover services and UUIDs, and send/receive data trough them. But Seed Wio can only connect to the peripherals and is not able to find 128-bit UUIDs, so I can not send/receive data with peripherals which have 128-bit UUIDs. I tried manythings, and still not able to fix it.

Hi there,

So which BLE lib are you using and Which BSP are you using for the Nrf52 side?
roll it back and try again… :v:
HTH
GL :slight_smile: PJ :v:

Post the code , using the code tags above " </> " paste it in there. :+1:

1 Like

Hi,

Thank you for following up.

I am using the libraries recommended in the Wiki, similar to the Client example provided there: [Client and Server introduction | Seeed Studio Wiki]

#include "rpcBLEDevice.h"
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

Rolling back is not an option for me because the nRF platform uses its own SoftDevice and C-based libraries, which are entirely different from Arduino libraries.

If you or anyone else knows of an example to send/receive data through custom 128-bit UUID services with the Wio Terminal acting as a Client (Scanner), please share the code or a link. It would be greatly appreciated.

Thank you!
Hossein

Hi there,

Ok, did you update the wireless core?
What about the UART UUID did that work, if not then it’s a LIB issue or something else.
I’ll set this up and try it, time permitting… I have the same hardware.

GL :slight_smile: PJ :v:

1 Like

Thank you for your reply.

Yes, On the Arduino IDE, the Wio Terminal core is 1.8.5 (Seeed SAMD Bords).
And Yes, I updated the BLE core (RTL8720 firmware) to the latest version (2.1.3). I even tried some older versions, as I thought the issue might be with the core rather than the Seeed Arduino libraries. But, that didn’t resolve the problem, so I’ve reverted to using the latest version again.

The Seeed Wio Terminal can connect to peripherals (Servers) successfully but is unable to discover or detect their 128-bit UUIDs. As a result, it cannot send or receive data (read/write) on those services, making communication with the servers entirely impossible.

Regards,
Hossein

Hi there,

So sounds to me like you have checked all the cross streets on this. I feel pretty sure it’s a LIB issue, I need to set it up to test for sure, seem strange only the samd though, I’ll setup an additional Xiao to connect to the UUID thats 128 bit with notify ON.

Meanwhile , If Seeed engineers or support Have anything on this Phenomenon a.k.a bug Please enlighten us.

HTH
GL :slight_smile: PJ :v:

I’m looking for the freeCad file for the enclosure as well So I asked over on the Discord server see what shakes out :+1:

1 Like

It would be great if I could get it to work. Since this is a general-purpose and useful feature, other users may also need it later. Having an example that demonstrates how to define 128-bit UUIDs, discover them after connection, and send/receive data through them would showcase the full capabilities and features of the SEEED Wio with BLE.

On the nRF (Nordic) MCU, there are many examples for client (Scanner/Central) functionality that define 128-bit UUIDs as follows:

#define NUS_BASE_UUID                   {{0x47, 0x71, 0xD0, 0x2A, 0x6C, 0x53, 0x52, 0x8A, 0x56, 0x4E, 0x08, 0xA3, 0x00, 0x00, 0x52, 0xB4}} /**< Used vendor-specific UUID. */
#define BLE_UUID_NUS_SERVICE            0x0100                      /**< The UUID of the Nordic UART Service. */
#define BLE_UUID_NUS_RX_CHARACTERISTIC  0x0101                      /**< The UUID of the RX Characteristic. */
#define BLE_UUID_NUS_TX_CHARACTERISTIC  0x0102                      /**< The UUID of the TX Characteristic. */

These UUIDs are then utilized in the main.c file, like this:

/**@brief NUS UUID. */
static ble_uuid_t const m_nus_uuid =
{
    .uuid = BLE_UUID_NUS_SERVICE,
    .type = NUS_SERVICE_UUID_TYPE
};

To send data via the UUID service:

ble_nus_c_string_send(&m_ble_nus_c, cBuffer_, 5);

To receive data, the ble_nus_c module’s event handler is used, as shown below:

switch (p_ble_nus_evt->evt_type)
{
    case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
        ble_nus_c_handles_assign(...);
        ble_nus_c_tx_notif_enable(p_ble_nus_c);
        // Discovery completed; perform additional actions now if you want.
         ....
        break;

    case BLE_NUS_C_EVT_NUS_TX_EVT:
        ble_nus_chars_received_uart_print(...);
        // Handle received data here.
       ...
        break;

    case BLE_NUS_C_EVT_DISCONNECTED:
        // Handle disconnection and restart scanning.
        ...
        scan_start();
        break;
}

This kind of comprehensive example would greatly illustrate the full potential of the SEEED Wio BLE capabilities and simplify implementation for developers."

1 Like

Hi there,

I couldn’t agree more. The BLE has become the MOST important close network comm tool of the century. something like 60 Billion BLE device… WOW :exploding_head:

I have been preaching to the choir about the Nordic advantage on NOT just the Superior hardware but the Phenomenal support and Software to help and SOLVE problems not present them to the maker, Like some companies.

Now Seeed is the only company caring enough to continue on providing innovative tech for makers but sometimes I feel they are distracted too much by the shiny new thing in the Space. SOFTWARE is a secondary item. NOT with AI they are finding that out forsure…

So even though great HARDWARE products it takes software and support to get the most repeat business. A lot of competitors jumping into AI hardware space and being first may make you end up LAST!.
Just look at all the jetson nano post issues’ with more to come with these new more complex models coming on-line.
reCamera is going to be one of those I’m thinking… time will tell.

GL :slight_smile: PJ :v:

I’ll keep looking for this UID-128 bit issue more this weekend. :+1:

1 Like

Is there any update about UUID-128 bit issue on scan mode? Three month past.

Thank you

Hi there,

SO I set up the first test on the 128 bit UUID, Using a Xiao Nrf52840 as the Peripheral. Basic I can connect to it with Nrf_connect for Desktop BLE app, using a Nordic BLE dongle on the Windows 11 Machine.
Time permitting I’ll work up to the Wio Terminal with both the Peripheral and Central examples.
For the base line tests it will be the Nrf52840 sense (Periph) and a Xiao ESP32C6 for the Central. I’ll use the PC to initially see what the BLE adverts, looks like.
Here’s the Periph I used.

// REV 1.0 - nRF52840 BLE Peripheral with 128-bit UUIDs
// Sends notifications via RX characteristic and receives ACKs via TX characteristic

#include <bluefruit.h>

// Custom 128-bit UUIDs
BLEService customService = BLEService("12345678-1234-5678-1234-56789abcdef0");
BLECharacteristic rxChar = BLECharacteristic("12345678-1234-5678-1234-56789abcdef1");  // Notify
BLECharacteristic txChar = BLECharacteristic("12345678-1234-5678-1234-56789abcdef2");  // Write

uint32_t counter = 0;

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);
  Serial.println("Starting nRF52840 BLE Peripheral with 128-bit UUIDs...");

  Bluefruit.begin();
  Bluefruit.setName("nRF52840-Peripheral");

  customService.begin();

  rxChar.setProperties(CHR_PROPS_NOTIFY);
  rxChar.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
  rxChar.setFixedLen(20);
  rxChar.begin();

  txChar.setProperties(CHR_PROPS_WRITE);
  txChar.setPermission(SECMODE_OPEN, SECMODE_OPEN);
  txChar.setWriteCallback(onWrite);
  txChar.begin();

  startAdvertising();
}

void loop() {
  // Send notification every 5 seconds
  static uint32_t lastSent = 0;
  if (millis() - lastSent > 5000) {
    lastSent = millis();

    String message = "PING " + String(counter++);
    rxChar.notify(message.c_str(), message.length());
    Serial.print("Sent notification: ");
    Serial.println(message);
  }
}

// Called when data is written to TX characteristic
void onWrite(uint16_t conn_hdl, BLECharacteristic* chr, uint8_t* data, uint16_t len) {
  Serial.print("Received from Central: ");
  for (uint16_t i = 0; i < len; i++) {
    Serial.print((char)data[i]);
  }
  Serial.println();
}

void startAdvertising() {
  Bluefruit.Advertising.addService(customService);
  Bluefruit.Advertising.addName();
  Bluefruit.Advertising.setInterval(100, 200);
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setFastTimeout(30);
  Bluefruit.Advertising.start(0);
  Serial.println("Advertising started.");
}

I can connect and subscribe to the notifications , AOK.
I see them change in the console of the BLE App.(pic)

Serial output:

Starting nRF52840 BLE Peripheral with 128-bit UUIDs...
Advertising started.
Sent notification: PING 0
Sent notification: PING 1
Sent notification: PING 2
Sent notification: PING 3
Sent notification: PING 4
---
Sent notification: PING 96
Received from Central: ACK
Sent notification: PING 97
Received from Central: ACK
Received from Central: ACK
Sent notification: PING 98
Received from Central: ACK
Sent notification: PING 99
Received from Central: ACK
Sent notification: PING 100

I type in 41,43, 4B in the write Char and it comes through as an “ACK” :grin:

Central is next with Xiao ESP32C6

HTH
GL :slight_smile: PJ :v:

Here is Central…

// ====================================================================================
// REV 6.2 - ESP32C6 BLE Central with 128-bit UUIDs
// Board: Seeed Studio Xiao ESP32C6
// Description: Connects to an nRF52840 Peripheral, discovers 128-bit service/char,
// subscribes to notifications, and prints raw bytes.
// ====================================================================================

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEClient.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

BLEClient* pClient;
BLERemoteCharacteristic* pRemoteCharacteristic;
BLEAdvertisedDevice* foundDevice = nullptr;
bool doConnect = false;
bool connected = false;

// 128-bit UUIDs
BLEUUID serviceUUID("12345678-1234-5678-1234-56789abcdef0");
BLEUUID charUUID_RX("12345678-1234-5678-1234-56789abcdef1");

// === Notification Callback ===
void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData, size_t length, bool isNotify) {

  Serial.print("Notification received: ");
  for (size_t i = 0; i < length; i++) {
    Serial.print((char)pData[i]);
  }
  Serial.println();

  Serial.print("Raw bytes: ");
  for (size_t i = 0; i < length; i++) {
    Serial.printf("%02X ", pData[i]);
  }
  Serial.println("\n");
}

// === Scan Callback ===
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice) override {
    Serial.println("\nFound device:");
    Serial.print("  Name: "); Serial.println(advertisedDevice.getName().c_str());
    Serial.print("  Address: "); Serial.println(advertisedDevice.getAddress().toString().c_str());
    Serial.print("  RSSI: "); Serial.println(advertisedDevice.getRSSI());

    if (advertisedDevice.haveServiceUUID() &&
        advertisedDevice.isAdvertisingService(serviceUUID)) {
      Serial.println("  --> Target service UUID matched.");
      BLEDevice::getScan()->stop();
      foundDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
    } else {
      Serial.println("  --> Service UUID not matched.");
    }
  }
};

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println();
  Serial.println("// =============================");
  Serial.println("// REV 6.2 - ESP32C6 BLE Central");
  Serial.println("// Scans, connects, and receives 128-bit UUID notifications");
  Serial.println("// =============================\n");

  BLEDevice::init("");
  BLEDevice::setPower(ESP_PWR_LVL_P9);  // Max TX power

  BLEScan* pScan = BLEDevice::getScan();
  pScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), false);
  pScan->setActiveScan(true);
  pScan->start(10, false);
}

void loop() {
  if (doConnect && !connected && foundDevice != nullptr) {
    Serial.println("\nConnecting to target device...");

    pClient = BLEDevice::createClient();
    if (pClient->connect(foundDevice)) {
      Serial.println("Connected to Peripheral.");

      BLERemoteService* pService = pClient->getService(serviceUUID);
      if (!pService) {
        Serial.println("Service not found. Disconnecting.");
        pClient->disconnect();
        return;
      }

      pRemoteCharacteristic = pService->getCharacteristic(charUUID_RX);
      if (!pRemoteCharacteristic) {
        Serial.println("Characteristic not found. Disconnecting.");
        pClient->disconnect();
        return;
      }

      if (pRemoteCharacteristic->canNotify()) {
        pRemoteCharacteristic->registerForNotify(notifyCallback);
        Serial.println("Subscribed to notifications.");
        connected = true;
      }
    } else {
      Serial.println("Connection failed.");
    }

    doConnect = false;
  }

  delay(100);
}

Here is the Serial OUtput from the ESP32C6 Central able to Scan , Connect and Subscribe… like a boss. It should work the same in the “Wio” but I’m afraid “Nio”… LOL you see what I did there :grin:

// =============================
// REV 6.2 - ESP32C6 BLE Central
// Scans, connects, and receives 128-bit UUID notifications
// =============================


Found device:
  Name: ASecure Cap 833A
  Address: 7f:2f:a9:76:df:bf
  RSSI: -90
  --> Service UUID not matched.

Found device:
  Name: 
  Address: 50:16:f4:a1:c7:6a
  RSSI: -71
  --> Service UUID not matched.
Found device:
  Name: iTrack
  Address: d2:b1:90:70:38:6d
  RSSI: -73
  --> Service UUID not matched.

Found device:
  Name: iTrack
  Address: c5:dd:b0:ac:6b:51
  RSSI: -72
  --> Service UUID not matched.

Found device:
  Name: 
  Address: fc:40:b1:f8:b3:4e
  RSSI: -69
  --> Target service UUID matched.

Connecting to target device...
Connected to Peripheral.
Subscribed to notifications.

Notification received: PING 1626��h�lZ���
Raw bytes: 50 49 4E 47 20 31 36 32 36 A8 10 91 68 DF 6C 5A A5 F2 95 D9 
Notification received: PING 1627��h�lZ���
Raw bytes: 50 49 4E 47 20 31 36 32 37 A8 10 91 68 DF 6C 5A A5 F2 95 D9 

Notification received: PING 1628��h�lZ���
Raw bytes: 50 49 4E 47 20 31 36 32 38 A8 10 91 68 DF 6C 5A A5 F2 95 D9 

Notification received: PING 1629��h�lZ���
Raw bytes: 50 49 4E 47 20 31 36 32 39 A8 10 91 68 DF 6C 5A A5 F2 95 D9 

HTH :v:

The issue that Im saying is on SEEED WIO Terminal which use none of those MCUs you tested. Seeed Wio Terminal uses a RTL MCU as WiFi/BLE and I can not detect/discover UUID 128-bit with that when SEEED is a ble scanner (not advertiser). So please test the Seeed Wio terminal for scan mode and see if it can recognize an advertizer 128-bit UUID service to send/receive data trough it.

Thank you
Hossein

Hi there,

I know that, I’m working up to it… Just relax. We need a base line of operation. If it’s possible it will be.
your NOT the only one interested in the 128 bit UUID AFAIK…so sit tight others will chime in as well.

Let me state it simply:

:mag: Problem:

The BLE scanner on the Wio Terminal (via the RTL8720DN chip) often doesn’t fully support discovering custom 128-bit UUIDs from advertising packets or during service discovery. It may only report 16-bit standard services, even if the peripheral is advertising with 128-bit ones.


:brain: Why?

The issue is likely caused by:

  1. SDK limitations of the Realtek Ameba D SDK used on the RTL8720DN.
  2. API gaps in Seeed’s rpcBLEDevice library — it doesn’t fully parse 128-bit UUIDs or handle service/characteristic discovery beyond 16-bit properly.
  3. Advertising packet parsing may not expose all the raw fields, like 0x07 or 0x06 for complete list of 128-bit UUIDs.

What You Can Try:

1. Check Raw Advertising Data

If you can, print the raw advertising packet and manually parse the 128-bit UUID field (0x07 or 0x06). Example:

bleAdvertisedDevice.getManufacturerData();
bleAdvertisedDevice.getPayload();  // or similar

Then parse it for 128-bit UUID blocks.


2. Modify Peripheral to Include UUID in Scan Response

Some devices will only advertise 128-bit UUIDs in the scan response, not in the advertising packet. So make sure the peripheral is setting it like this:

BLEAdvertisingData scanResponseData;
scanResponseData.setCompleteServices128Bit(uuid);
pAdvertising->setScanResponseData(scanResponseData);

This gives the scanner a better shot at discovering them—especially with Realtek BLE stacks that don’t merge advertising + scan response automatically.


3. Use a Better BLE Central

If your goal is to confirm BLE discovery, test with:

  • nRF Connect (Android/iOS/Desktop) for reference
  • Or temporarily use ESP32-C3 or C6 as central, which supports 128-bit UUID scanning well (I already did this above!)

:warning: TL;DR

The RTL8720DN BLE Central stack in the Wio Terminal is not robust for 128-bit UUID scanning. You might get raw data but not full UUID discovery. This is a chip/SDK limitation, not just a Seeed code issue.

once there’s a good handle on the issue? (who’s it is) and a Fix I can verify it.
GL :slight_smile: PJ :v:

I’m working on it so we will see what shakes out. :+1:

Here is what you get when you scan for 128 Bit UUID:
serial output of Wio terminal.

// REV 6.4 - BLE Scanner (Wio Terminal w/ rpcBLE)
------------------------
Found: Name: 
  Address: bf:df:76:a9:2f:7f
  RSSI: -84
------------------------
Found: Name: 
  Address: 6a:c7:a1:f4:16:50
  RSSI: -84
------------------------
Found: Name: iTrack
  Address: 51:6b:ac:b0:dd:c5
  RSSI: -72
  Service UUID: <NULL>
------------------------
Found: Name: 
  Address: 32:74:7c:9a:b8:40
  RSSI: -96
------------------------
Found: Name: nRF52840-Pe
  Address: 4e:b3:f8:b1:40:fc
  RSSI: -66
  Service UUID: <NULL>
------------------------
Found: Name: 

the last entry in the list is the 128 UUID Periph from above. You can clearly see the " < NULL > " ski!
In some cases, the rpcBLE library may not fully support scanning for 128-bit UUIDs directly. A potential workaround is to perform a general scan to discover all nearby devices, then connect to the desired peripheral by matching its MAC address or other identifiable information. Once connected, you can discover the services and characteristics, including those with 128-bit UUIDs, and set up notifications as needed.​

Here’s a general outline of how you might implement this approach:

  1. Scan for Devices: Perform a general scan to discover all nearby BLE devices.​
  2. Identify Target Device: Filter the discovered devices to find the one you want to connect to, perhaps by matching its MAC address or advertised name.​
  3. Connect to the Device: Establish a connection with the identified peripheral.​
  4. Discover Services and Characteristics: Once connected, discover the services and characteristics offered by the peripheral, including those with 128-bit UUIDs
  5. Set Up Notifications: Subscribe to notifications for the characteristics you’re interested in.​

Please note that the rpcBLE library’s limitations may affect the implementation of this approach.
:crossed_fingers:

I’m working on a work around. :+1: