B4J Code Snippet B4A - Sockets and AsyncStreams

@DonManfred actually provided the foundation for this, and I thought it worthy of a snippet.

This involves connecting an android device to an AP and getting data that a scale controller is publishing to it via a RS232 to Ethernet device (every second). If nothing is listening, the data simple vanishes into byte ether...

Sub Process_Globals

    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim sock As Socket ' Network lib
    Dim AStreams As AsyncStreams ' RandomAccesfile lib  
    Public wghtmsg As String = ""

End Sub

Pause and Resume Subs
Sub Activity_Pause (UserClosed As Boolean)

        AStreams.Close  ' close any open stuff... (safe call if not inited)

End Sub

Sub Activity_Resume
    If AStreams.IsInitialized Then ' close any open socket (not likely since Pause took care of this...)
    End If
    If sock.IsInitialized Then   ' close any open stream
    End If

    StartScale   ' create new scale socket object
End Sub

Sub StartScale
    sock.Connect("",10001, 10000)
    ' IP address, port, timeout (10 seconds)
    ToastMessageShow(" Connecting to Scale Controller... ",False)

End Sub

Sub Scalecontroller_Connected (Successful As Boolean) ' raised on either success or failure (timeout)
    Log($"Scalecontroller_Connected: (${Successful})"$)
    If Successful Then
        AStreams.Initialize(sock.InputStream,   Null, "Scale") 
       ' create a new stream. Here we only need the input stream from the controller
       ' create an output stream if you wish to talk back to it.
        ToastMessageShow(" Connection to Scale Controller Failed! ",True)
        SetWeight   '  If, after 10 seconds we cannot connect (some hard problem) then allow manual input    
    End If      
End Sub

Now that we are connected to the IP and port, let's get the data

Sub Scale_NewData (Buffer() As Byte)

' of course, the following example is specific to my needs - yours WILL vary...

    Dim w As String = ""
    w  = BytesToString(Buffer, 0, Buffer.Length, "UTF8")  ' temp var for processing in buffer
       Log("length of w: "&w.Length&" string: "&w)  ' show the length and what is inside...
'  Note: serial to ethernet device has a 2k buffer. This will be sent on first open but string is not 17 chars long (2017 bytes) - so ignore...

    If  w.Length = 17 Then    ' A valid string IS 17 characters long (no more - no less)
       For i = 0 To w.Length-1  ' this was used to see exactly what the string was made of (for testing).  Many space characters in it...
          Log(" i: "&i& "  ["&w.SubString2(i,i+1)&"]")  ' what is each character in string
          Log(" i: "&i& "  ["&Buffer(i)&"]")                   ' what is each buffer byte value
        wghtmsg = w.SubString2(3, 15)  '  this is the center (valid weight) portion of the passed buffer. The rest are control - info characters and carriage return
        If w.SubString2(2,3) = Chr(34) Then  '     if byte 3 is a " , then the value of weight is negative .  ( you can't """ to do this, hence the Chr(34) )
           wghtmsg = "-"& wghtmsg.Trim  ' append a " - " (minus sign) to the trimmed weight value (get rid of spaces fore and aft)
        End If
        If w.SubString2(2,3) = "(" Then    ' if this char is at location, it means the scale has not yet stabilized (truck is driving on and shaking it)
           wghtmsg = "*"&wghtmsg.Trim&"*"  ' Add " * " to the string to indicate Not Stable
        End If
        wghtmsg = wghtmsg.Trim  ' trim this public var again
        lblweight.Text = wghtmsg.Trim&" lb"   ' add " lb" to the label text (not really needed)
    End If
    Log("  weight: "&lblweight.Text)
End Sub

Sub Scale_Error ' on error
    ToastMessageShow("Scale Error: "&LastException.Message, True)
    Log("Scale_Error: "&LastException.Message)
End Sub

Sub Scale_Terminated ' if terminated somehow....
    If AStreams.IsInitialized Then   ' close everything if terminated.  Also - close in Pause!
    End If

End Sub

Sub SetWeight   ' if mobile device can't reach AP, then have driver type in the weight
                       '  from the digital display on the scale controller (which most always works - 99.8%)

  Dim i As Int
  Dim xlo As String
  Dim kbrd As Phone
  xlo = "" ' NumberFormat2(lo ,1,1,1,False)

  Dim param As BD_InputBoxParams
  Dim bd As BetterDialogs
  param.Default = xlo
  param.InputType = param.INPUT_TYPE_DECIMAL_NUMBERS
  param.InputTextSize = 24
  param.Question = "Provide The Vehicle Weight"
  param.QuestionTextSize = 28
  param.SpaceBetween = 15dip
  param.Multiline = False
  i = bd.InputBox(" Controller Connection Failed! ",param,"OK","Cancel","",DefCM.BLC)

  If i = DialogResponse.POSITIVE  Then
        wghtmsg = param.Answer
  End If

End Sub

There you have it. A simple and elegant way to use a socket and stream to get data from, in this case, an access point broadcasting on a specific address and port.

Last edited: