Android Tutorial [B4X] AsyncStreams Tutorial

Status
Not open for further replies.

dcafuta

New Member
Licensed User
Longtime User
Problem with astream and arduino project

Connected android over blietooth serial to arduino. Arduiono receives the data and answers (9600bps).
Created global array data(50) as byte and length as int

Astream_newdata contains code (sorry for syntax errors)
For i=0 to buffer.length-1
Data[length+i]=buffer
next
Length=length+buffer.length
End sub

Arduino is sending FF000281829C (checked with .net code on pc using the same bluetooth to serial adapter)
Android is receiving most of the time wrong results. Most of the times rearenged data as 0002818FF29C. Error is every time different.

I suspect that thread with newer data is executed before the older data.

Is there any simpler and faster way to fill my global buffer (array data) to check it on timer tick?

Is there any way to postpone receiving of newdata event (i can predict how much byte need to receive from arduino)?

Arduino is using format FF as message start and 0002 dictate length of 2 byte plus one last checksm byte. Can i rearange serial lib and make prefix compatible with this protocol?

Any help apprichiated

:sign0085:
 

flyingbag

Member
Licensed User
Longtime User
Sample working code posted

Hi,
As a beginner I know that it is difficult to wrap your head around Sockets, Server Sockets and Asyncstreams...

Here is sample code that can help you to debug and understand better - it does TCP/IP Socket communication with a server using B4A android app

Please find attached:
- SocketServer.zip (this has java code for a socket that runs on a server, listens to the text that client sends, and echoes it back)

-TestClientSocket.zip (this has B4a code - you can install on your device and debug to test Asyncstreams as well as Socket connections etc)

How to run?:
-unzip the SocketServer.zip. Copy the two files inside this zip into a directory. You need Java installed on this machine. If you do not have Java installed - you can download Java from here
- On commandline - go to the folder which has the above two files
- In that folder: Run on commandline : java SocketServer
- the server will now start and by default listen on port 9092
- if you want to choose a different port - run commandline : java SocketServer <yourchosenportnumber>
- eg: java SocketServer 8081
- IMPORTANT: Make sure that firewall on the machine where you install this server allows connections on the port you have chosen!

-Now unzip the TestClientSocket.zip
- Open the b4a code - make sure that you set the "ip" and "port" fields in sub globals to match the ip of the machine running the above Socketserver and the port that it is listening on
- Install this on a real device (not emulator)
- Connect to server - type the text in lower text box - you should see the echo from the server
- Debug and understand Connect, AsyncStreams Read and Write etc ...

I spent a lot of time trying to understand this - eventually it was very simple. Hope this helps the beginners to get started quickly - just like others out here helped me

Enjoy
flyingbag
 

Attachments

  • SocketServer.zip
    2.9 KB · Views: 1,879
  • TestClientSocket.zip
    7.2 KB · Views: 2,261
Last edited:

Sbleck

Member
Licensed User
Longtime User
Is there any other way to check this ?


Hello,

Wanted to check this example, but encountered some problems that I mentioned below:


Wanted to know what could be done to see the mentioned results, as expected. Was not mentioned what release of Java is needed, also...

Regards,
Sven
 

IanMc

Well-Known Member
Licensed User
Longtime User
You can queue the messages and process them with a timer every x milliseconds.

Would you have any examples of how to do this?

I am sending a string of data from my Arduino but it always splits it up so that if for example I send the word hello I get

h
ello

I don't want to have to use prefix mode, is there anything I can easily do in the AStream_NewData Subroutine?
 

mc73

Well-Known Member
Licensed User
Longtime User
In the newData sub, you can add your new data to a string, name it 'myBuffer' declared in globals, and at the same time, we can declare a variable, name it 'ticksOfInactivity'.
B4X:
myBuffer=myBuffer & BytesToString(Buffer, 0, Buffer.Length, "UTF8")
At the same time, you enable a time (after the addition) and set the ticksOfInactivity to zero.
B4X:
ticksOfInactivity=0
timerStreams.enabled=true
At the timerStreams_tick, you increase the 'ticksOfInactivity', and if they reach a certain value, you process the 'myBuffer' string,empty it, disable the timer and set the ticks to zero (optionally).
B4X:
sub timerStreams_tick
   ticksOfInactivity=ticksOfInactivity+1
   if ticksOfInactivity=ourSetMaxTicks then
     'process myBuffer
     myBuffer=""      
     timerStreams.enabled=false
   end if
end sub
You have to set a reasonable interval for the timer, in order for it to wait a bit until it's decided that we received a 'full' string.
Surely there are other ways to do this as well and probably more efficiently, cause I am not sure what will happen, if there is a 'sleep' interval, and then data are received at the very same moment that the timer is processing the buffer
 

IanMc

Well-Known Member
Licensed User
Longtime User
Thanks mc73 I'll study that code and see if I can use it.

Well it works!

But instead of using another 'ticksOfInactivity' variable I just used:

timerStreams.Initialize("timerStreams", 100)

initialising the timer to 100 milliseconds.

Thanks again!

perhaps in the future Erel might make an AsyncStreams2 which has this timer function built in but this works fine.
 
Last edited:

dddvvv

Member
Licensed User
Longtime User
asyncstreamprefix troubles

Hi everyone

I have been trying asyncstream on my galaxy tab. Works with the bluetooth chat example, although im getting mixed data, like;

Bl
Uetooth

So im trying the prefix mode, and not having any luck. The app force closes immediately i connect.

Im just confused about the requirements of the four prefix bytes.
How are they suppossed to be formatted?
Is it : 0 0 0 3 "234"
OR : 3 3 3 3 "234"

Ive been struggling with this for weeks, on and off. Data is coming from a pic microcontroller, and can be formatted to support the prefix mode.

Thanks
Ddd
 

derez

Expert
Licensed User
Longtime User
I wrote a basic4ppc program that communicates with asyncstream.
I found that the four bytes are converted to int32 with this:

B4X:
ArrayCopy(Q(),0,4,tbr(),0)
msgsize = bc.Int32FromBytes(tbr(),0)
where Q() is the big buffer that recieve everything, and tbr() is a small buffer to hold the four bytes.
byte 0 is the least byte in the four.
As can be understood - the int32 value is the size of the message.

For sending data I use this code (b4ppc):
B4X:
Sub send_msg(st As String)
Dim L As Integer
tbuf() = stream.StringToBytes(st)
L = ArrayLen(tbuf())
Dim buffer(4+L) As byte
tbs() = bc.Int32ToBytes(L)
ArrayCopy(tbs(),0,4,buffer(),0)
ArrayCopy(tbuf(),0,L,buffer(),4)
stream.WriteBytes(buffer())
End Sub
 
Last edited:

dddvvv

Member
Licensed User
Longtime User
Thanks for the quick reply.

My problem is that im trying to receive bytes /string from a microcontroller, not send bytes. (At least, not yet). Still having same issues. App force closes, since im not sending prefix bytes the right way.

How should I send them from the microcontroller? Hex, dec, ascii?
Thanks
 

derez

Expert
Licensed User
Longtime User
My answer give both ways - send and recieve. The Prefix is 4 bytes which form an int32 (each byte is 8 bits, the least significant byte is the first in the four).
 

rhouri

New Member
Licensed User
Longtime User
AsyncStream always not initialized

I'm having a problem with AsyncStreams. IsInitialized always returns false.
I tried the flyingbag example above and it does the same thing.
Any pointers to what the problem might be?
Thanks.
 

rhouri

New Member
Licensed User
Longtime User
I am running the exact program that was posted by flyingbag earlier in the posts.
I also have this code in a class which also fails. This one connects to a different server. The connection in both cases seems to be successful.
Thx



B4X:
'Class module
Sub Class_Globals
   Dim AStreams As AsyncStreams
   Dim TCPSocket As Socket
   Dim TCPAddress As String
   Dim TCPPort As Int
   Dim TCPDelay As Int
   
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize (ipAddress As String, port As Int, wait As Int)
   TCPAddress =ipAddress
   TCPPort = port
   TCPDelay =wait
    TCPSocket.Initialize("TCPSocket")
    TCPSocket.Connect(TCPAddress , TCPPort, TCPDelay)
   
End Sub

Public Sub TCPSocket_Connected (Successful As Boolean)
    If Successful = False Then
        ToastMessageShow("Connection Failed",False)
    End If
   AStreams.Initialize  (TCPSocket.InputStream,TCPSocket.OutputStream, "AStreams")
End Sub

Sub AStreams_Error
    ToastMessageShow(LastException.Message, True)
End Sub

Sub AStreams_NewData (Buffer() As Byte)
    Dim msg As String
    msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
    ToastMessageShow(msg, False)
    Log(msg)
End Sub

Public Sub communicate
   Dim s As String
    s="Hello"
   
    If AStreams.IsInitialized = False Then 
      ToastMessageShow("AStreams not Initialized", False)
         Return
   End If
   
    Dim buffer() As Byte
    buffer = s.GetBytes("UTF8")
    AStreams.Write(buffer)
    Log("Sending: " & s)
    
End Sub


Public Sub Close
   AStreams.Close
   TCPSocket.Close
End Sub
 

rhouri

New Member
Licensed User
Longtime User
After messing around a bit, I re installed the original Network test from flyingbag and it now works correctly. I'll have to review my own code for errors.
Thanks
 

qsrtech

Active Member
Licensed User
Longtime User
AsyncStreams with mulitple clients?

Hi I'm trying to setup a client/server service. I'm little perplexed on the use of asyncstreams. The question is how can you handle multiple clients with one stream/event? I don't see and property to determine which client is sending the data. Please Advise. Thanks!

EDIT: Never mind, I build a small class to handle multiple instances. Will post for others eventually.
 
Last edited:

kiki78

Active Member
Licensed User
Longtime User
Hello Erel,

I use AsyncStream to write data in file.
To optimize memory use, my byte array argument is reused between each call to "Write" or "Write2".
My question is : Is it safe ?
In other word, when "Write" come back, is array copied in temporary queue buffer, and so I can overwrite it ?

Regards
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…