Android Question USING RANDOM ACCESS STREAMS FOR TCP SOCKETS

rgarnett1955

Active Member
Licensed User
Longtime User
Hi

I am using a random access AStreams to talk to an embedded processor (EP) with WiFI. In summary code I do the following:

B4X:
======================================================
Dim cmdAckglbl As Boolean

======================================================
Sub Activity_Create(FirstTime As Boolean)
   Sock1.Initialize("Sock1")
   Sock1.Connect("20.0.0.1", 8899, 5000)
End Sub

======================================================
Sub Sock1_Connected(Successful As Boolean)
   AStreams.InitializePrefix(Sock1.InputStream, False, Sock1.OutputStream, "AStreams")

   cmdNoglbl = 0   'Set Date
   sendCommand

   Do While cmdAckglbl = False
     Sleep(20)
   Loop

   cmdNoglbl = 14   'Get Serial No
   sendCommand

   Do While cmdAckglbl = False
     Sleep(20)
   Loop

   .... Other commands here

   voltageGraph(False)
End Sub

======================================================
Sub sendCommand()
   cmdAckglbl = False

   Select cmdNoglbl
     Case 0  ' Set date
       strBuff = DateTime.Date(DateTime.now)
       strBuff = "$SetDate," & strBuff & Chr(13) & Chr(10)
       buffer = strBuff.GetBytes("UTF8")
       AStreams.Write(buffer)
  
     Case 14   ' get Serial Number  
       strBuff = "$GetSerNo,"
       buffer = strBuff.GetBytes("UTF8")
       AStreams.Write(buffer)

     Case 16   ' get Waveforms
       strBuff = "$GetWaveForms,"
       buffer = strBuff.GetBytes("UTF8")
       AStreams.Write(buffer)
  
     Case 17   ' get Last Log Entry
       strBuff = "$GetLastLog,"
       buffer = strBuff.GetBytes("UTF8")
       AStreams.Write(buffer)
   End Select
End Sub

======================================================
Sub AStreams_NewData (buffer() As Byte)

   Dim i As Int
   Dim k As Int
   Dim testFloat As Float

   Dim strBuff As String

   Select cmdNoglbl
     '------------------------------------------------------------------------------
     Case 0   ' Set date
       msg = BytesToString(buffer, 0, buffer.Length, "UTF8")
       lblStatus.Text = lblStatus.Text & " - Time Set: " & msg.SubString(9)
       cmdAckglbl = True

     '------------------------------------------------------------------------------
     Case 14   ' Get Serial Number
       msg = BytesToString(buffer, 0, buffer.Length, "UTF8")
       msg = msg.SubString(10)
       msg = " Fence Ser No: " & msg
       lblTitle.Text = msg
       cmdAckglbl = True
    
     '------------------------------------------------------------------------------
     Case 16   ' Get WaveForms
       Conv.LittleEndian = True
    
       'Convert block of bytes from buffer to floats
       fieldFloatBlock = Conv.FloatsFromBytes(buffer)
    
       'Append this block to the data set
       For i = 0 To blockSize - 1
         k = blockSize * blockNum + i
         waveFloat(k) = fieldFloatBlock(i)
       Next
  
       If blockNum < 7 Then
         'Send the acknowledge'
         strBuff = "ack"
         buffer = strBuff.GetBytes("UTF8")
         AStreams.Write(buffer)
         blockNum = blockNum + 1
         blockNum = blockNum
       Else
         cmdAckglbl = True
       End If
    
     '------------------------------------------------------------------------------
     Case 17   ' Get Last Log Entry
       msg = BytesToString(buffer, 0, buffer.Length, "UTF8")

       cmdAckglbl = True

   End Select
End Sub

======================================================
Sub btnRefresh_Click
   msg = ""
   cmdNoglbl = 16   'Get Last Waveform
   sendCommand
    
   Do While cmdAckglbl = False
     Sleep(2)
   Loop

   msg = ""
   cmdNoglbl = 17   'Get Last Log
   sendCommand

   Do While cmdAckglbl = False
     Sleep(2)
   Loop

   msg = ""
   'edtDebug.Text = ""
   cmdNoglbl = 16   'Get Last Waveform
   sendCommand

   Do While cmdAckglbl = False
     Sleep(2)
   Loop
  
   voltageGraph(tglBtnZoom.Checked)
End Sub

The idea is that I use the global variable cmdAckglbl as a semaphore set by the AStreams_NewData sub, to signal that data from the EP is ready using a,

Do While cmdAckglbl = False
Sleep(2)
Loop


This works fine within the Sub Sock1_Connected sub but does not work in the subroutine btnRefresh_Click. In the btnRefresh_Click sub. The do while loops do not detect the cmdAckglbl becoming True and so never move forward to the next statements.

I have tried 0 ms in the sleep statement, but then it just seems to fall straight through with no waiting for the semaphore to become true.

I also tried a "Wait For" event statement, using cmdAckglbl as the event, but this didn't work either.

I read up on events, but could not work out how to generate a suitable event from the AStreams_NewData sub.

I have uploaded the whole project in a zip file.

I am used to embedded C programming using deferred interrupts and all those wonderful things so I struggle a bit with higher level languages running on general purpose operating systems.

Please Help
 

Attachments

  • eFence1.01.zip
    138.3 KB · Views: 151
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. Please edit the title and don't use all caps.
2. Please use [code]code here...[/code] tags when posting code.
3. You should use File - Export as zip to create a zip with the required files.

I don't see any issue in your code. However it is inefficient.

You should use Wait For instead:
B4X:
sendCommand
Wait For CanContinue
'...

Sub Astreams_NewData (buffer() As Byte)
'data is available
CallSubDelayed(Me, "CanContinue")
End Sub
 
Upvote 0

rgarnett1955

Active Member
Licensed User
Longtime User
Hi

Sorry about point 1
Sorry about point 2
I did use "send to compressed zip file windows explorer context menu" to zip file point 3.

I can't see any problems with my code either, but it doesn't work in the refresh subroutine. As for it's efficiency it is my first go at using B4A.

I think I understand your solution I will play around with it

Thankyou.
 
Upvote 0

rgarnett1955

Active Member
Licensed User
Longtime User
Hi Erel,

I wasn't able to get it working. I had a look at the B4x Basic language manual pp 47 which covers waiting for a resumable sub to complete and tried the example given. viz

B4X:
#Region  Project Attributes
   #ApplicationLabel: B4A Example
   #VersionCode: 1
   #VersionName:
   'SupportedOrientations possible values: unspecified, landscape or portrait.
   #SupportedOrientations: unspecified
   #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
   #FullScreen: False
   #IncludeTitle: True
#End Region

Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim allDone As Boolean
End Sub

Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:
   'Activity.LoadLayout("Layout1")
   FirstSub
   allDone = True 'Breakpoint
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub FirstSub
   Log("FirstSub started")
   SecondSub
   Wait For SecondSub_Complete
   Log("FirstSub completed")
End Sub

Sub SecondSub
   Log("SecondSub started")
   Sleep(10000)
   Log("SecondSub completed")
   CallSubDelayed(Me, "SecondSub_Complete")
End Sub

You will note I put a 10 second time delay into SecondSub, but the delay does not occur. I put a break point where I set allDone to True, but the program runs straight through with no delay. Am i doing something wrong?

In the code you posted:
B4X:
sendCommand
WaitFor CanContinue

'...
Sub Astreams_NewData (buffer() As Byte)
'data is available
CallSubDelayed(Me, "CanContinue")
End Sub

What is in the sub "CanContinue"

Could you elaborate on the "CanContinue" sub?; what's in it and how it works.

Thanks
Rob
 
Upvote 0

rgarnett1955

Active Member
Licensed User
Longtime User
Hi Erel,

I have got it working. The penny dropped after I looked at how the example in the manual worked.

Thanks
 
Upvote 0
Top