Android Question Best way to get data packets from multiple systems

mscientist33

Active Member
Licensed User
I have a lxClv with a list of systems. I loop through that list and for each item in that list I send a "status" command. The system in return sends the status packet back to the tablet. The problem is it sends the next status command way to quick for the system to respond before it sends the status command for the next system. It seems the first response is still processing when the next status packet arrives so it never gets it. I can send the stats command individually all day long. I am using the Network library, a send socket on port 10001 and a receive socket on port 10002 along with the Received_PacketArrived sub. Is there a way to pause the iteration through the xClv until the responding packet is received or a way to queue the responses before processing to make that sub quicker? What is the best way to handle this?
 

teddybear

Active Member
Licensed User
Best way is posting code to show your process。for the asynchronous processing, you should create a mapping list to systems, after sending command, you may update corresponding item related to the system by mappping list in Received_PacketArrived sub
 
Upvote 0

Gandalf

Member
Licensed User
I would use MQTT for such task instead of sockets... But if responding systems don't support MQTT, I would create a List as global variable and add all responses there when they arrive. Then the sub which parse responses can take them one by one later from this List and remove after processing.
 
Upvote 0

emexes

Expert
Licensed User
I have a lxClv with a list of systems. I loop through that list and for each item in that list I send a "status" command. The system in return sends the status packet back to the tablet. ... What is the best way to handle this?

Can you include the system id in the responding packet? Then just continually loop through the list of systems, sending status commands to each system in turn at a reasonably constant rate, ie, set up a 10-to-1000 ms timer tick to send status command to next server in sequence.

On the receive side, when you receive a status response, update the status of whichever system id is specified in the response.

In your list of systems, you'll want either a timestamp of the last response received, or a flag that is set when you send the status command and cleared when you receive a response. Either of those will allow you to easily tell you when a system stops responding. The timestamp method is probably better, because you can specify the timeout period, vs the flag method timeout is tied to your request loop rate.
 
Upvote 0

mscientist33

Active Member
Licensed User
I do have the above working, but it is like it never gets the completed and goes through all of the for i=1 to 3 loop.

I need to just be able to loop through the xCLV and for each system do a "wait for" until the packet arrives (with a timeout) and when the timeout expires or the packet arrives go to the next item in the loop.
 
Upvote 0

emexes

Expert
Licensed User
I do have the above working, but it is like it never gets the completed and
Has any response packet ever been received? Is it only the first one, and the subsequent ones are somehow lost?

goes through all of the for i=1 to 3 loop.
Indices in B4X are usually zero-based, so perhaps that for loop should be: for i = 0 to 3 - 1

I need to just be able to loop through the xCLV and for each system do a "wait for" until the packet arrives
There are people on this forum who know "wait for" way better than me, so I will bow out here.
 
Upvote 0

teddybear

Active Member
Licensed User
I don't know what the IP's are, they are given out by a dhcp server AP. So they could be anything. I have found this code: https://www.b4x.com/android/forum/threads/udp-acknowledge-wait-for-with-timeout.89185/#post-564283 and I will see if this works for me.

How did you send status command to server as you said that you don't know what ips are?

I need to just be able to loop through the xCLV and for each system do a "wait for" until the packet arrives (with a timeout) and when the timeout expires or the packet arrives go to the next item in the loop.

For your question, wait for it is not necessary, as emexes said, you should create a list to map xCLV's item to Server's ip/host, like this:
0<->server1 ip/host
1<->server2 ip/host
.....
In Received_PacketArrived sub, you can get ip/response msg from udp response packet, then update xClv's item status by searching the list you created
 
Upvote 0

mscientist33

Active Member
Licensed User
My access point is the dhcp server so it is not controlled by the tablet or the systems or even a computer at all. This is a closed network. The only given is the SSID that the systems look for then the dhcp gives them an address. My tablet has no idea what the systems ip is. My systems DO however by the use of code and a bcd switch have an "ID". My app broadcast a status command which includes the ID of the system I want to control. All systems receive the packet, looks at the ID inside the packet. If it pertains to that system, does as it is commanded otherwise it disregards the packet.

I can send an status and get a response all day long but when I go through the list of ID's and send the command, it either tries to send to fast between each ID or it does have enough time to get a response before sending the next status command. I have sniffed the network and it appears that the command IS sent, just the response is lost as the other systems in the xCLV are sending their packets too.
 
Upvote 0

emexes

Expert
Licensed User
My app broadcast a status command which includes the ID of the system I want to control.
Does the response packet also include that same ID?

it either tries to send to fast between each ID or it does have enough time to get a response before sending the next status command.
Sounds like the universe is telling you to slow down. How quickly does a response usually come back? eg a few milliseconds, or a few hundred milliseconds, or more than a second?

A simple polling method is: when you receive a response, then send the next status command and set a timeout timer of duration say twice as long as the usual response time.

In fact, it might work better to have the timer tick handler send the next status command. If you want to send a status command earlier (because eg you just received the previous device's response), just reset the timer period to a small value eg 2 ms, and then the timer will trigger shortly after and send the next status command.

Also, does the BCD switch mention mean that you have at most 10 devices to monitor?

How often do the devices need to be monitored? Every 10 seconds? Once a second? Ten times a second?
 
Upvote 0

mscientist33

Active Member
Licensed User
Yes, the response packet does include the ID. I think the problem "IS" that it needs to slow down. That is why I was trying the "wait for" in the xCLV loop. That is where the command is sent. It would be nice if it could wait for a packet received (with a timeout of course) then move to the next one after the receive or the timeout.

The bcd switch just give the system its ID on bootup. Nothing special there. Actually, the system reads three bcd switches. I have up to 999 systems.

The system status is usually always sent manually. Getting back from a single systems works perfect, its the timing in the xCLV loop that I believe is giving me trouble.
 
Upvote 0

teddybear

Active Member
Licensed User
That is why I was trying the "wait for" in the xCLV loop. That is where the command is sent. It would be nice if it could wait for a packet received (with a timeout of course) then move to the next one after the receive or the timeout.
You don't need to wait for the response in the xCLV loop at all, you just do send status command to systems all. the job for updating xCLV item should be put into Received_PacketArrived sub, there you can update the corresponding xCLV item by ID from response packet.
 
Upvote 0

emexes

Expert
Licensed User
If the devices respond quickly eg within a few milliseconds, then simplest solution is to Sleep(a few few milliseconds) between sending the request and checking for a response.

If you are looking for continual "background" polling of all devices, then a timer that fires at whatever rate you want to check them (all) at is probably a better solution.
 
Upvote 0
Top