Bluetooth AStreams Problem?

Status
Not open for further replies.

stephankuba

Member
Licensed User
Longtime User
Hi,

i want to receive a string every second form a bluetooth device.
The string looks like this:

#231;30895;21440;1837;1685;49;252;1;28;28;28;28;126;3242*

I use this to initialize Astrem
B4X:
Sub Serial1_Connected (Success As Boolean)
   If Success Then
      ToastMessageShow("Connected successfully", False)
      ListView1.AddSingleLine("verbunden")
      'StartActivity(bluetooth)
      
         If AStream.IsInitialized = False Then
            AStream.Initialize(serial1.InputStream, serial1.OutputStream, "AStreams")
            
         End If
      
   Else
      
      Msgbox(LastException.Message, "Error connecting.")
   End If
End Sub

AStreams Buffer
B4X:
Sub AStreams_NewData (Buffer() As Byte)  
   
   LogMessage("", BytesToString(Buffer, 0, Buffer.Length, "ASCII"))
   
End Sub

B4X:
Sub LogMessage(From As String, Msg As String)
   'txtLog.Text = txtLog.Text & From & ": " & Msg & CRLF
   'txtLog.SelectionStart = txtLog.Text.Length
      
   txtLog.Text = txtLog.Text & Msg & CRLF
   txtLog.SelectionStart = txtLog.Text.Length
      
   
   received_data = Msg
      
End Sub

i want to use the variable "received_data" to store the received string.
and than i want to split the received string #231;30895;21440;1837;1685;49;252;1;28;28;28;28;126;3242*

in variable1 = 231, varialble2 = 30895 and so on....


But the problem is:

i receive the string splitted. First i receive # then 231;30895;21440; and then 1837;1685;49;252;1;28;28;28;28;126;3242*.


i don't now why it is splitted.

so I have to put the strings together but how?
or is it possible to receive the string complete?

Maybe someone has an idea??????
thanks
 

agraham

Expert
Licensed User
Longtime User
This is expected behaviour on many sorts of network. Because the data is sent in packets it can be received in separate parts. You will either need to reassemble the string yourself, or if you have control over what is being sent you could use AsyncStreams in prefix mode where it will reassemble the string for you. See the "Prefix mode" section at the end of the AsyncStreams tutorial.
http://www.b4x.com/forum/basic4andr...als/7669-asyncstreams-tutorial.html#post43578

As you seem to have "#" at the start and "*" at the end of the string it should be easy to reassemble yourself using IndexOf and SubString.
 
Upvote 0

stephankuba

Member
Licensed User
Longtime User
AStreams Problem

Thank you for the fast answer.

I tried prefixmode, but if the connection is established and the first data received the app exits. I just get the message "App closed" i don't know why?


I tried this:
same code above only this different:

B4X:
If AStream.IsInitialized = False Then
     AStream.InitializePrefix(serial1.InputStream, True, serial1.OutputStream, "AStreams")   
End If

here is the complete code:
B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim serial1 As Serial
   Dim admin As BluetoothAdmin
   Dim AStream As AsyncStreams

End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.

   Dim TabHost1 As TabHost
   Dim ListView1 As ListView
   Dim PairedDevices As Map
   Dim txtLog As EditText
   Dim txtInput As EditText
   Dim btnSend As Button
   
   Dim received_data As String 
   
   Dim ListView2 As ListView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:
   
   If FirstTime Then
      serial1.Initialize("Serial1")
      admin.Initialize("admin")
   End If

   

   If admin.IsEnabled = False Then
      If admin.Enable = False Then 
         ToastMessageShow("Error enabling Bluetooth adapter.", True)
      Else
         ToastMessageShow("Enabling Bluetooth adapter...", False)
         'the StateChanged event will be soon raised
      End If
   Else
      Admin_StateChanged(admin.STATE_ON, 0)
   End If
   If serial1.IsEnabled = False Then
      Msgbox("Please enable Bluetooth.", "")
   Else
      serial1.Listen 'listen for incoming connections
   End If
   
   Activity.AddMenuItem("Beenden","exit")

   Activity.LoadLayout("main")

   TabHost1.AddTab("Init","tab1")
   TabHost1.AddTab("Wert","tab2")
   
   
   
   PairedDevices = serial1.GetPairedDevices
   Dim l As List
   l.Initialize
   For i = 0 To PairedDevices.Size - 1
      l.Add(PairedDevices.GetKeyAt(i))
      ListView1.AddSingleLine(PairedDevices.GetKeyAt(i))
      ListView1.AddSingleLine(PairedDevices.GetValueAt(i))
      
   Next
   

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub



Sub ListView1_ItemClick (Position As Int, Value As Object)
   serial1.Connect(Value)
End Sub
Sub Admin_StateChanged (NewState As Int, OldState As Int)
   NewState = admin.STATE_ON
   
End Sub

Sub Serial1_Connected (Success As Boolean)
   If Success Then
      ToastMessageShow("Connected successfully", False)
      ListView1.AddSingleLine("verbunden")
      'StartActivity(bluetooth)
      
         If AStream.IsInitialized = False Then
            AStream.Initialize(serial1.InputStream, serial1.OutputStream, "AStreams")
            'AStream.InitializePrefix(serial1.InputStream, True, serial1.OutputStream, "AStreams")   
         End If
      
   Else
      
      Msgbox(LastException.Message, "Error connecting.")
   End If
End Sub


Sub exit_click
   serial1.Disconnect
   Activity.Finish 
   ExitApplication
End Sub


Sub AStreams_NewData (Buffer() As Byte)  
   
   LogMessage("", BytesToString(Buffer, 0, Buffer.Length, "ASCII"))
   
End Sub
   
Sub LogMessage(From As String, Msg As String)
   'txtLog.Text = txtLog.Text & From & ": " & Msg & CRLF
   'txtLog.SelectionStart = txtLog.Text.Length
      
   txtLog.Text = txtLog.Text & Msg & CRLF
   txtLog.SelectionStart = txtLog.Text.Length
      
   
   received_data = Msg ' HERE IS THE PROBLEM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      
End Sub

Sub AStream_Error
   ToastMessageShow("Connection is broken.", True)
   btnSend.Enabled = False
   txtInput.Enabled = False
End Sub      

Sub AStream_Terminated
   AStream_Error
End Sub


I think i have to search in the fist received string for "#" and then add the secend string and look if there is a "*". Than put the strings together too one string.

I only have one second to do this before the next strings comes.



i tried
B4X:
counter = 0
dim string1 as string
dim string2 as string
dim string3 as string
dim string4 as string

do while counter = buffer.lenght
  counter = counter +1
  counterchar = msg.charat(counter)

  if counterchar = "#" then
     string1 = msg
   end if
  if counterchar != "#" or counterchar !="*" then
     string2 = msg
  end if
  if counterchar = "*" then
    string3 = msg
  end if
loop

received_data = string1 & string2 & string3

But the problem is I don't know how often the received string is splitted. I variates fom 2 to 5 splits.

Maybe you have an idea (code) to do this.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Prefix mode only works if the other end supports it. In prefix mode when your program exits you will probably see an exception in the Logs pane because AsyncStreams is treating the first received four bytes as a length indicator.

Every time you get some data add it to any previous data string and check if IndexOf finds both a "*" and a "#". Chop out the bit between them with SubString and shorten the string to keep any remaining data. Rinse and repeat.
 
Upvote 0

stephankuba

Member
Licensed User
Longtime User
Problem

Thank you for your answear.
But i don't realy understand how to transform the example you posted into my code.
Maybe you have an idea?
 
Upvote 0

stephankuba

Member
Licensed User
Longtime User
Problem

I tried this:
B4X:
Sub LogMessage(From As String, Msg As String)
   'txtLog.Text = txtLog.Text & From & ": " & Msg & CRLF
   'txtLog.SelectionStart = txtLog.Text.Length
   
      txtLog.Text = txtLog.Text & From & Msg 
      txtLog.SelectionStart = txtLog.Text.Length
      
      If txtLog.Text.Contains("#") AND txtLog.Text.Contains("*") Then
         daten = txtLog.Text.SubString2(txtLog.Text.IndexOf("#"),txtLog.Text.IndexOf("*"))
         txtLog.Text = ""
      End If
      Msgbox(daten,"Data")
      
   
End Sub

but it makes only nonsens.

im my textbox the string is correct, maybe it's possible to get the string out of the textbox by reading the last line?

HELP
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Nonsense in what way? It looks a bit odd to add "From" to "Msg" before checking it as I assume what you want is in "Msg" and adding "From" might put it in the middle of separate parts of a full message but otherwise it looks OK except it returns the leading "#" but not the trailing "*". You might add 1 to the index of "#" if you just want the characters between them.
B4X:
daten = txtLog.Text.SubString2(txtLog.Text.IndexOf("#")+1,txtLog.Text.IndexOf("*"))
 
Upvote 0

stephankuba

Member
Licensed User
Longtime User
Problem

The device sends string's like this:#231;30895;21440;1837;1685;49;252;1;28;28;28;28;12 6;3242*

in the textbox the string is ok. Every second comes an other string an it looks like this in the textbox.

#231;30895;21440;1837;1685;49;252;1;28;28;28;28;12 6;3242*
#231;30895;21440;1837;1685;49;252;1;28;28;28;28;12 6;3242*
#231;30895;21440;1837;1685;49;252;1;28;28;28;28;12 6;3242*
#231;30895;21440;1837;1685;49;252;1;28;28;28;28;12 6;3242*

Now I want to cut the sting in pieces:

string1 : 231
string2 : 30895
string3 : 21440
....

The problem is in the variable "Msg" the sting is not complete.
I get for examle
#2
31;30895;21440;1837;1685;49;252;1;
28;28;28;28;12 6;3242*

How often it is cutted variates.

If i do this:
B4X:
Sub LogMessage(From As String, Msg As String)
    'txtLog.Text = txtLog.Text & From & ": " & Msg & CRLF
    'txtLog.SelectionStart = txtLog.Text.Length
    
        txtLog.Text = txtLog.Text & From & Msg 
        txtLog.SelectionStart = txtLog.Text.Length
        
        If txtLog.Text.Contains("#") AND txtLog.Text.Contains("*") Then
            daten = txtLog.Text.SubString2(txtLog.Text.IndexOf("#"),txtLog.Text.IndexOf("*"))
            txtLog.Text = ""
        End If
        Msgbox(daten,"Data") 'just to look for whats in daten
        
    
End Sub

in the variable daten I get
#231;30895;21440;1837;
or
#231;30895;21440;1837;231;30895;21440;1837;1685;49;252;1;28;28;28;28;12 6;3242*
or
;30895;21440;1837;1685;
.......


Now I'm realy clueless......

I'm thinking of reading the last line of the textbox in a string and then cut it,
but the problem is the program has to run for some days, if I get every second a string from device the strings will not fit in the textbox and the app crashes.
 
Upvote 0

candycedric

Member
Licensed User
Longtime User
hello

I try to use the following code:

B4X:
Sub AStreams1_newdata(buffer()As Byte)

LogMessage("", BytesToString(buffer, 0, buffer.Length, "utf8"))
End Sub
Sub LogMessage(From As String, msg As String)
   
    label13.Text = label13.Text & msg
       
       
        If label13.Text.Contains("#") AND label13.Text.Contains("*") Then
        daten = label13.Text.SubString2(label13.Text.IndexOf("#"),label13.Text.IndexOf("*"))
        label13.Text = ""
       
       
        End If
     
             
   
End Sub
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'ENVOI DONNEE AU PIC POUR RECUPERER TOUTES LES DONNEE ,TEMPERATURE , ETAT SORTIES
Sub timetemp_tick
Dim envoi() As Byte
envoi = "D".GetBytes("utf8")
astreams1.Write(envoi)
        IND0=daten.SubString2(1,6) 'recupere la temperature de la chaine ex: #20.00OFOOFFFO1025* = 20.00
pa=IND0 ' converti string en double pour comparaison de temperature dans timegeneral
    label1.Text = pa

the code works very well but after a while I no longer receives the data from the host, but I just continue to send

thank you for your help, I use jelly bean android 4.1.2
 
Upvote 0

raphael75

Active Member
Licensed User
Longtime User
I have not read your code in detail, but maybe you should replace
B4X:
label13.Text = ""
with
B4X:
label13.Text = label13.Text.SubString(label13.Text.IndexOf("*") + 1)
because there may be some new characters behind "*", and you don't want to delete them before the next label13.Text = label13.Text & msg .
 
Upvote 0

candycedric

Member
Licensed User
Longtime User
thank you,
I changed it :)

but would you tell me why that after a while I no longer receives anything?
the label13.text it freezes while the host continues many transmitter data

thank you in advance for your answers
 
Upvote 0

candycedric

Member
Licensed User
Longtime User
Here is the code:


B4X:
Sub Activity_Create(FirstTime As Boolean)
If FirstTime Then

    Activity.LoadLayout("coup")
   
   
Server.Initialize(5500, "Server")
Server.Listen
label14.Text=Server.GetMyIP & ("...OK")
   
   
   
   
Serial1.Initialize("Serial1")
timegeneral.Initialize("timegeneral",300)
timegeneral.Enabled=True   
plustemp="26.1"
mointemp="25.6"
End If
End Sub
Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
'CONNECTION SERVEUR POUR ENVOI VERS TELEPHONE
Sub Server_NewConnection (Successful As Boolean, NewSocket As Socket)
    If Successful Then
        ToastMessageShow("Connected", False)
        Socket1 = NewSocket
        astreams2.Initialize(Socket1.InputStream,Socket1.OutputStream,"Astreams2")
       
       
    Else
        ToastMessageShow(LastException.Message, True)
    End If
    Server.Listen
   
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'CONNECTION BLUETOOTH
Sub Button12_Click
Serial1.Connect("20:13:05:15:11:20")
End Sub
'SI CONNECTER AFFICHE CONNECTION OK
Sub Serial1_Connected (Success As Boolean)
  If Success Then
      ToastMessageShow("CONNECTION AU MODULE CANDY_BOARD", False)
astreams1.Initialize(Serial1.InputStream,Serial1.OutputStream,"astreams1")
button12.Color=Colors.Green
   
  Else
      Msgbox(LastException.Message, "erreur connection.FAIRE RESET HARDWARE")
      button12.Color=Colors.red
      End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' RECUPERE DONNEE ENVOYER DU PIC
Sub AStreams1_newdata(buffer()As Byte)
LogMessage("", BytesToString(buffer, 0, buffer.Length, "ASCII"))
   
       
 
End Sub
Sub LogMessage(From As String, Msg As String)
 
      label13.Text = label13.Text & Msg
    edittext1.Text = edittext1.Text &From & Msg
   
            If label13.Text.Contains("#") AND label13.Text.Contains("*") Then
            daten = label13.Text.SubString2(label13.Text.IndexOf("#"),label13.Text.IndexOf("*"))
            label13.Text = label13.Text.SubString(label13.Text.IndexOf("*") + 1)
            End If
           
           
            IND0=daten.SubString2(1,5) 'recupere la temperature de la chaine ex: #20.00OFOOFFFO1025* = 20.00
pa=IND0 ' converti string en double pour comparaison de temperature dans timegeneral
label1.Text = pa   
 
End Sub
 
Upvote 0

raphael75

Active Member
Licensed User
Longtime User
I don't see any obvious problems in your code.
Maybe you can try to deactivate some parts of the code to try to find where the problem is.
Does edittext1 freeze with following code ?

B4X:
Sub LogMessage(From As String, Msg As String)
    'label13.Text = label13.Text & Msg
    edittext1.Text = edittext1.Text &From & Msg

    'If label13.Text.Contains("#") AND label13.Text.Contains("*") Then
    '    daten = label13.Text.SubString2(label13.Text.IndexOf("#"),label13.Text.IndexOf("*"))
    '    label13.Text = label13.Text.SubString(label13.Text.IndexOf("*") + 1)
    'End If
        
    IND0=daten.SubString2(1,5) 'recupere la temperature de la chaine ex: #20.00OFOOFFFO1025* = 20.00
    pa=IND0 ' converti string en double pour comparaison de temperature dans timegeneral
    label1.Text = pa
End Sub
 
Upvote 0

candycedric

Member
Licensed User
Longtime User
thank you for your answer, but I dropped the bluetooth. I went into the wireless connection is much more reliable

sorry for my English I use google translator
 
Upvote 0
Status
Not open for further replies.
Top