The problem is that at this time, the MCU can’t handle more than one command at the same time, it only pays attention to the first one, so I need to fire these off quickly, but separately.
I could pause between each one, but I don’t really like doing that if I don’t have to. I have tried calling TCPSocket.flush after each of the above commands but the result is that it works for the first one, but not subsequent responses. That is:
>[GetDesktopServerIP]
[STATUS|Command Successful, Server IP address = 192.168.1.221]
>[GetDesktopServerPort][GetClearCoreIP][GetClearCorePort][GetHearbeatInterval]
[STATUS|Command Successful|Port ID=8889]
Even though the code was modified to flush after each SendCommand call, it looks like it only worked for the first command [GetDesktopServerIP], and the next three got bunched together.
What’s a surefire way to make sure these commands all go out separately? is my only option to build in a pause between each one?
None in xojo. This is the way TCP is designed and Xojo uses the OS implementation without offering a way to tune how packets are treated, so unles your pause is in the magnitud of seconds to be sure, the commands will be cached and sent in the same packet. Yo will have to implement a parser in the other end, add all the bytes to a queue, then process each command in FIFO. For thos use cases I use an MQTT implementation
**This is correct. In the DataAvailable event, you should be breaking the string apart into an array by the delimiters, and looping thru the array to handle each command. This will keep your commands in sequential order and ensure none get dropped…
We are using [ and ] to indicate the start and end of discrete commands. Right now, the firmware is not set up to accept multiple commands per incoming message. That is, it’s expecting [GetDesktopServerIP] and [GetClearCorePort] to be in independent messages. It’s not expecting [GetDesktopServerIP][GetClearCorePort]. In this second case, it’s throwing out everything after the first “]” – it is not ideal but what we have at the moment.
I’m talking to our firmware developer about parsing the incoming message to handle multiple commands at once. In our testing of individual commands it’s been fine, but now that we have multiple things going at the same time (such as automated pings to check that the MCU is still there), we’re finding that on the MCU side, some instructions are getting lost, because they’re getting piggybacked into the same message as another command.
You will need to parse the incoming data, for example
Var commands() as String = me.ReadAll.Split("]")
For i as integer = 0 to commands.lastrowindex
Var currentCommand as String = commands(i).nthfield("[",2).trim
//Now use “currentCommand” to process the command. The for/next loop will automatically move-on to the next command and process it.
next
**TCPSocket does not break up commands, it’s a perpetually connected datastream. It’s the equivalent of pouring marbles into a funnel…you’ll need to catch each “marble” that falls thru the funnel and do something with it. Each marble that falls into the funnel though, will remain in the order it’s sent… the process should be really easy to implement.
thanks - but I’m not talking about receiving commands in Xojo - we are sending from Xojo to an external device. The issue is on the device and how it is processing the messages it’s receiving from our Xojo application.
Our firmware developer is about to leave on a month-long trip next week so we’re looking for a solution on the Xojo side but it doesn’t sound like that’s an option. We can’t wait seconds between commands.
In some cases, commands get responses, but not all. Or at least, not all immediately. For example, I can send commands to move two linear stages into certain positions as separate commands, and the MCU will handle them simultaneously. It may take 20 seconds for each one to get where it’s going. But there’s other stuff that needs to be done in the mean time, so we can’t make everything 100% sequential or we’ll be waiting all day for things to finish before moving on to the next thing.
The bigger issue though, is that there are some commands being sent automatically. For example, there is a periodic “ping” we send to the MCU to make sure it’s still there. If my application happens to send a message at the same time as one of these pings, it goes out as something like:
The result in the first case that the command to set the server port is piggybacked on the automated message, and is subsequently lost when it’s received on the MCU. The second case works as expected.
So what I need to do is force the outgoing message to be split on a per-command basis in the short term, and in the long term, the MCU needs to handle the situation in which multiple commands come in at once.
I’m not sure I see how that would help. I mean, maybe for the heartbeat checks, but there are other things that can happen concurrently that would be out of my control so while it might fix that specific issue, I can see other cases where multiple commands get sent to the MCU at once. There are quite literally, a lot of moving parts on this machine!
the Firmware developer says this is a major “enhancement”, which is disappointing, because he’s about to leave the country for a month, and we’re already months behind schedule with this project (not because of him).
I can build brief delays into the code if that helps, but not seconds. Are the Xojo docs incorrect in stating that (regarding Flush):
This function can be useful in point-to-point communication over sockets and similar connections: To optimize for transmission performance, some types of output streams try to collect small pieces of written data into one larger piece for sending instead of sending each piece out individually. By calling Flush, the data collection is stopped and the data is sent without further delay, reducing latency.
It doesn’t really seem to work as described. or when it says “the data is sent…” does that mean Xojo is sending the data along to the OS TCP stack, and we have to wait there for it to send?
I haven’t but I’ll give that a try after lunch. sounds similar in principal to the outgoing command buffer that Ivan is suggesting so I’ll have to see which is faster.
As of right now, I’ve determined that adding in delays requires a delay of 400ms after each command, to reliably separate them. That’s unacceptable as there are times when we will need to send 15-20 commands per second.
I don’t see any way of hitting those speeds without the firmware being modified.
Adding arbitrary delays is definitively not the way to go.
Ideally, your firmware should handle each command separately (loop thru all commands surrounded by using NthField) so even with commands coming at the same time, it can handle all of them.
If this is for starting up or so… Why not ask the dev to push something like “[GetCompleteConfig]” ?
Normally in streams or command based packaging you’d have something like is being suggested already, a packet has a strart/end when it’s detected at the device level it’s queued (or buffered) and then processed asap the responses are basicly packets too with start/end.
For now it seems there is no issue? From your quote:
You get the correct sequence, and you have all of them back. The issue is at the device level e.g. it’s sending the echo back and then it’s processing it which is too late. Your device may be behaving better if:
It consumes the data as a buffer
It reads the first from the buffer
write back an echo for the command
process the command
wite back the output of them command
Repeast from step 2 (until buffer is empty, then go to 1).
Now you should get the correct sequence in xojo.
Getting an echo directly with everything you have send is probably not expected on a high end machine (pc).
If you need a way to fix this from the xojo side i’d be sending a command “[GetDesktopServerIP]”, set a string LastCommand = “[GetDesktopServerIP]” in dataavailable check for the echo. if the echo is there, then your dataavailable is waiting for it’s status command when that’s received set LastCommand = “” now your queue sends out the next one. There is not really a timer required but on disconnect and connect/reset etc. i’d be setting lastCommand = “” and clear the buffer e.g. Call Sock.ReadAll
In the case a response is not expected just set lastCommand = “”
Sounds like you need to send one command and then wait for an ACK of that command (i.e., confirmation of its receipt) before proceeding to send the next one. You could include a number string (incremented for each new command sent) as part of the string and the ACK.