I am using the code below to read a paired bluetooth-serial converter.
It works very well in my test application, where I have ONE BUTTON for each command.
When I try to integrate on my application I have a big problem.
I need to send a request to the device, the request is received. And the device responds.
However the New_Data event does not happen until I get out of the SUB where I made the request.
I know I should be going event based, however this case the user is doing an action that needed that and everything depends on this. The program must wait for the answer.
In fact, the answer comes extremely quick, however the event is only fired AFTER I get out of the SUB.
I have used DOEVENTS, making a loop trying to wait for that, but that does not work.
I really dont know how to be in a loop waiting for the request arrive in the New_Data. It is milliseconds.
This is the code that I use to read the bluetooth
and this is the part where I call it. You see there is a loop to retry the reading, and that I have the same thing reading from USB and working. Now I made the same thing to read from BT.
The idea is always the same, I send a request and get back a value. I see that working on the log. But the NEW_DATA event only happens after I get out of this SUB. After 5 times the sub get out and then I see the Log message of the NEW_DATA.
The class yBTManager is declared in a Class_Globals.
Please, I ask for help, I have a delivery date that is way too close now...
EDIT:
I see this is a recurring issue on the questions. I read the tutorials and I besides the "it runs on the main thread" nothing else I could found. In fact I see that somehow there is a kind of message loop at the main thread level. I was hoping that DoEvents would force it. The problem is that i created the application around the USB-Serial library that reads blocking and now I have an Async reading that I am trying to make Blocking.
So I need a trick to solve that, since DoEvents doesnt.
It works very well in my test application, where I have ONE BUTTON for each command.
When I try to integrate on my application I have a big problem.
I need to send a request to the device, the request is received. And the device responds.
However the New_Data event does not happen until I get out of the SUB where I made the request.
I know I should be going event based, however this case the user is doing an action that needed that and everything depends on this. The program must wait for the answer.
In fact, the answer comes extremely quick, however the event is only fired AFTER I get out of the SUB.
I have used DOEVENTS, making a loop trying to wait for that, but that does not work.
I really dont know how to be in a loop waiting for the request arrive in the New_Data. It is milliseconds.
This is the code that I use to read the bluetooth
B4X:
'Class module
Sub Class_Globals
Dim BTMac As String
Dim Connected As Boolean
Private OSerial As Serial
Private OStream As AsyncStreams
Private RXData As String
End Sub
'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
OSerial.Initialize("OnSerial")
Connected = False
End Sub
' show available BT devices for choose and return the MAC of the selected
Public Sub SelectionDialog As String
Dim PairedDevices As Map
PairedDevices = OSerial.GetPairedDevices
Dim l As List
l.Initialize
For i = 0 To PairedDevices.Size - 1
l.Add(PairedDevices.GetKeyAt(i))
Next
Dim res As Int
res = InputList(l, "Selecione Bluetooth", -1) 'show list with paired devices
If res <> DialogResponse.CANCEL Then
BTMac = PairedDevices.Get(l.Get(res))
Return BTMac
Else
Return ""
End If
End Sub
Public Sub Connect
If BTMac = "" Then
ToastMessageShow("Informe Bluetooth as Ser conectado", False)
Else
If Not(Connected) Then
OSerial.Connect(BTMac) 'convert the name to mac address and connect
End If
End If
End Sub
Public Sub Disconnect
OStream.Close
OnStream_Terminated
End Sub
Private Sub OnSerial_Connected (Success As Boolean)
OSerial.Listen
Connected = Success
If Success Then
OStream.Initialize(OSerial.InputStream, OSerial.OutputStream, "OnStream")
ToastMessageShow("Bluetooth Conectado", False)
End If
End Sub
Private Sub OnStream_Error
Log("###Bluetooth "&LastException)
OStream.Close
OnStream_Terminated
End Sub
Private Sub OnStream_Terminated
Log("###Bluetooth stream terminada")
Connected = False
OSerial.Disconnect
End Sub
Private Sub OnStream_NewData(Buffer() As Byte)
Dim s As String
s = OnlyNumbers(BytesToString(Buffer, 0, Buffer.Length, "UTF-8"))
If s <> "" Then
RXData = s
End If
Log("###Bluetooth recebido dados "&s)
End Sub
Sub RequestPeso
Log("###Bluetooth request peso ")
If OStream.IsInitialized Then
Dim msg = Chr(5)
OStream.Write(msg.GetBytes("UTF-8"))
' RXData = ""
End If
End Sub
Public Sub SendPrice(Price As String)
Dim s As String
Dim v As BigDecimal
v.Initialize(Price)
v.MovePointRight(2)
s = Chr(2)&FillZeroes(OnlyNumbers(v.ToPlainString)&Chr(3), 6)
OStream.Write(s.GetBytes("UTF-8"))
End Sub
Public Sub Read As String
Dim s As String = RXData
RXData = ""
Log("### lido dados: "&s)
Return(s)
End Sub
'Remove anything that is not in the range 0 -> 9
Private Sub OnlyNumbers(Value As String) As String
Dim s As String
s = ""
For i = 0 To Value.Length - 1
If (Asc(Value.CharAt(i)) >= Asc("0")) AND (Asc(Value.CharAt(i)) <= Asc("9")) Then
s = s & Value.CharAt(i)
End If
Next
Return s
End Sub
'Fill Zeroes to the Left according the number of digits
Private Sub FillZeroes(Value As String, Digits As Int) As String
Dim s As String
s = Value
If Value.Length < Digits Then
For i = 0 To Digits - Value.Length - 1
s = "0" & s
Next
End If
Return s
End Sub
and this is the part where I call it. You see there is a loop to retry the reading, and that I have the same thing reading from USB and working. Now I made the same thing to read from BT.
B4X:
Dim I As Int
Dim s As String
Dim erro As Boolean
I = 5
Do While I > 0
If FAppManager.GetConfig.GetBoolean("balancabt") Then
FAppManagerAct.BTMan.RequestPeso
Else
FAppManagerAct.UsbMan.RequestPeso
End If
DoEvents
DoEvents
DoEvents
DoEvents
DoEvents
DoEvents
DoEvents
erro = False
If FAppManager.GetConfig.GetBoolean("balancabt") Then
s = FAppManagerAct.BTMan.Read
Else
s = FAppManagerAct.UsbMan.Read
End If
If s.Length < 5 Then
I = I - 1
erro = True
Else
FMultiplicador.Initialize(s) 'coloca o peso como multiplicador
div.Initialize3(1000)
FMultiplicador.Divide(div)
I = 0
erro = False
End If
Loop
If erro Then
ToastMessageShow("Problema na leitura balanca", True)
Return -1
End If
The idea is always the same, I send a request and get back a value. I see that working on the log. But the NEW_DATA event only happens after I get out of this SUB. After 5 times the sub get out and then I see the Log message of the NEW_DATA.
The class yBTManager is declared in a Class_Globals.
Please, I ask for help, I have a delivery date that is way too close now...
EDIT:
I see this is a recurring issue on the questions. I read the tutorials and I besides the "it runs on the main thread" nothing else I could found. In fact I see that somehow there is a kind of message loop at the main thread level. I was hoping that DoEvents would force it. The problem is that i created the application around the USB-Serial library that reads blocking and now I have an Async reading that I am trying to make Blocking.
So I need a trick to solve that, since DoEvents doesnt.
Last edited: