03-06-2010 01:30 PM
I have a fairly involved messaging utility (known as the RCTx) that I need to grow, and I'm wondering if/how labview OO can be used to accomplish this. Here is what I currently have: I have a producer-consumer loop that accepts user input from the many controls on its many front panels. These user inputs are converted to standardized messages, placed in a queue, and processed. These messages eventually then get sent (http, via secure ethernet (TLSv1)) to a radio (UUT). I then listen for a response (comes back in XML), process it, and display results on appropriate HMI panel. This method of use is primarily for the engineer in the lab talking directly from the RCTs to the radio. At the same time, there is another producer loop that is listening for changes to a shared variable (written to by a client). When something comes into that SV, that message is placed into the same queue as above, and sent on to the radio as before. The response, however, is written to a different shared variable that the client is listening to. This second method is how we plan to remotely communicate with the radio in a production environment. Although one method or the other will be used, both are currently capable of operating in the same session. A little more about some of the inner workings of this monster - I use a web browser (IWebBrowser2), and the Navigate2 (ActiveX) widgets to establish the secure link to the radio, and to POST/GET the messages. I originally designed the RCTx with the help of the State Diagram Toolkit. That has been a real help in being able to visualize what I'm trying to do, and to create the initial base software template. Also, I have all my source code (LabVIEW 2009) in a LabVIEW project, and I used the Build Specification to create an exe of the RCTx.
At the time I created the (one) RCTx, it was thought that one client would want to talk to one radio through the RCTx. Now, however, we've received a requirement where the client may need to communicate with up to 16 radios (pretty much simultaneously) that are in an environmental chamber. There are just too many controls, logic, etc to even phathom duplicating all of it sixteen times, and I'm not sure if/how multiple instances of my RCTx EXE could be brought up, and how each instance would manage which Shared variable would need. So, I started thinking about using an object-oriented approach. As I've never done this before in LV, I read a number of white papers, and discussions. It all sounds promising, but given all the things I have going on in the RCTx, I really have no idea where to begin, or if OO is the best way to proceed. As I mentioned, I have a Rx and Tx shared variable that the client and RCTx share. It seems like I would need to create 32 SVs, or dynamically create them (not sure if that's possible). Anyway, I was hoping someone could give me sanity check on whether OO would be feasible and what obstacles I may need to overcome given the types of controls and communications I'm trying to use.
03-06-2010 04:03 PM
Mrbean,
Regarding 16 radios and idea of duplicating controls 16 times: with OO design you only need a single set of controls, unless of course you want to show more than one set on a screen at any given time.
Here is what you do:
Create a single set of controls that is common to all radios
Get a reference to each control, bundle all references and put the cluster either into Global variable or into an object with get/set methods
Create an array for a radio count (16) element where each element is a cluster filled with all radio controls
Make an object with get/set/update methods for an array of radio control values
Initialize the array either to some predefined values or have it to read values from a config file
Update GUI radio controls by using value from the array and setting Controls via references/property nodes
Have some method for scrolling through radios (scroll bar, PgUp, PgDown buttons) and by doing this index to an appropriate element in array and update your GUI
03-07-2010 01:40 AM
Your post is lacking in some important details, but in general I would say that if your system is working you should not make considerable changes to it, unless you plan on maintaining or extending it a lot going forward.
One thing that's not clear is what's on the other side of those shared variables, but I would suggest getting rid of them and using TCP to directly communicate with whatever's on the other side, using your own simple ASCII protocol. There are numerous examples around (from the example finder to examples in the components board). When you open a direct channel you have the advantage of being able to have N clients, but you would need to change some of your archiecture for this as well.
As for having multiple instance of the EXE, you can do this by manually creating copies of the EXE or adding the lines AllowMultipleInstances=TRUE to the app's INI file. The main thing to look out for is shared resources such as the SV or serial ports and settings which need to be changed (such as the IP address for each UUT).
03-07-2010 04:24 PM
I found an example in the LabVIEW2009/examples/comm/TCPIP.llb - it's the multiple connections server / client(s) example. It seems like if I can modify my server to grow TCP connections like they do there, I can have as many radios connect to the RCTx, correct? I'm having trouble understanding a couple of items in those examples, though.
In the client while loop, the comment says "Read the date and time data being sent by the Date & Time Server.vi. First TCP Read gathers bytes to read and passes it to the second TCP read which outputs the date & time string." I really don't understand how the two TCP reads do what they say it does. If I replace the two with just one TCP read and tell it to read 28 bytes (instead of two reads of 4 bytes), then it reads the date/time, but it's behavior is not exactly like the two-read method, but it's close (although the time/date are output, the data in the indicator is skewed slightly). Also, when I probe the first TCP Read output, I see " x" (actually, there is a little box where the x is, but I couldn't reproduce it here), the the second TCP read contains all the time/date info. I don't really see what the purpose of the first read was.
I'm assuming I could just replace the date/time info with my data. I was planning on making my data packets all the same size so as to simplify the data server client interaction. Thoughts?
03-08-2010 01:06 AM
I agree that the documentation is not good enough in this example, especially as this particular point is quite critical.
If you look at how the server constructs the data, this becomes clearer. In TCP comm, you have no way of knowing in advanced how much data is available from the other side, so you have to ask for "enough". This example, and other implementations, works around this by checking the length of the data in the sender (the StrLen in the server) and sending that before the actual data.
Since the length of this header is known (it's an I32, so it's always 4 bytes), you now know that you can read 4 bytes, convert them to an I32 (thus no longer seeing the gibberish you're seeing in the probe) and use that to know how many bytes you need to read now. This is what the example shows. This should also help explain why the data looked wrong - the server was sending length+data, but you were interpreting all of it as data. You should have removed the first 4 bytes first.
03-08-2010 07:29 AM
03-08-2010 08:00 AM
mrbean wrote:
Is there a way to know that, or is that determined by an ID field I'd have to pass around in the message?
You can either include an ID in the message, or have the server maintain a lookup table, so that it remembers which client is associated with each connection. You should note that in most cases, the server waits for requests from the clients, so this is less of an issue.
03-08-2010 08:08 AM
Just an idea...
Could you use unique TCP/IP ports for each clone of your app to replace the SV?
Re:"replacing functional decomposition design with object oriented"
You don't have to dump everything to go with LVOOP. You can shift to LVOOP gradually if that fit your needs better. Either way, I recomend getting a good OOp design in place on paper ahead of time. This design becomes the "goal" with your current app the starting point. Look to those parts that present the major challenges at the moment and convert those parts to LVOOP.
Just sharing ideas,
Ben
03-08-2010 08:39 AM
Concerning the unique ports...in the Multiple Connections example, they just picked port 6341. I'm not sure how they knew that was available. How do you just dynamically request a random port?
On the other side of the RCTx I have a similar issue, where I currently have ONE browser that establishes the TLSv1 connection with the radio. For each TCP connection the client establishes with the RCTx, I'll need a browser connection to a radio (different IP addr for each). I'm wondering if I ultimately want to get to where the RCTx is a factory, where, for each radio a client wants to test, the RCTx factory returns an object that exposes all the interfaces it needs to the client.
03-08-2010 08:55 AM
mrbean wrote:Concerning the unique ports...in the Multiple Connections example, they just picked port 6341. I'm not sure how they knew that was available. How do you just dynamically request a random port?
On the other side of the RCTx I have a similar issue, where I currently have ONE browser that establishes the TLSv1 connection with the radio. For each TCP connection the client establishes with the RCTx, I'll need a browser connection to a radio (different IP addr for each). I'm wondering if I ultimately want to get to where the RCTx is a factory, where, for each radio a client wants to test, the RCTx factory returns an object that exposes all the interfaces it needs to the client.
Take a look at this post. I just answered that question a couple of days ago. As for Ben's suggestion of using a unique port for eachdeviceI would not recommend that approach. Unless you know exactly how many radios you will have and never anticipate adding more a singleprt solution is better since any radio added to the system will know which port to use for the server. You only need to create a single listener for your server. If you use multiple ports you will need a listener for each and every port that you use. I would use a simple registration packet when you first connect to the server. This packet would contain the device ID and using this you can direct messages to a single device.