Android Question buffer to text

wiwit

Member
Licensed User
Longtime User
hallo, i want to ask about buffer tot text

B4X:
Sub AStreams_NewData (Buffer() As Byte)
    Dim msg As String
 
   If msg.StartsWith ("S1") Then
       msg = BytesToString(Buffer, 0, 3, "UTF8") 
     
       Dim s1 As Int = msg
       Label1.Text = msg
    End If
       If msg.StartsWith ("S2") Then
           msg = BytesToString(Buffer, 0, 3, "UTF8")
 
       Dim s2 As Int = msg
       Label2.Text = s2
         
       End If
 
     
End Sub

Data does not appear on Android
 
Last edited:

emexes

Expert
Licensed User
i want to ask about buffer tot text
Ask away!

In the absence of an actual question, I suspect your problem is that you are using msg (".StartsWith") before msg is given a value. So put the "msg =" bit before you check it, eg:

B4X:
Sub AStreams_NewData (Buffer() As Byte)
Dim msg As String

msg = BytesToString(Buffer, 0, 3, "UTF8")  'msg = BytesToString(Buffer, 0, 3, "UTF8")
 
If msg.StartsWith ("S1") Then

Also note the possible upcoming problems:
(i) you should probably first check the length of the buffer, before converting it to a string, and
(ii) UTF8 conversion is probably going to do unexpected things for bytes > 127
 
Upvote 0

wiwit

Member
Licensed User
Longtime User
How are you going to determine the msg variable start with s1? I think your if condition block msg variable to begin passed sense you check before reading
Incoming data from Arduino via serial


S1200
S2400

I want to appear on Label1 200 and label2 400
 
Upvote 0

emexes

Expert
Licensed User
How about:
B4X:
Sub AStreams_NewData (Buffer() As Byte)

    Dim bc As ByteConverter

    Dim msg As String = bc.StringFromBytes(Buffer, "UTF8")
 
    If msg.StartsWith ("S1") Then
        Label1.Text = msg.SubString(2)
    End If

    If msg.StartsWith ("S2") Then
        Label2.Text = msg.SubString(2)
    End If

    'If msg.StartsWith ("S123") Then
    '    Label123.Text = msg.SubString(4)
    'End If

End Sub
:)
 
Upvote 0

emexes

Expert
Licensed User
Incoming data from Arduino via serial


S1200
S2400

I want to appear on Label1 200 and label2 400
If you have access to the Arduino program code, then you would be better to delimit/separate your message fields, eg:

S1=200
S2=400

and then you will be able to cleanly expand to S10 and beyond :)

You can decode the fields by:
B4X:
Dim EqualsAt As Int = msg.IndexOf("=")
If EqualsAt < 0 Then
    Log("invalid setting line: " & msg)
Else
    Dim SettingId As String = msg.SubString(0, EqualsAt)
    Dim SettingValue As String = msg.SubString(EqualsAt + 1)

    Select Case SettingId    'assuming B4A does selects on strings...
        Case "S1"
            Label1.Text = SettingValue

        Case "S2"
            Label2.Text = SettingValue

        Case "S9", "S10", "S11"
            Label9to11.Text = SettingValue

    End Select
End If
 
Upvote 0

emexes

Expert
Licensed User
Otherwise you cannot assume that the messages will not be split.
This is a good point (that I always forget)(and Erel always remembers).

If you are still having trouble, even after rearranging the code so that you check msg *after* putting something in it, then split messages may well be the problem, and AsyncStreams in prefix (or text line) mode is a solution, if you have access to the Arduino side of the interface.
 
Upvote 0

wiwit

Member
Licensed User
Longtime User
If you have access to the Arduino program code, then you would be better to delimit/separate your message fields, eg:

S1=200
S2=400

and then you will be able to cleanly expand to S10 and beyond :)

You can decode the fields by:
B4X:
Dim EqualsAt As Int = msg.IndexOf("=")
If EqualsAt < 0 Then
    Log("invalid setting line: " & msg)
Else
    Dim SettingId As String = msg.SubString(0, EqualsAt)
    Dim SettingValue As String = msg.SubString(EqualsAt + 1)

    Select Case SettingId    'assuming B4A does selects on strings...
        Case "S1"
            Label1.Text = SettingValue

        Case "S2"
            Label2.Text = SettingValue

        Case "S9", "S10", "S11"
            Label9to11.Text = SettingValue

    End Select
End If
ok thank you.i will try this way
 
Upvote 0

wiwit

Member
Licensed User
Longtime User
Your best option is to use B4R on the Arduino and use AsyncStreams in prefix mode. Otherwise you cannot assume that the messages will not be split. You can use AsyncStreamsText in B4A if the messages end with a defined character.
I want to learn B4R
 
Upvote 0

wiwit

Member
Licensed User
Longtime User
How about:
B4X:
Sub AStreams_NewData (Buffer() As Byte)

    Dim bc As ByteConverter

    Dim msg As String = bc.StringFromBytes(Buffer, "UTF8")
 
    If msg.StartsWith ("S1") Then
        Label1.Text = msg.SubString(2)
    End If

    If msg.StartsWith ("S2") Then
        Label2.Text = msg.SubString(2)
    End If

    'If msg.StartsWith ("S123") Then
    '    Label123.Text = msg.SubString(4)
    'End If

End Sub
:)
I tried it already ok, when I creamed S1340 or S1 = 340.
appeared to work well.
but when I send S130 or S1 = 30 an error appears.
The point is that every data less than 3 digits the app appears error
 
Upvote 0

emexes

Expert
Licensed User
I tried it already ok, when I creamed S1340 or S1 = 340.
appeared to work well.
but when I send S130 or S1 = 30 an error appears.
The point is that every data less than 3 digits the app appears error
Hmm. Perhaps I have assumed too much of .SubString. Add the following Log lines, post the resultant log:
B4X:
Sub AStreams_NewData (Buffer() As Byte)

    Dim bc As ByteConverter

    Dim msg As String = bc.StringFromBytes(Buffer, "UTF8")
    Log("msg = " & msg.Length & " [" & msg & "]")    '*** ADD THIS LINE ***
 
    If msg.StartsWith ("S1") Then
        Log("S1")                                    '*** ADD THIS LINE ***
        Label1.Text = msg.SubString(2)
    End If

    If msg.StartsWith ("S2") Then
        Log("S2")                                    '*** ADD THIS LINE ***
        Label2.Text = msg.SubString(2)
    End If

    'If msg.StartsWith ("S123") Then
    '    Label123.Text = msg.SubString(4)
    'End If

End Sub
 
Upvote 0

wiwit

Member
Licensed User
Longtime User
Hmm. Perhaps I have assumed too much of .SubString. Add the following Log lines, post the resultant log:
B4X:
Sub AStreams_NewData (Buffer() As Byte)

    Dim bc As ByteConverter

    Dim msg As String = bc.StringFromBytes(Buffer, "UTF8")
    Log("msg = " & msg.Length & " [" & msg & "]")    '*** ADD THIS LINE ***
 
    If msg.StartsWith ("S1") Then
        Log("S1")                                    '*** ADD THIS LINE ***
        Label1.Text = msg.SubString(2)
    End If

    If msg.StartsWith ("S2") Then
        Log("S2")                                    '*** ADD THIS LINE ***
        Label2.Text = msg.SubString(2)
    End If

    'If msg.StartsWith ("S123") Then
    '    Label123.Text = msg.SubString(4)
    'End If

End Sub
everything is not good.
I tried to see incoming data from the serial via Bluetooth Terminal Hc05 is ok.
but when in the application such as lack of response. even label2.text doesn't appear

ino code
B4X:
void setup() {
  Serial.begin(9600);
}
void loop() {
  int S1 = analogRead(A0);
  int S2 = analogRead(A1);
 
    Serial.print("S1");
    Serial.println(S1);
     delay(100);
    Serial.print("S2");
   Serial.println(S2);
 
 
  delay(100);   
}
 
Upvote 0

emexes

Expert
Licensed User
Righto, first thing is that I am itching to do is make this code more future-proof, and the serial communications more human-readable, by adding that "=":
B4X:
void loop() {
    int S1 = analogRead(A0);
    Serial.print("S1=");
    Serial.println(S1);
  
    delay(100);

    int S2 = analogRead(A1);
    Serial.print("S2=");
    Serial.println(S2);
 
    delay(100);  
}
Then see if you can see those incoming lines with a regular terminal program like RealTerm.
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Then, in your B4A Android app, temporarily rename the existing AStreams_NewData Sub to old_AStreams_NewData.

Use this in its place, to log the same incoming data, and post say a dozen lines to this thread.
B4X:
Sub AStreams_NewData (Buffer() As Byte)

    Dim bc As ByteConverter
    Log(DateTime.Now & " " & bc.HexFromBytes(Buffer) & " " & bc.StringFromBytes(Buffer, "UTF8"))

End Sub
Once we've confirmed how the data is coming in, then we'll know how to handle it :)
 
Upvote 0

wiwit

Member
Licensed User
Longtime User
If you have access to the Arduino program code, then you would be better to delimit/separate your message fields, eg:

S1=200
S2=400

and then you will be able to cleanly expand to S10 and beyond :)

You can decode the fields by:
B4X:
Dim EqualsAt As Int = msg.IndexOf("=")
If EqualsAt < 0 Then
    Log("invalid setting line: " & msg)
Else
    Dim SettingId As String = msg.SubString(0, EqualsAt)
    Dim SettingValue As String = msg.SubString(EqualsAt + 1)

    Select Case SettingId    'assuming B4A does selects on strings...
        Case "S1"
            Label1.Text = SettingValue

        Case "S2"
            Label2.Text = SettingValue

        Case "S9", "S10", "S11"
            Label9to11.Text = SettingValue

    End Select
End If

I have replaced it with this code, but there was an error while in Run :(
Too many parameters.
which one should i fix

B4X:
Sub AStreams_NewData (Buffer() As Byte)
    Dim bc As ByteConverter

    Dim msg As String = bc.StringFromBytes(Buffer, "UTF8")
    Log("msg = " & msg.Length & " [" & msg & "]")   

    Dim EqualsAt As Int = msg.IndexOf("=")
    If EqualsAt < 0 Then
        Log("invalid setting line: " & msg)
    Else
        Dim SettingId As String = msg.SubString(0, EqualsAt)
        Dim SettingValue As String = msg.SubString(EqualsAt + 1)

        Select Case SettingId    'assuming B4A does selects on strings...
            Case "S1"
                Label1.Text = SettingValue

            Case "S2"
                Label2.Text = SettingValue
        End Select
    End If
End Sub
 
Upvote 0

emexes

Expert
Licensed User
The error message should have indicated precisely which line the error was on, but at least you mentioned the "too many parameters" message which was clue enough that the problem is probably the line:

Dim SettingId As String = msg.SubString(0, EqualsAt)

which should be:

Dim SettingId As String = msg.SubString2(0, EqualsAt)
 
Upvote 0

emexes

Expert
Licensed User
I'm hopeful it will all now work no problem, but I'd be happy to see the log anyway just to be sure.

There is still the possibility that text lines might be split into two delivery events, with the start of a line in one packet and the end in the next packet. The solution is probably AsyncStreamsText per:

https://www.b4x.com/android/forum/threads/b4x-asyncstreams-tutorial.7669/

which says:
- If the data sent and received is text based and each message ends with an end of line character(s) then you should use AsyncStreamsText. For example if you are connecting to an external GPS. Note that it is also possible to modify the class and support different delimiters.
The advantage of using AsyncStreamsText is that it will build the messages correctly. You will not receive partial messages (or multiple messages together).
The AsyncStreamsText class file is at:

https://www.b4x.com/android/forum/t...eful-when-working-with-streams-of-text.27002/
 
Upvote 0
Top