DATA.TEXT and IP Messages
TurnipTruck
Posts: 1,485
Greetings,
We all know that DATA.TEXT can return incomplete serial messages. I have always assumed that the same rules apply to IP messages and parsed accordingly.
I have been working with several Telnet IP-communicating devices lately and have noticed that each trigger of the string data_events returns a complete message.
What has been others' experiences with incoming IP strings?
Thanks.
We all know that DATA.TEXT can return incomplete serial messages. I have always assumed that the same rules apply to IP messages and parsed accordingly.
I have been working with several Telnet IP-communicating devices lately and have noticed that each trigger of the string data_events returns a complete message.
What has been others' experiences with incoming IP strings?
Thanks.
0
Comments
For IP comm my general rule is to cache all IP messages and not rely on the Data_event to trigger any parsing code. I've just found that its best to be patient and wait for the whole message. Since a lot of IP stuff gets broken up between packets. So, I just keep adding IP messages to a cache/buffer and look for terminators that then act as the event that triggers the parsing. I also then peel off the data into another buffer. That's just how I roll...
I think like most of us if it ain't internal AMX comms allways append to a local, global or created buffer but if the returns are large like when web scrapping it's best to store the rx data in your var but trigger (find_string) on the data.text which limits the string you have to search through to a max of 1500 bytes of the latest data event.
Although you normally get one complete packet at a time with IP, DATA.TEXT has a fixed size of 2048 bytes. So if your packet length exceed that, you will get multiple events with 2048 bytes at a time until the packet response has totally been reported to the data event.
I always try to use create_buffers for RS232 and IP communication, and parse them inside the data_events.
Jeff
http://en.wikipedia.org/wiki/Ethernet_frame
http://en.wikipedia.org/wiki/Jumbo_frame
Now, what I've done in the past, I would FIND_STRING on a common byte like $0D and then after I was finished with the string, REMOVE_STRING to clear its contents. Using the code above with this device, I am unable to look for a byte to say its the complete my string. If I look for a $01, in one response it's at the beginning of the string, thus ignoring the rest of the strings; for another response it's at the end of the string. The response that has 4 bytes, I am looking at the last two bytes (and in this example) to get my lamp hours.
p.s. the reason I concatenated my incoming string is because a straight DATA.TEXT would only read one byte at a time, over-writing the previous value, thus not allowing me to build the full string.
I understand there is no delimeter to key your parsing on but usually there are other known factors to work with. Sometimes you have to base your parsing on the the string type you just sent. Command returns often differ from query returns so you might have to check the command last sent to determine how to parse the string received. Of course you could be SOL if the device provides unsolicited responses but even then you can key on the first couple of bytes to determine the type of message you're dealing with and then if they're nice they'll provide a length byte in a fixed positon relative to the start byte which may vary.
If we couuld look at the syntax we might be able to help you find a pattern.
I've attached the protocol for the projector. Below is a sample of my code.
The way I have dealt with this type of device is to first separate the code for it into a module. The commands are sent to the module from the main program like many of the old-style AMX modules. So to turn the projector on, I send a command to the virtual device of 'POWER=1".
Within the module, I set up a queuing system where a command is received from the main program and then added to the queue. For a case like this, I would add a string to the front of the actual "BEEF" command to tag the type of command that was being sent. For example, a power setting command would have something like 'PWR' in front of the command being written to the queue. A power status request would have something like "PR?" as the prefix. So you would prefix the commands with the type such as "INP" for input, "ASP" for aspect-ratio and "LM?" for a lamp hour request.
At the end of the standard device command I add my own end of command character. You need to look for a character that does not occur in the standard command structure. As an example, I may add a hex FF to the end of the command.
When you pull a command out of the queue, you use the $FF to delimit the REMOVE_STRING function call. At that point, you have the entire command with the 3-byte command type on the front of the command and the $FF at the back.
Remove the first three bytes and save them in a variable such as cCMD_SENT[] for the actual device's Data_Event. I use the LEFT_STRING to place the 3 bytes into a variable and then just use three GET_BUFFER_CHAR to remove them. Then I set the string length of the command to be one less than the actual length in order to strip off the $FF and do a SEND_STRING to the projector.
I generally set a timeout so that if I don't get a response back from the projector I can either resend or discard the command.
In the DATA_EVENT for the device, when I receive a string I look for the command type that I last issued in the cCMD_SENT variable. That lets me know how to pick apart the returned string to store the info that I need.
From there I send a response back to the device. So if I get a lamp time request i will send a string back to the main program from the module's virtual device that contains something like 'LAMPTIME=99'
Since I use the same basic command structure for all projectors, I can swap a projector with minimal changes to the main program.
Just create a select active or switch case based of the last string type sent. Plus you know the first byte will almost always be $00 unless the sting you sent is invalid or has errors.