DFRobot Bluno Boards

DFRobot Bluno boards (Arduino-compatible with built-in BLE) have a firmware bug that prevents Windows from receiving characteristic change notifications. The Bluetooth Framework provides the ForceNotifications property to bypass the missing client configuration descriptor, enabling full communication with Bluno boards on Windows.

The DFRobot Bluno Boards are a series of Arduino-compatible development boards (e.g., Bluno Uno, Bluno Nano) developed by DFRobot that integrate a Bluetooth 4.0 (BLE or Bluetooth Low Energy) module (specifically, a TI CC2540 chip). This integration allows developers to add wireless communication, smartphone control (via associated apps for iOS and Android), and even wireless programming capabilities to their Arduino projects with ease. The boards are fully compatible with Arduino Nano, Arduino UNO, Arduino Mega 1280, and Arduino Mega 2560.

The boards can easily be used with Android and iOS applications because DFRobot provides a mobile SDK for those platforms. However, the boards cannot be used with Windows applications that use the standard Microsoft Bluetooth LE API. You can connect to the board, read and write attributes, but you cannot receive any characteristic change notifications. The problem is that the board's firmware has a critical bug: its notifiable characteristic does not have a client configuration descriptor. But the Windows WinRT GATT API requires that!

With the Bluetooth Framework, you can solve this problem and use the boards without any issues, and your application will receive characteristic change notifications as it should.


How It Works

To test this feature, you can use the GattClient sample application from the Bluetooth Framework package. Start the sample application and click the Discover button. When BLE device discovery is completed, select the board in the found devices list. Now, set the Force indications checkbox. Click the Connect button. The board will be paired during connection. The sample application uses the default PIN, which is 0000. If your board uses a different PIN, change it in the OnPinRequest event handler in the sample application.

When the connection is established (you can track this in the log listbox at the bottom of the application - the Connected event's Error parameter will have a value of 0x00000000), you can start working with your board. After reading the services and characteristics, select the notifiable one and simply click the Subscribe button. Now the application will start receiving characteristic change notifications.

In your code

To work with the Bluno boards, use the wclGattClient class. The class has the ForceNotifications property, which must be set to true to enable receiving the characteristic change notifications from the Bluno boards (or from any other GATT-enabled device that does not have the client configuration descriptor). The board will be paired during connection establishing, so your application must handle the OnPinRequest event of the wclBluetoothManager class. The default PIN is 0000.

When the connection is established, your application can start receiving notifications by simply calling the Subscribe method of the wclGattClient class. Your application must not call the WriteClientConfiguration in this case because the boards do not have the Client Configuration Descriptor configured for the characteristic.


Code Example: Connecting and Subscribing

The snippets below are taken directly from the GattClient sample. They show the three essential steps: handling the PIN request, setting ForceNotifications based on the Force indications checkbox, and calling Subscribe after discovering characteristics.


procedure TfmMain.wclBluetoothManagerPinRequest(Sender: TObject;
	const Radio: TwclBluetoothRadio; const Address: Int64; out Pin: String);
begin
	Pin := '0000';
end;

procedure TfmMain.btConnectClick(Sender: TObject);
var
	Res: Integer;
	Item: TListItem;
begin
	Item := lvDevices.Selected;
	wclGattClient.ForceNotifications := cbForceIndications.Checked;
	Res := wclGattClient.Connect(TwclBluetoothRadio(Item.Data));
	// Check Res for errors...
end;

procedure TfmMain.btSubscribeClick(Sender: TObject);
var
	Characteristic: TwclGattCharacteristic;
begin
	// FCharacteristics is populated after reading characteristics
	Characteristic := FCharacteristics[lvCharacteristics.Selected.Index];
	wclGattClient.Subscribe(Characteristic);
end;
                        

void __fastcall TfmMain::wclBluetoothManagerPinRequest(TObject *Sender,
	const TwclBluetoothRadio *Radio, const __int64 Address, String& Pin)
{
	Pin = "0000";
}

void __fastcall TfmMain::btConnectClick(TObject *Sender)
{
	TListItem* Item = lvDevices->Selected;
	wclGattClient->ForceNotifications = cbForceIndications->Checked;
	int Res = wclGattClient->Connect((TwclBluetoothRadio*)Item->Data);
	// Check Res for errors...
}

void __fastcall TfmMain::btSubscribeClick(TObject *Sender)
{
	TwclGattCharacteristic Characteristic = FCharacteristics[lvCharacteristics->Selected->Index];
	wclGattClient->Subscribe(Characteristic);
}
                        

void Manager_OnPinRequest(Object Sender, wclBluetoothRadio Radio, Int64 Address, out String Pin)
{
	Pin = "0000";
}

private void btConnect_Click(Object sender, EventArgs e)
{
	ListViewItem Item = lvDevices.SelectedItems[0];
	Client.ForceNotifications = cbForceIndications.Checked;
	Int32 Res = Client.Connect((wclBluetoothRadio)Item.Tag);
	// Check Res for errors...
}

private void btSubscribe_Click(Object sender, EventArgs e)
{
	wclGattCharacteristic Characteristic = FCharacteristics[lvCharacteristics.SelectedItems[0].Index];
	Client.Subscribe(Characteristic);
}
                        

Private Sub Manager_OnPinRequest(ByVal Sender As Object, ByVal Radio As wclBluetooth.wclBluetoothRadio,
	ByVal Address As Long, ByRef Pin As String) Handles Manager.OnPinRequest
	Pin = "0000"
End Sub

Private Sub btConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btConnect.Click
	Dim Item As ListViewItem = lvDevices.SelectedItems(0)
	Client.ForceNotifications = cbForceIndications.Checked
	Dim Res As Int32 = Client.Connect(CType(Item.Tag, wclBluetoothRadio))
	' Check Res for errors...
End Sub

Private Sub btSubscribe_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btSubscribe.Click
	Dim Characteristic As wclGattCharacteristic = FCharacteristics(lvCharacteristics.SelectedItems(0).Index)
	Client.Subscribe(Characteristic)
End Sub
                        

void CGattClientDlg::wclBluetoothManagerPinRequest(void* Sender,
	CwclBluetoothRadio* const Radio, const __int64 Address, tstring& Pin)
{
	Pin = _T("0000");
}

// Connect button click
void CGattClientDlg::OnBnClickedButtonConnect()
{
	int Item = lvDevices.GetNextSelectedItem(Pos);
	wclGattClient.ForceNotifications = (cbForceIndications.GetCheck() != FALSE);
	int Res = wclGattClient.Connect((CwclBluetoothRadio*)lvDevices.GetItemData(Item));
	// Check Res for errors...
}

void CGattClientDlg::OnBnClickedButtonSubscribe()
{
	wclGattCharacteristics::iterator it = FCharacteristics.begin();
	std::advance(it, lvCharacteristics.GetNextSelectedItem(Pos));
	wclGattCharacteristic Characteristic = (*it);
	wclGattClient.Subscribe(Characteristic);
}
                        


For more details, please refer to the GattClient sample application source code.


Frequently Asked Questions

Why can't I receive notifications from DFRobot Bluno boards on Windows?
The boards lack a client configuration descriptor on their notifiable characteristic, which is required by the Windows WinRT GATT API. The Bluetooth Framework bypasses this bug.
How to enable notifications on Bluno boards with Bluetooth Framework?
Set the wclGattClient.ForceNotifications property to true before subscribing. The framework then handles the missing descriptor and lets your application receive characteristic change notifications.
What is the default PIN for pairing with Bluno boards?
The default PIN is '0000'. You must handle the OnPinRequest event of wclBluetoothManager and provide this PIN during pairing.