B4A Library Customise your BLE GATT Service with BLE Peripheral 2 Enhanced

Hello All,
First I want to say thank you to the B4X developers that reached out to me via PM and to others that I spoke to, you all know who you are 👍

As you are all well aware I personally do not touch Java, I only started learning java so that I could enhance Erel's current BlePeripheral2 library which was just too limited for a clients project. I can't believe that I'm saying this, but I have actually enjoyed learning some Java and I will continue to do so 😯

About BlePeripheral2Enhanced library.
Using this library, you can create your own custom BLE GATT Service or emulate manufacturer hardware if you know the service UUID and characteristics UUIDs.

I've added the following features to the original BlePeripheral2 V1.12 library which I've renamed to BlePeripheral2Enhanced V1.5.
  • Create a custom primary service with your own unique UUID
  • Create multiple characteristics with your own unique UUIDs under the primary service UUID
  • Characteristics can be set to either Read and Write, just Read or just Write
  • Set the default value for Read or Read Only characteristics
  • Set notifications on a per characteristic basis
  • Return the sending central characteristic UUID
  • Return the received data as String, Hexadecimal or Binary
I have not removed or changed any of Erel's original code for creating a service with characteristics. If you switch to using this library, UUIDs 0001, 1001, 1002 and descriptor 2902 will still work as they did previously with no changes necessary. If need be you can create your own custom service with custom characteristics by calling CreatePrimaryServiceUUID and CreateCharacteristicUUIDs after you have Initialized the BlePeripheral2Enhanced library. Optionally, you can use SetCharacteristicReadValues to establish default values for Read or Read-Only characteristics.

BLE2PeripheralEnhanced

Author:
Version:
1.53
  • BlePeripheral2Enhanced
    Allows to configure the device as a BLE peripheral device. Other central devices can connect to this device.
    Only supported by some devices running Android 5+. Make sure to check IsPeripheralSupported property.
    • Events:
      • ConnectionStatus (DeviceId As String, ConnectionState As String)
      • NewData (DeviceId As String, Data() As Byte)
      • NewData2 (DeviceId As String, Data() As Byte, CharacteristicUUID As String, DataAsStr As String, DataAsHex As String, DataAsBin As String)
      • Start (Success As Boolean)
      • Subscribe (CentralId As String)
      • Unsubscribe (CentralId As String)
    • Fields:
      • CreateCharacteristicUUIDs As List
        Create a list of custom characteristic UUIDs with Read/Write permissions and Notify.
        Usage: CharacteristicUUID As String, Read As Boolean, Write As Boolean, Notify As Boolean.
        Example: CreateCharacteristicUUIDs("CharacteristicUUID,Read,Write,Notify", "CharacteristicUUID,Read,Write,Notify", ...)
      • CreatePrimaryServiceUUID As String
        Create the primary service UUID.
        The primary service UUID must be created before adding your custom characteristic UUIDs.
      • GetCharacteristicUUID As String
        Returns the characteristic UUID that sent the data.
      • GetDataAsBinary As String
        Returns the characteristic data that was sent.
        Converts the data from bytes to binary.
      • GetDataAsString As String
        Returns the characteristic data that was sent.
        Converts the data from bytes to string.
      • MultipleConnections As Boolean
        Enable or disable multiple central devices to connect simultaneously.
      • SetCharacteristicReadValues As List
        Set the default read value for characteristics via the characteristic UUIDs.
        Usage: CharacteristicUUID As String, ReadValue As String.
        Example: SetCharacteristicReadValues("CharacteristicUUID,ReadValue", "CharacteristicUUID,ReadValue", ...)
    • Functions:
      • Close
      • GetDataAsHexadecimal (CommaSeparated As Boolean) As String
        Returns the characteristic data that was sent.
        Converts the data from bytes to hexadecimal.
        CommaSeparated: True includes commas, False removes commas.
      • Initialize (EventName As String, Ble As BleManager2)
        Initializes the object.
      • Start (Name As String)
        Starts advertising. The name will be set as the device Bluetooth name. Pass an empty string to keep the current name.
        The Start event will be raised.
      • Start2 (Name As String, Settings As android.bluetooth.le.AdvertiseSettings)
        Similar to Start. Allows overriding the default settings.
      • Write (Centrals As List, Data As Byte())
        Writes data to subscribed devices.
        Centrals - Target devices. Pass Null to send to all subscribed devices.
    • Properties:
      • IsPeripheralSupported As Boolean [read only]
        Checks whether peripheral mode is supported.
      • ManufacturerData As Map
        Gets or sets the manufacturer specific data that will be advertised.
        Each item in the map should have a positive int number as the key and an array of bytes as the value.

BLE GATT primary service with multiple custom characteristics, created using only 2 lines of code in B4A.

Highlighted the B4A custom BLE GATT primary service.
Found.png


7 custom characteristics added to the BLE GATT primary service.
Highlighted the Read-Only characteristic value set using SetCharacteristicReadValues.

Defult_Value.png


B4A GATT Service scanned using BLE Scanner app.

Update: V1.50
  • Set targetSdkVersion to 33
  • Added RuntimePermissions to the main activity
  • Added permissions to the manifest
  • Moved the code from the starter service to the new MonitorBLEPeripheral service
Update: V1.51
  • Updated IsPeripheralSupported property
  • Updated peripheral example
Update: V1.52
  • Added field SetCharacteristicReadValues (See post #14 below)
  • Replaced Tilde(~) with Comma(,) as a separator (You will need to update CreateCharacteristicUUIDs) with commas
  • CreateCharacteristicUUIDs is now defined as a list and not as a string array
  • Updated peripheral example
Update: V1.53
  • Added event ConnectionStatus - This even fires whenever a remote central device connects or disconnects to the peripheral service (See post #18 below)
  • Added field MultipleConnections - Allows for limiting central device connections to only a single connection at any one time (See post #18 below)
  • Updated peripheral example
D = 13+13, 3+3, 20+20, 15+15, 5+5, 14+14, 33+26


Enjoy...
 

Attachments

  • BLE2PeripheralEnhancedLib.zip
    9.5 KB · Views: 54
  • BlePeripheralEnhanced.zip
    10 KB · Views: 48
Last edited:

Alessandro71

Well-Known Member
Licensed User
Longtime User
this is quite interesting, and something i was looking for some BLE device emulation.
but the provided example crashes because of missing BLUETOOTH_CONNECT permission
 

Peter Simpson

Expert
Licensed User
Longtime User
this is quite interesting, and something i was looking for some BLE device emulation.
but the provided example crashes because of missing BLUETOOTH_CONNECT permission
Thank you for reporting this to me. I was testing this on an older device and not the Pixel 6 Pro in the drawer. Once I tested it on the P6P I saw the permission issue.

I added the missing permission but strangely enough it didn't work, so I just quickly put the SDK back to the same SDK in Erel's example for now and it's working as expected. I've re-uploaded the example and library zip files, I will have a proper look in the morning as it is getting late now. Please try the newly uploaded files and also replace the library too as I've made a small change there too. Let me know how you get on with them.


Enjoy...
 

Alessandro71

Well-Known Member
Licensed User
Longtime User
I added the missing permission but strangely enough it didn't work, so I just quickly put the SDK back to the same SDK in Erel's example for now and it's working as expected. I've re-uploaded the example and library zip files, I will have a proper look in the morning as it is getting late now. Please try the newly uploaded files and also replace the library too as I've made a small change there too. Let me know how you get on with them.
It's working fine now, thank you for your prompt answer
 

GJREDITOR

Member
Thanks for the library. How do I send data to particular service? Eg: I want to send the light sensor data to : D3DE8C5C-6EE4-43D6-8A5B-61D45BFA16C2. This needs to be detected by 'Central' which has set notify for D3DE8C5C-6EE4-43D6-8A5B-61D45BFA16C2 service.
 

Star-Dust

Expert
Licensed User
Longtime User
I'm not too sure about that SD, and I can't believe that you actually read my profile even though it's there for all to see :cool:


Enjoy...
Instead I read the profile. 😜
 

Peter Simpson

Expert
Licensed User
Longtime User
Thanks for the library. How do I send data to particular service?
Have you seen this example from Erel?

You should study Erel's chat example above before using this library. Once you have learnt how the chat example works, use this library to create your custom services with characteristics.


Enjoy...
 

Peter Simpson

Expert
Licensed User
Longtime User
Updated the library to V1.52.

PLEASE NOTE:

I have replaced the Tilde(~) separator with a Comma(,). You will need to update CreateCharacteristicUUIDs in your code by replacing the Tildes(~) with Commas(,).

This update enables you to establish a default 'Read' value for any characteristic. This is particularly useful for instance when dealing with characteristics that are Read-Only and offer no write option. For example you can set a Read-Only account number value, Read-Only serial number value, Read-Only options list value, Read-Only settings value for central connected devices among other possibilities.

To set the default value of a Read or Read-Only characteristic, you have to use SetCharacteristicReadValues. SetCharacteristicReadValues is a list that can set multiple Read or Read-Only characteristic values at the same time. Use a comma(,) to separate the characteristic UUID from the value. Values can include commas as SetCharacteristicReadValues only splits at the first comma separating the UUID from the value itself.
SetCharacteristicReadValues example:
  'Set the read values for selected characteristics (Optional)
  Peripheral.SetCharacteristicReadValues = Array As String ("0B494FBF-6ACC-4DE2-86FE-390CFA74EE07,B4A Read Only Value")

The underlined string below represents a Read-Only characteristic, allowing it to be read by connected devices but not written to.
Read.png



Enjoy...
 
Last edited:

Peter Simpson

Expert
Licensed User
Longtime User
Great job! Could you implement this for iOS as well?
Thank you for you positive feedback but rarely do I develop on iOS, only for personal projects.
I only updated this library out of necessity. A hardware manufacturer needed me to emulate their nRF52 powered devices but on Android devices, the original BlePeripheral2 library was too limited for their project.
 
Last edited:

lutz ebner

Member
Licensed User
Okay, too bad. I need it for an nrf52832 module. However, not just for Android but also for iOS. Nevertheless, thank you very much for your great work!

By the way, I tested your library with the Nordic UART Service (NUS). It works wonderfully.
 

Peter Simpson

Expert
Licensed User
Longtime User
Updated the library to V1.53.

Added event
ConnectionStatus event:
_ConnectionStatus (DeviceId As String, ConnectionState As String)
This event fires whenever a remote central device connects or disconnects to or from the peripheral service.

Example result for ConnectionStatus:
Device 62:01:06:FF:64:2C is CONNECTED
Device 62:01:06:FF:64:2C is DISCONNECTED

Added field
MultipleConnections:
Peripheral.MultipleConnections = True or false
Allows for limiting central device connections to only a single connection at any one time.


Enjoy...
 
Last edited:
Top