B4A Library [class] AsyncStreamsText - Useful when working with streams of text

Status
Not open for further replies.
When a message (set of bytes) is sent over a network channel, of any type, there is no guarantee that the whole message will arrive as a single set of bytes.

The message might be split or merged together with other messages.

One way to overcome this issue is to initialize AsyncStreams in "prefix" mode. In this mode a 4 bytes header is added to each message with the message length. This allows AsyncStreams to internally build the messages correctly. However you can only use prefix mode if both sides of the connection adhere to this protocol. If for example you connect to a Bluetooth GPS then you cannot use prefix mode.

AsyncStreamsText can help you if:
1. The data sent is text and not binary data.
2. Each message ends with an end of line character (both Unix and Windows formats will work).

AsyncStreamsText works by handling the NewData event and looking for the end of line characters.

Using AsyncStreamsText is simple:
B4X:
Sub Process_Globals
   Private ast As AsyncStreamsText
   Private server As ServerSocket
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      server.Initialize(5555, "server")
      Log(server.GetMyWifiIP)
      server.Listen
   End If
End Sub

Sub server_NewConnection (Successful As Boolean, NewSocket As Socket)
   If Successful Then
      If ast.IsInitialized Then ast.Close
      ast.Initialize(Me, "ast", NewSocket.InputStream, NewSocket.OutputStream) 'initialize AsyncStreamsText with the socket streams.
   Else
      Log(LastException)
   End If
   server.Listen
End Sub

Sub ast_NewText(Text As String)
   Log("Text: " & Text)
   Log(Text.Length)
End Sub

Sub ast_Terminated
   Log("Connection terminated")
End Sub

Sub Activity_Click
   ast.Write("this is an example..." & Chr(10) & Chr(13))
End Sub

NewText event is raised each time that there is a complete message available.

Note that AsyncStreamsText.Write writes text and not bytes.
The charset field sets the encoding used to convert the bytes to string and vice versa.
 

Attachments

  • AsyncStreamsText.bas
    1.8 KB · Views: 3,413
Last edited:

Tom Christman

Active Member
Licensed User
Longtime User
Okay I changed the erroneous line to
B4X:
ast.Initialize(usb,"ast",usb.GetInputStream,usb.GetOutputStream)
and the program will compile and download to the device, but when the program is started, it fires a "java.lang.Exception: Sub astreams_newdata was not found." I've enclosed the zip file.
 

Attachments

  • UsbNewerror.zip
    9.1 KB · Views: 305
Last edited:

EvgenyB4A

Active Member
Licensed User
Longtime User
I made the same exersize. I try to modify USBSerial Example and to use

AsyncSteamsText class. I added the .bas module as existing module and at compiling I get:
Parsing code. Error
Error parsing program.
Error description: Unknown type: asyncstreamstext
Are you missing a library reference?
Occurred on line: 16
Dim ast As AsyncStreamstext
 

PD5DJ

Member
Licensed User
Longtime User
I am trying this with the Serial1 (bluetooth) example, but i cant seem to change this to asyncstreamstext...

I want to use this because all my receiving commands are in ASCII ending with CR's.
 
Last edited:

PD5DJ

Member
Licensed User
Longtime User
I totally dont get it, how this works.

I added the Class to my code.. changed the Asyncstreams to asyncstreamstext in process globals.

Then i get a compile error in my code at: AStreams.Initialize(Serial1.InputStream, Serial1.OutputStream, "AStreams")

I have added my code:
 

Attachments

  • v1.1.zip
    164.8 KB · Views: 413

PD5DJ

Member
Licensed User
Longtime User
Go over the code in the first post. You are not initializing the object correctly.

That i am aware of :), but the question is "How do I initialize it"

I dont have a clue whatsover..

I already was happy that I got the normal Asyncstreams working. :)
 

PD5DJ

Member
Licensed User
Longtime User
Ok i have changed my main code to this:

I changes the Astreams to AST,

But it still gives error at: ASt.Initialize(Serial1.InputStream, Serial1.OutputStream, "ASt")


B4X:
#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: True
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region
#ApplicationLabel: BlackBox Simple Remote
#CanInstallToExternalStorage: true
#SupportedOrientations: portrait
#FullScreen: true
'Activity module
Sub Process_Globals
    Dim Serial1 As Serial
    Dim TextReader1 As TextReader
    Dim TextWriter1 As TextWriter
    Dim connected As Boolean
    Private ASt As AsyncStreamsText
    Dim RX As String
End Sub

Sub Globals
    Dim PWS As PhoneWakeState
    Dim txtSend As EditText
    Dim Azimuth As Int
    Dim Elevation As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Manual")

    If FirstTime Then
        Serial1.Initialize("Serial1")
        PWS.KeepAlive(True)
    End If
    Activity.AddMenuItem("Connect", "MenuConnect")
    Activity.AddMenuItem("Disconnect", "MenuDisconnect")
    Activity.AddMenuItem("Exit","MenuExit")
    Activity.Title = "BlackBox Simple Remote"
End Sub
Sub Activity_Resume
    If Serial1.IsEnabled = False Then
        Msgbox("Please enable Bluetooth.", "")
    Else
        Serial1.Listen 'listen for incoming connections
    End If
End Sub
Sub menuConnect_Click
    Dim PairedDevices As Map
    PairedDevices = Serial1.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, "Choose device", -1) 'show list with paired devices
    If res <> DialogResponse.CANCEL Then
        Serial1.Connect(PairedDevices.Get(l.Get(res))) 'convert the name to mac address
    End If
End Sub
Sub MenuExit_click
    PWS.ReleaseKeepAlive
    Serial1.Disconnect
    connected = False   
    ExitApplication
End Sub
Sub Serial1_Connected (Success As Boolean)
    If Success Then
        ToastMessageShow("Connected successfully", False)
    ASt.Initialize(Serial1.InputStream, Serial1.OutputStream, "ASt")
        connected = True
    Else
        connected = False
        Msgbox(LastException.Message, "Error connecting.")
    End If
End Sub
Sub menuDisconnect_Click
    Serial1.Disconnect
    connected = False
End Sub

Sub Activity_Pause(UserClosed As Boolean)
    If UserClosed Then
        'Log("closing")
        'AStreams.Close
    End If
End Sub


Sub AStreams_NewData (Buffer() As Byte)
    Dim msg As String
    Dim x As Byte
    msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
    If msg.StartsWith("+") Then
        x = 1
        Azimuth = msg.SubString2(2,5)
        Elevation = msg.SubString2(7,10)
        Else
        x= 0
    End If
End Sub

Sub AStreams_Error
    ToastMessageShow(LastException.Message, True)
End Sub
Sub btnSend_Click
  If ASt.IsInitialized = False Then Return
  If txtSend.Text.Length > 0 Then
        Dim buffer() As Byte
        buffer = txtSend.Text.GetBytes("UTF8")
        ASt.Write(buffer)
        txtSend.SelectAll
        'Log("Sending: " & txtSend.Text)
    End If
    txtSend.Text = ""
End Sub
Sub Send_Single_Command (Command As String)
    Dim Buffer() As Byte
    Dim B As String
    B = Command & Chr(13)
    Buffer = B.GetBytes("UTF8")
    ASt.Write(Buffer)   
End Sub
Sub UP_Click
    Send_Single_Command("U")   
End Sub
Sub down_Click
    Send_Single_Command("D")       
End Sub
Sub CW_Click
    Send_Single_Command("R")   
End Sub
Sub ccw_Click
    Send_Single_Command("L")       
End Sub
Sub Stop_Click
    Send_Single_Command("S")   
End Sub

Sub button_az_0_Click
    Send_Single_Command("M000")
End Sub
Sub Button_az_90_Click
    Send_Single_Command("M090")   
End Sub
Sub Button_az_180_Click
    Send_Single_Command("M180")   
End Sub
Sub Button_az_270_Click
    Send_Single_Command("M270")   
End Sub
Sub Button_az_360_Click
    Send_Single_Command("M360")   
End Sub
Sub Button_el_0_Click
    Send_Single_Command("Y000")   
End Sub
Sub Button_el_22_Click
    Send_Single_Command("Y022")   
End Sub
Sub Button_el_45_Click
    Send_Single_Command("Y045")   
End Sub
Sub Button_el_67_Click
    Send_Single_Command("Y067")   
End Sub
Sub Button_el_90_Click
    Send_Single_Command("Y090")   
End Sub
Sub GotoManual_Click
    Activity.RemoveAllViews
    Activity.LoadLayout("manual")   
End Sub
Sub GotoPreset_Click
    Activity.RemoveAllViews
    Activity.LoadLayout("preset")   
End Sub
 

shmulik taiber

Member
Licensed User
Longtime User
Hello erel .
I've downloaded the AST module, haven't modified it, but can't seem to get it to initialize .
I've tried in my code :
ast.Initialize("","ast",usb.GetInputStream, usb.GetOutputStream) ,and got :

java.lang.RuntimeException: java.lang.RuntimeException: java.lang.Exception: Sub ast_newtext was not found.
I've look inside the AST code but I guess seem to understand the meaning of the target module and event name..... the program worked with the normal async .
 

agus mulyana

Member
Licensed User
Longtime User
Hi,

I would like to receive serial data from Arduino, and try to use this class, but i do not understand, what should i do to add this call to my project and how to use it properly ? please help me
 

agus mulyana

Member
Licensed User
Longtime User
Hi

I have been using this class, and good for text, but when i send my serial data from ARDUINO, for example : ERG,123,RH,45, the decimal data is missing,,what should i do to fix this problem ? please help me

thanks a lot
 

agus mulyana

Member
Licensed User
Longtime User
Hi erel, thank you for your respon, but the problem is solved, i do a little fix in arduino code, thank you erel
 
Status
Not open for further replies.
Top