Android Question BLE2 activate DataAvailable routine

Marco Maria Vilucchi

Active Member
Licensed User
Longtime User
Hi all,
after connecting to a chip via ble2, I'm trying to talk to him. In the first instance I printed all the characteristics of the service.
Then I wrote a command: "E".
Now I am trying to get an answer, but I have some difficulties.
To activate the DataAvailable routine I need to set:
B4X:
    manager.SetNotify(ServiceId, C301_risposta, True)
It's true?
previously I have defined the characterisctic:
B4X:
    C301_risposta= UUID("C301")
UUID is the Erel routine that construct UUID.
The characteristic exists.

But SetNotify has an error:
B4X:
starter_manager_connected (java line: 470)
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.bluetooth.BluetoothGattDescriptor.setValue(byte[])' on a null object reference
    at anywheresoftware.b4a.objects.BleManager2.setNotify(BleManager2.java:322)
    at anywheresoftware.b4a.objects.BleManager2.SetNotify(BleManager2.java:311)
    at com.mamavi.slimup.starter._manager_connected(starter.java:470)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:196)
    at anywheresoftware.b4a.BA$2.run(BA.java:370)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:7000)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)

So far I have always connected with the features of BleCentral (by Erel - ReadChar and WriteChar) and now I need support to use other characteristics.
Now I have near 25 characteristics on the chip and I need to know how manage read, write and DataAvailable.
Does anyone have any examples?
Does anyone know why I get this error?
I have B4A 9.01 and Ble2 1,38
Thanks all
Marcom
 

emexes

Expert
Licensed User
Mission Impossible is on tv here right now, and they're in Italy. Not sure if that is a sign of how things are going to go.
 
Upvote 0

emexes

Expert
Licensed User
When you press the Scan button, you should get a log like this. The pressure sensor here is returning a steady two byte reading of 0 2 (= 0.2 PSI) about twice a second.

Logger connected to: TCL 5009A
--------- beginning of main
*** Service (starter) Create ***
manager.Initialize
--------- beginning of system
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
ScanButton_Click
StartScan
manager.Scan2
64:C3:6B:6D:92:8C
3A:3C:A1:9F:4B:FB
C8:69:CD:10:1E:C9
F8:B4:86:32:9D:0A 34506
manager.StopScan
manager.Connect2 F8:B4:86:32:9D:0A
Discovering services.
00001800-0000-1000-8000-00805f9b34fb
00001801-0000-1000-8000-00805f9b34fb
cc4a6a80-51e0-11e3-b451-0002a5d5c51b
0000180f-0000-1000-8000-00805f9b34fb
00001804-0000-1000-8000-00805f9b34fb
0000180a-0000-1000-8000-00805f9b34fb
000018ff-0000-1000-8000-00805f9b34fb
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 391
Data (decimal bytes) = 0 2

8cd67da0-da9b-11e3-9087-0002a5d5c51b
00002a1c-0000-1000-8000-00805f9b34fb
00002a21-0000-1000-8000-00805f9b34fb
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 439
Data (decimal bytes) = 0 2

8cd67da0-da9b-11e3-9087-0002a5d5c51b
00002a1c-0000-1000-8000-00805f9b34fb
00002a21-0000-1000-8000-00805f9b34fb
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 400
Data (decimal bytes) = 0 2

8cd67da0-da9b-11e3-9087-0002a5d5c51b
00002a1c-0000-1000-8000-00805f9b34fb
00002a21-0000-1000-8000-00805f9b34fb
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 408
Data (decimal bytes) = 0 2

8cd67da0-da9b-11e3-9087-0002a5d5c51b
00002a1c-0000-1000-8000-00805f9b34fb
00002a21-0000-1000-8000-00805f9b34fb
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 382
Data (decimal bytes) = 0 2

8cd67da0-da9b-11e3-9087-0002a5d5c51b
00002a1c-0000-1000-8000-00805f9b34fb
00002a21-0000-1000-8000-00805f9b34fb
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 422
Data (decimal bytes) = 0 2

8cd67da0-da9b-11e3-9087-0002a5d5c51b
00002a1c-0000-1000-8000-00805f9b34fb
00002a21-0000-1000-8000-00805f9b34fb
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 391
Data (decimal bytes) = 0 2

8cd67da0-da9b-11e3-9087-0002a5d5c51b
00002a1c-0000-1000-8000-00805f9b34fb
00002a21-0000-1000-8000-00805f9b34fb
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 404
Data (decimal bytes) = 0 2

8cd67da0-da9b-11e3-9087-0002a5d5c51b
00002a1c-0000-1000-8000-00805f9b34fb
00002a21-0000-1000-8000-00805f9b34fb
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 483
Data (decimal bytes) = 0 2
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
What should happen is:

'you press the start button
ScanButton_Click

'the activity module button routine calls the Starter module StartScan routine
StartScan

'which starts a BLE scan
manager.Scan2

'which will start calling DeviceFound routine for each BLE advertisement packet received
64:C3:6B:6D:92:8C
3A:3C:A1:9F:4B:FB
C8:69:CD:10:1E:C9

'until finally we receive one that matches the If Id.EndsWith filter
F8:B4:86:32:9D:0A 34506

'and then we stop the BLE scan
manager.StopScan

'and Connect to the matched device
manager.Connect2 F8:B4:86:32:9D:0A

'this is a log from within the BLE2 library
Discovering services.

'when the connection is done, the Manager_Connected routine is called with a list of services
00001800-0000-1000-8000-00805f9b34fb
00001801-0000-1000-8000-00805f9b34fb
cc4a6a80-51e0-11e3-b451-0002a5d5c51b
0000180f-0000-1000-8000-00805f9b34fb
00001804-0000-1000-8000-00805f9b34fb
0000180a-0000-1000-8000-00805f9b34fb
000018ff-0000-1000-8000-00805f9b34fb

'and when we find a service that matches the .StartsWith filter
'we set BLE_State and LastReadTime so that


'the next 100ms ReadTimer_Tick will issue a ReadData for the service
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b

'when the data is received, Manager_DataAvailable is called with a list of received characteristics and data
'and when we find a characteristic that matches the .StartsWith filter, we log the time and data

835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 391
Data (decimal bytes) = 0 2

'then we set LastReadTime to "schedule" the next ReadData for the ReadTimer_Tick

'and ignore the other characteristics (probably could have aborted the loop here, because it's the only
'characteristic we're looking for, and will only appear once in the map)

8cd67da0-da9b-11e3-9087-0002a5d5c51b
00002a1c-0000-1000-8000-00805f9b34fb
00002a21-0000-1000-8000-00805f9b34fb

'the next 100ms ReadTimer_Tick will issue a ReadData for the service
manager.ReadData cc4a6a80-51e0-11e3-b451-0002a5d5c51b

'and we do it all again...
835ab4c0-51e4-11e3-a5bd-0002a5d5c51b
Data read time = 439
Data (decimal bytes) = 0 2
 
Last edited:
Upvote 0

Marco Maria Vilucchi

Active Member
Licensed User
Longtime User
I see that DataAvailable loop continuosly... it's correct?
Then I can test for C301 data or C302 or C303 data...
Ok

I'm using realterm to test connection and I would like to insert the chip responses using AT commands. For example the second characteristic is the C301 and with the command "AT + BLEGATTSSETATTR = 1,2,, 2" (service 1, characteristic 2, 2 chars expected) Realterm expects two characters for the 301 characteristic which then DataAvailable should read.
But with this loop the realterm screen scrolls continuously and I can't send the command.
Should I stop the loop? such as?
 
Upvote 0

emexes

Expert
Licensed User
Simplest solution right now whilst getting a feel for how the BLE2 library and ECP32 BLE work, might be to slow the timer down so that readings are only done at most every 5 seconds rather than every 100 ms.

Change
B4X:
ReadTimer.Initialize("ReadTimer", 100)    'check to do ReadData every 100 milliseconds
to
B4X:
ReadTimer.Initialize("ReadTimer", 5000)    'check to do ReadData every 5 seconds
 
Upvote 0

Marco Maria Vilucchi

Active Member
Licensed User
Longtime User
ok I'm studied the code.
Really I have near 25 characteristics to manage.
I send a command to the chip (C300) and when I receive "OK" from C301 I'm going to read the affected characteristic (C302 or C303 or C340....) to read the data.
The chip technician programmed it this way.
Then I need to activate ReadTimer_tick only when I send a command to the chip.
Is it correct as reasoning? How do I get ReadData started when I want it?
 
Upvote 0

emexes

Expert
Licensed User
Once you have the system communicating one piece of data reliably, then you could extend it to do multiple pieces of data by:

1/ create an array of Services to be read

2/ in the ReadTimer_Tick, cycle through that array one step each time it issues a ReadData request

something like:
B4X:
global variables:
    Dim NumServices As Int = 3
    Dim ServiceUUID(NumServices) As String
    Dim NextServiceToRead = 0

service start:
    ServiceUUID(0) = "00001800-0000-1000-8000-00805f9b34fb"
    ServiceUUID(1) = "00001804-0000-1000-8000-00805f9b34fb"
    ServiceUUID(2) = "00001807-0000-1000-8000-00805f9b34fb"    

Sub ReadTimer_Tick

    If BLEState = BLE_STATE_READING Then
        If DateTime.Now - LastReadTime > 10000 Then
            BLEService = ServiceUUID(NextServiceToRead)
            NextServiceToRead = (NextServiceToRead Mod NumServices)    'next time around, read the next service of the array

            manager.ReadData(BLEService)    'initiate read
            Log("manager.ReadData " & BLEService)
           
            LastReadTime = DateTime.Now    'times out in 10 seconds to continue reads even if no data received
        End If
    End If
   
End Sub
 
Upvote 0

emexes

Expert
Licensed User
Perhaps i can put BLEState = BLE_STATE_IDLE as normal state and BLEState = BLE_STATE_READING when I want read?
You can do that. Better yet, perhaps add another state in-between BLE_STATE_CONNECTING and BLE_STATE_READING. Call it BLE_STATE_CONNECTED, ie, you are connected to the BLE device but not yet reading it.

When you want to start reading it, you'd set BLEState to BLE_STATE_READING* and then it will be picked up by the next ReadTimer_Tick.

* and ideally, LastReadTime to 0, to make sure we don't get caught up in that 10-second retry-if-no-data-received timeout
 
Upvote 0

emexes

Expert
Licensed User
I send a command to the chip (C300) and when I receive "OK" from C301
I am visualising your system as the SCP32 having a wired serial connection on one side that is connected to your hardware that is sending AT commands to it, and a wireless BLE connection on the other side that is "connected" to your Android B4A app.

Is this correct?

And the above two (2) communications - are they over the wired (RealTerm?) connection, or over the BLE connection?
 
Upvote 0

Marco Maria Vilucchi

Active Member
Licensed User
Longtime User
Yes it is an SCP32... I love you (no it's too much)!!!

And the above two (2) communications - are they over the wired (RealTerm?) connection, or over the BLE connection?

I don't understand this question. I connect chip via AT command on realterm and use ble to connect with app

I tried with BLE_STATE_IDLE and it seems to work, but if I read a second time C301 I find again the same characters. How can I delete them?
 
Upvote 0

emexes

Expert
Licensed User
I send a command to the chip (C300) and when I receive "OK" from C301 I'm going to read the affected characteristic (C302 or C303 or C340....) to read the data.
Is the above happening over the RealTerm-wired-serial connection, or the BLE-Android connection? Or perhaps both. I should split the question up.

"send a command to the chip (C300)" - is this from RealTerm to SCP32?

"receive OK from C301" - is this from SCP32 to RealTerm, in response to command?

"read the affected characteristic" - is this the B4A app reading from the SCP32 via BLE?

How does the B4A app know which is the affected characteristic?
 
Upvote 0

emexes

Expert
Licensed User
if I read a second time C301 I find again the same characters. How can I delete them?
You probably can't delete them.

GATT works like a football scoreboard. On one side of the scoreboard, the scorekeeper's updating the information. On the other side of the scoreboard, people are reading the latest information, but that doesn't delete the information from the scoreboard. If a spectator goes away and comes back a few minutes later, the information is still on the scoreboard: maybe it has changed and been updated by the scorekeeper, or maybe it has not changed and is still the same score that it was last time the spectator read it.
 
Upvote 0

emexes

Expert
Licensed User
What is the equipment connected to the SCP32 that you will be getting readings from? BLE is good for getting right-now current readings of stuff. It is not so good for reliably transferring large quantities of data - for that, you might be better with a standard Bluetooth Classic SPP serial connection... except that Apple has restricted this to large manufacturers, and that is why many of the Bluetooth relay boards for sale on Ebay specify "Android only".
 
Upvote 0

Marco Maria Vilucchi

Active Member
Licensed User
Longtime User
the system is a card connected to various sensors that will give me information such as height, weight, etc ...

App sends a command to the chip (C300) and when App receive "OK" from C301 App is going to read the affected characteristic (C302 or C303 or C340....) to read the data.
To test the connection I simule the sensors writing height or weight on realterm. (I think to do this, but I still haven't arrived to do it).
Now I'm working to bring you code on my app.
Thank you very much for your help.
 
Upvote 0

emexes

Expert
Licensed User
I would do that as:

Set up a characteristic for each measurement, eg:
C301 = left-foot weight
C302 = right-foot weight
C302 = height
C303 = temperature
C304 = resistance left-palm to right-palm
...
C330 = pedal speed?

I don't know if there is a limit of how many characteristics can be on one service - if there is a limit, split them up across two or three services.

So what you then have with BLE GATT is a scoreboard with 30 numbers on it, perhaps grouped into two or three sections.

You can then read those numbers by:
- issuing a ReadData for a section (ie service)
- BLE2 library will read all the numbers of that section/service and return them to you by a DataAvailable call
- that DataAvailable call gives you a Map of all the numbers for that section (ie characteristics and their values)

If you hit a limit with having too many numbers, then you could always put multiple numbers into one characteristic, eg:
each characteristic can have up to 20 bytes of data, so you could fit up to eg five 32-bit ints into one characteristic.
 
Upvote 0
Top