Buffer SEND_COMMAND/STRING between virtuals?
nicholasjames
Posts: 154
It's common practice, if not a necessity, to buffer any string from an external serial or IP device. I was just working on a module when I found myself absent-mindedly setting up buffering for strings coming in from a virtual device on another master when I thought, "That's silly, there's NEVER a need to buffer these strings." Of course those hyperboles always sends a little red flag up in my mind. Never is never never.
Though I've never experienced an issue sending commands or strings between virtual devices, multi-master or otherwise, I'm curious if anyone has ever found it beneficial. Have you ever had a virtual to virtual command or string arrive in 2 parts? If so, when and why?
Thanks!
Though I've never experienced an issue sending commands or strings between virtual devices, multi-master or otherwise, I'm curious if anyone has ever found it beneficial. Have you ever had a virtual to virtual command or string arrive in 2 parts? If so, when and why?
Thanks!
0
Comments
For everything else, I make a buffer and queue so I can tweak the timing and performance.
The simple answer is no, only one data event is generated for send_command and send_string between the program and virtual devices.
The more complete answer is that the text parameter for data events has a fixed size and if you try sending more information in one send_string/send_command than Data.Text can make available to the data event, the information you receive will be truncated. I couldn't find documented reference to this size (I'm sure its in the NetLinx programmers guide or similar) but it is likely to be 2048 characters, as implied by NetLinx.axi below:
If you need to send bulk data using send_command/string to a virtual device you'll need to chop it up and send it in chunks.
On the odd occasions when I need to do this I use an ASCII STX character to mark the start of the bulk data and an ETX character to denote the end of the data so that whatever is using the information knows the transmission has completed and processing can begin.
As far as the max is concerned, you make a good point about the 2048 limit. If you look at device status: it lists MaxStringLen and MaxCommandLen for the virutal (33001:1) at 2000 but the serial port (5001:1) at only 64. Grant it the 2000 is 48 bytes shorter than Netlinx's purported 2048, but why be greedy...
Of course then there's the data.text limit of 2048 that Auser just mentioned and if the string is longer it get's truncated unless you handle breaking up the string in code and sending it in chunks in which case you'll have multiple data.text's before you receive the complete string.
Possibly with M2M you might get a 2 part data.text of a string under the data.text limit if the string is over 1500 bytes since the M2M communicate via ethernet and the masters should handle the ethernet packets and transmit no more thant the max MTU (ethernet = 1500) at a time but it will send the complete string. The truncating occurs on the receive side due the data.text limit.
Check out technote 886:
Something I've been doing lately if I need to share large chunks of data between modules is to use a shared variable. For example, for my weather module, I do a string_to_variable, and then pulse a channel to tell the responding module that it's ready to be converted to a structure.
Why, or, when is this helpful? You can't pass structures to modules, but you can pass variables - and they're all passed by reference. So, within my main code I would have a large char var (ex. volatile char s_enc[65535]) and pass that to both a comm and to the ui modules. The comm module populates a stack_var of the structure, then encodes it to the string, pulses a channel at which point the UI module takes that same s_enc variable that was pass in as reference, and uses string_to_variable() to populate a global structure. I see no reason why if you're transferring large forms of data, that you couldn't use the same transfer mechanism.
on the recceiving end (main)
in this snippet I'm send my structure back to the main code hence the "send_string". I use "1" as my first byte so in the main code I can take that byte and determine if the remaing string needs to be decoded (string to var).
If I have a large attachement to pass back I just write that to file and pass the file name back and if the .cFile has a value the main will know there's an attachment to retrieve. The file name is generic to the module so module instance 1 would be SITREP_Mod_1.txt.