Jump to content

TCP Client & UI Mulitple Data Display: Which Design Pattern(s) to use?


Recommended Posts

 

Hi,

 

I am making a determined effort to migrate a particular application of mine over the fence to OO, but I would like to be "herded" towards using the correct or proper design pattern(s).  This application of mine is a TCP Client app that allows the user to connect to one (1) test server as to display test data in various forms (i.e. tabular, time-histories, gauges, etc.) using a single tab control.  There can be up to ten (10) such Clients logged in at one time to the same Server.

 

I have read recently that several folks on NI & LAVA forums advise to move away from the tab control and to use sub panels instead.  Combine that with this web page's neat UI plugin example, I seem to be getting close to finding the proverbial "light switch" in the dark room, but ... it could be something else ....

 

Some notes:  I do have LabVIEW 2012 at my disposal.  The test server is written in C++.  Down the road a bit we may need to encrypt the XML stream so I may need to put a LabVIEW web service in between the Server and each Client using SSL - if that's a future design bit to note here but not as important as the basic environment or use case of a TCP Client that displays data via several types of displays - which the display types will only grow in the near future as we all have experienced.  So adding different displays should be as "easy" as possible.

 

Note: My question was originally posted here, but I was advised to post it here on LAVA for a more experienced architect to respond.

 

Thank you very much in advance !!!

 

CS

 

Edited by CommonSense
Link to comment

You're a bit vague, so I'm gonna make as good of a recomendation as I can. It seems like this will be a really slick object hierarchy that will really help you out in the long run. I'm making 1 big assumption:

That the TCP connection is opened at the beginning of the Manager class' lifetime (see below for class description) and closed at the end of the Manager class' life.

 

note: when i talk about "tabs" i'm actually talking about changing the active VI in the sub panel.

 

There are two main components in this implementation: An overall Manager class (the Top Level VI would belong to this class) and a set Clients.

 

The Manager class would be responsible for opening the TCP connection, and passing that connection off to to the active Client. He will also create the "Stop" user event ref, and be the one generating events on it.

 

Next, I propose you have a parent class called Client. This will handle all (or almost all) of the house keeping type tasks in private static methods. From what you've told me, here are the methods and access scopes I'd have for this class:
 

Public Static:
Run Client: This is the main entry point for the client. When the user changes "tabs", this is the VI that will be run. It will have an input of the TCP connection, a reference to the Sub panel and a "Stop" user event ref. All this VI should do is store the Active Connection it it's private data and then call the Insert And Run UI.vi with the sub panel ref and user event ref.

 

Protected Static:

Query Data: This should send a TCP string to the server to get the data. You do not want to make this dynamic dispatch. It's function is to generate a query string to send over TCP, wait for a response, and parse the response. It's supposed to handle the lower level stuff. The real question mark here is how do you generate the query string. It may be the case that they all have the same query string. This would be the easy case, then all you have to do is hardcode (or make a config paramter, whatever normal tricks you'd use) the query string. If they're not all the same, then you'll have to use the Generate Query String.vi method described below. Again, the goal of this function is to handle the writing/reading from the TCP connection. This will keep you from having to expose the active connection reference via an accessor VI, and more importantly, keep you from having to copy/paste code.

 

Protected Dynamic:
Insert and Run UI: This is an abstract VI. It should have an Input of the sub panel reference and user event ref. This is where all of your children will implement their UI. Each child should insert itself in the subpanel reference, then run it's UI logic. Make sure your child registers for the Stop User event ref and stop your UI when needed.

Generate Query String: (optional) This is an abstract VI. Each child instance should override this VI and output a string that will be sent over the TCP Write buffer.

 

OK, now that we have the parent all setup, all that we need to do is create children of the Client class for each "tab" you want. The only VI that they'll need to override is the Insert And Run UI, and possibly the Generate Query String. You'll write your UI pretty much as you'd normally would any other sub panel VI. The only extra thing you need to know is that you now have a built in Query Data VI that will auto-magically query the server and get back the data for you. Call this VI whenever you need to update the data. 

 

If you need to add a new type of UI in the future, then just create a new child class and override the one VI. You'll only ever need to mess with the specifics of TCP and stuff the one time (when you're writing the parent class)

 

Let me know your thoughts/question.

Link to comment

QueueYueue,

 

Thank you for taking the time to formulate a design framework per my, yes, vague requirements/use case. 

 

Before I begin to digest the class structure, I'd like to say more about the TCP client use case:

 

-Connection Use Case:

 

1.) When the client application starts up, it is not connected to a (the) Server.  When the operator decides to connect to a certain Server, they must enter the IP address, the Port, a configuration alphanumeric value, and another optional configuration piece of information.

 

2.) When the client connects to the server, the server first sends a list of the available data channels, plus channel attribute information.

 

3.) There may be several test servers that are running concurrently in different labs, but the client can only connect to one Server stream at a time. 

 

3.) When the tcp client operator disconnects from the Server, they'd like to still look at the data on the display (tabular or time history) and not have it go away until they close the program.  Sometimes, the Server has to go down for h/w changes, then come back up in 10 minutes to 2 hours and while this is happening, the test engineer may need to still analyze the data that was acquired and streamed up until that time.

 

Note: The Server type is a non-LabVIEW written program that is also a data acquisition system with a separate module that handles the Server-Client connects / disconnects and the streaming of data along with stream status commands in certain XML tags.  The Server hardware is usually a Win7 Dell precision desktop PC.

 

-Current LabVIEW Client Design w/ single Tab Control:

 

The tab control is designed to have (for example):

1.) A maximum of five (5) pages that display tabular data (2 columns, 25 rows each).

2.) A maximum of five (5) pages that display time history data (Qty=1 XY chart, with up to 10 channel traces per chart)

 

When the TCP Client starts up, it reads a text file that says how many of each type of tabular and XY pages the operator has configured, the name of the tab page, with the associated channels and attributes on each page that he/she would like to monitor.  The operator can edit this text file only via a deparate dialog / vi program that opens up from the menu on the Main vi. 

 

Note #1: The time history data is handled via a single LV2 style global and not with the XY graph.  I pre-allocate x amount of space at startup. 

 

Note #2: The current list of customers that are using the tcp client are looking at data that is acquired at 1 to 5 Hz, for anywhere from 30 minutes to 24 hours. 

 

The above use case information I was hanging on to until / if someone responded to my OO design query.  From what little I've read of your original design thoughts, I'm pretty sure that most of it still can be used with some modifications.

 

I've probably have gone now from vague to overload of requirements!

 

Thank you again,

 

CS

Link to comment

QueueYueue,

 

One more clarification / point per a paragraph I wrote above;

 

"When the TCP Client starts up, it reads a text file that says how many of each type of tabular and XY pages the operator has configured, the name of the tab page, with the associated channels and attributes on each page that he/she would like to monitor.  The operator can edit this text file only via a deparate dialog / vi program that opens up from the menu on the Main vi. "

 

I meant to say that when the tcp client starts-up, it reads a text file as to how many of the maximum amount of tab pages are displayed (not hidden).

 

With the OO eventual design, the new tcp client application will still read a text file to the quantity and type of test pages that are of interest to the operator. Maybe after reading the text (*.ini) file at start-up, the Main vi has the available data displays that he/she can select from a menu list via the menu bar above.  I am assuming now from the old/current design that they can only show one data display at a time (i.e. one subpanel).  A new and somehwta more complicated design may allow the operator to show several data displays at one time that are separately spawned / re-sizable Windows? 

 

Anyway, thank you again and I am now returning now to read & properly digest your original post,

 

CS

Link to comment

I'm pretty sure that what I originally suggested would still work even with the more specific details.

 

Morel of the story: you want to keep all the TCP communication in the parent class, and then your child classes will be the ones to decide how to display/parse this data.

 

Your INI file would would probably be used to build an array. The array contents would be instances of the children classes.

 

If you want to do the "Several Data Displays at one time" Actors would be a pretty good fit. There is a bit of a learning curve, but basically it'd take care of a lot of the asynchronously spawning things for you. Don't use Actor Framework to try to teach yourself OO though. Learn OO first, then start to look into actors.

Link to comment

You should watch Trevor's Presentation that is stickied on this board, you should look at the built in examples, and then you should develope your own projects using OO principals. After you have some OO experience, and a decent understanding of how OO things work, you should take a look at the actor framework.

Link to comment

QueueYueue,

 

I've watched Trevor's and AQ's presentations, and have built some basic OO code and now know quite a bit more than I did, but this is a continuous learning process of course. One other question to you is that while I am looking at and trying to continue the design process that you suggested, what design pattern(s) that have been mentioned here on LAVA and on the NI website, is closest to your suggestion?  This will greatly help my understanding of the design implementation process - at least for this particular use case.

 

I have been reading the forums on the various pro's and con's of the current version of AF, versus say MessagePump and Lapdog, and I am leaning toward Lapdog a little as I would like not to be limited in the kind of customizations down the road.

Just my 0.02$ at this point.

 

Thank you,

 

CS

Link to comment

There is a difference between frameworks and design patterns. You seem to be asking me for a name of a design pattern, then you go on to talk about actor framework and such. These are two separate things.

 

In terms of design patterns, honestly, I don't know patterns may have suggested. I've read up on the design patterns in the past and implement them as needed. Usually you need to mix and match a bunch of the formal design patterns to implement your solution.

 

Here are a bunch of design patterns: https://decibel.ni.com/content/docs/DOC-2875

 

From memory about the solution I proposed, you'd probably use the following design patters: Template Method and Factory Patter.

 

I'm trying to get at 2 main points here:

1. Frameworks and Design patterns are not the same thing.

2. You don't pick 1 design pattern. They are tools to help solve your problem. Use them as needed.

 

Side note: I'm not a fan of the OO Plugin Framework. I don't think there is a good way to actually deploy these solutions.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.