Android Question BLE2 activate DataAvailable routine

Marco Maria Vilucchi

Active Member
Licensed 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
 

Marco Maria Vilucchi

Active Member
Licensed User
follow part of code.

on STARTER module
B4X:
Private Sub Manager_Connected (Services As List)
    Log("Connected")
    For Each S As String In Services
        Log("Service: " & S)
    Next

    For i=0 To Services.Size-1
        manager.ReadData(Services.Get(i))
    Next
    Log("Proprietà caratteristica 301 "&manager.GetCharacteristicProperties(ServiceId, C301_risposta))

'    manager.SetNotify(ServiceId, ReadChar, True)
'    manager.SetNotify(ServiceId, C301_risposta, True)             THIS LINE IS COMMENTED

    connected = True
    CallSub2(Main, "SetState", connected)
    messagesToSend.Clear
End Sub

Private Sub Manager_DataAvailable (SId As String, Characteristics As Map)
    Log ("Manager_DataAvailable")

    Log(SId)
    For i = 0 To Characteristics.Size - 1
        Log("Key: " & Characteristics.GetKeyAt(i))
        Log("Val: " & Characteristics.GetValueAt(i))
        Dim BC As ByteConverter
        Log("Str: " & BC.StringFromBytes(Characteristics.GetValueAt(i),"utf-8"))
        
        Log("Main.tipomessaggiobluetooth " & Main.tipomessaggiobluetooth)
        Log("Characteristics.GetKeyAt(i) " & Characteristics.GetKeyAt(i))
        If Main.tipomessaggiobluetooth="E" Then
            If Characteristics.GetKeyAt(i)=C303_posizionebilancia Then
                Dim BC As ByteConverter
                MessaggioBluetooth= BC.StringFromBytes(Characteristics.GetValueAt(i),"utf-8")
                LogColor("Main.tipomessaggiobluetooth " & Main.tipomessaggiobluetooth &" Characteristics.GetKeyAt(i) " & Characteristics.GetKeyAt(i) & " MessaggioBluetooth " & MessaggioBluetooth,Colors.blue)
            End If
        End If   
    Next
    Log(" ")
    
'    Dim b() As Byte = Characteristics.Get(C301_risposta)
'    CallSub2(Main, "NewMessage", b)
'    NewMessage(b)
End Sub

Public Sub SendCommand(msg() As Byte)
   LogColor("Dentro SendCommand",Colors.red)
   messagesToSend.Add(TrimMessage(msg))
   If messagesToSend.Size = 1 Then
       Do While messagesToSend.Size > 0
           Try
               manager.WriteData(ServiceId, C300_comando, messagesToSend.Get(0))
           Catch
               FailedToSend
               Return
           End Try
           Wait For Manager_WriteComplete (Characteristic As String, Status As Int)
           If Status <> 0 Then
               FailedToSend
           End If
           If connected = False Or messagesToSend.Size = 0 Then Return
           messagesToSend.RemoveAt(0)
       Loop
   End If
End Sub
on another module:
B4X:
        Main.tipomessaggiobluetooth="E"
        Main.chichiededellapedana="MisurazioniAltezza"
        Log("misaltezza Main.tipomessaggiobluetooth " & Main.tipomessaggiobluetooth)
'        Dim s As String = "B4A: " & Main.tipomessaggiobluetooth
        Dim s As String = "E"
        CallSub2(Starter, "SendCommand", s.GetBytes("utf8"))
In this way I see on RealTerm that I wrote "E", but I haven't response and DataAvailable doesn't start.

upload_2019-7-2_10-30-57.png


If I uncomment manager.SetNotify(ServiceId, C301_risposta, True)
I have the previous 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)
How can I do to have a response from chip?
Thanks all
Marco
 

emexes

Expert
Licensed User
I feel like this burst of read requests could be too much for the BLE device:
B4X:
For i=0 To Services.Size-1
    manager.ReadData(Services.Get(i))
Next
It is possible that only the first few or last few requests are answered.

Next, I'd add a Log here to confirm that the SetNotify parameters are what you think they are, eg:
B4X:
Log("SetNotify [" & ServiceId & "] [" & C301_riposta & "]")
manager.SetNotify(ServiceId, C301_risposta, True)
and compare them to what you saw in Nrf Connect, including the upper/lowercaseness.
 

emexes

Expert
Licensed User
I've found with BLE that step one is to write the simplest possible app that reads some data.

There is an awful lot that needs to go right, and it only takes one wrong thing for it not to work.

Do you have such an app?

If not, I can send you my first pressure-reading app.
 

emexes

Expert
Licensed User
Eg, on this BLE sensor here, I can READ and NOTIFY (stream of readings) the temperature, but I cannot write to it. And I can READ and WRITE the measurement interval, but there is no notify facility for it, because the only time it would change is if I wrote to it.

upload_2019-7-2_19-50-9.png
 

Marco Maria Vilucchi

Active Member
Licensed User
I use readdata to read services

B4X:
    For i=0 To Services.Size-1
        manager.ReadData(Services.Get(i))
    Next
but how can I read data from characteristics?
I see that only DataAvailable has Characteristics as parameter, but how cha I start DataAvaialble routine?

Please can you give me your base code?
 

emexes

Expert
Licensed User
I use readdata to read services
B4X:
For i=0 To Services.Size-1
    manager.ReadData(Services.Get(i))
Next
I think that the above code is issuing too many ReadData requests all at once, and it overwhelms the BLE device. At least, that is what would happen with my BLE pressure sensor - it runs off a battery and is very slow.

but how can I read data from characteristics?
I see that only DataAvailable has Characteristics as parameter, but how cha I start DataAvaialble routine?
When you send a BLE ReadData request, the BLE device should return some data and that will call (start) the DataAvailable routine, with the received data.
 

emexes

Expert
Licensed User
The following are the only changes made after I tested it with my BLE device here, to (hopefully) make it work with your device:
B4X:
'''If Id.EndsWith("9D:0A") Then  
If Id.EndsWith("B9:AA") Then

'''If S.StartsWith("cc4a6a80") Then
If S.StartsWith("0000a002") Then
      
'''If C.StartsWith("835ab4c0") Then
If C.StartsWith("0000c301") Then
 
Top