-
Posts
798 -
Joined
-
Last visited
-
Days Won
14
Content Type
Profiles
Forums
Downloads
Gallery
Posts posted by John Lokanis
-
-
Anyone have a good way of converting a variant tree into something displayable/log-able without writing some massive recursive function? (using 8.6.1, so no native recursion for me unless I use VI Server tricks)
I need to dump the status of my tree to a log file for debug purposes. The tree is just an empty variant with attributes that have attributes that have attributes...
thanks,
-John
-
I have had very good luck with DIGI port servers. We have many of these at facilities all over the world and they have worked flawlessly for us. The nice thing is, you can configure them so your LabVIEW code just connects over TCP/IP to their IP and the specific port that corresponds to the physical serial port on the unit. No need for any drivers on your machine. Of course, they also have a driver for virtual serial port support so existing apps can use them seamlessly.
I know they come in 2,4 8 and 16 port versions. I have used the 4 and 16 port versions my self. They even have a wireless version if you don't have network cabling to where your serial device is located.
You can remotely manage these via a web browser.
here are some links:
http://www.digi.com/products/serialservers/portserverts816.jsp#overview
http://www.digi.com/products/serialservers/portserverts.jsp#overview
good luck!
-
1
-
-
I think Brian's point was that the pinvoke method wraps up all the error handling, mem alloc and threading issues into a nice .net interface. Not sure as I have not used it yet and I am sure I will learn more as I do. I have called some Win32 stuff in the past and it can be non-trivial if you don't know what you are doing.
-
No, but they do have a pilot program for a web-based front end that uses other technology. If you join the pilot, perhaps you can convince them that HTML 5 is more appropriate.
Already tried that...
-
I think what it mainly give you are c# wrappers for Win32 calls that you can use to build a simple .NET assembly that you can then call from LV easily.
-
Here is a site that Brian Tyler (formerly of NI, now at MS) recommended for all LV Dev who need to call Win32 functions:
This site is a Wiki for how to use pinvoke from .NET to call the Win32 APIs. This is also a good ref for those of you who dapple in C#.
hope this helps someone...
-John
-
Too bad NI is not making a LV web front end that uses HTML5.
-
Also, to do this programmatically, you need to deal with many issues.
1. you cannot disable the control, because then the scroll bars will not work and the mouse scroll wheel will not work.
2. It does not matter if it is a control or indicator, because you will trap all the mouse down events and discard them anyways.
3. You must make sure the mouse down events you trap and process are 'in bounds' so you don't mess up clicks on the scroll bars.
4. You must process both shift and ctrl separately and mimic their normal behaviors.
5. Due to #4 you must save the last clicked row in the shift, ctrl and no modifier cases for use in the shift case. This is because the selection for the shift case is always between the clicked row and the last clicked row.
6. For the ctrl case, you must deal with both the add row and delete row if the row is already selected.
7. If your MCLB is set to 1 or more items, you must not allow all rows to be deselected in the ctrl case.
8. For the shift case, you must build an array of indexes for all value between the selected row and the last clicked row.
So, this is not trivial. And a real PITA to have to do just because you don't have access to the 'last clicked row' value of the native control.
-
Yes, but I still contend this is a bug. There is data in there that is not available to the programmer. (the last clicked on row) Why? Is there no way to set this in code?
-
Here are some VIs demoing the issue.
When the prompt VI appears, hold down shift and click on any row other than 0 or the selected row.
You will see the selection set to the rows from your clicked row to row 0. The programmatically selected row will be ignored.
Now, click on any other row (other than 0 or your programmatically selected row.)
Close the prompt VI.
Run the calling VI open the VI again.
This time hold shift and select any row other than row 0, the programmatically selected row or the last selected row before you closed the VI.
You will see the selection set to the row between your newly clicked row and the row you last clicked on before closing the VI the last time.
Confirmed in both 8.6.1 and 2009.
-
In a multi column list box, you can select multiple items (if you set the list boxtox an array datatype) by clicking on items while holding down CTRL or by clicking on a first item and then holding down shift and selecting the last item in a range you wish to select.
I want to display a listbox of data and allow the user to select items in this way. BUT, I want to preselect the first item for them. So, all they would need to do is hold down shift and select the last item to choose a range. Unfortunately, I cannot get this to work. Here is what I have tried:
I have set the value of the control to an array containing only the first selected row’s element (even using value signaling).
I have set the edit position to the first selected row.
I have set the ActiveCell to the first selected row.
All of this is done before the user is allowed to select anything.
But, the issue remains, the user cannot select a range without first physically selecting the starting row, even if that row has already been programmatically selected by the application. Instead, when the VI first opens, the ‘first row’ is set to row 0. So, holding shift and selecting a row selects all rows from the top row to the clicked row.
Even weirder, if the user selects a new ‘first row’ when using the VI, whatever the user selects as this first row is remembered each time the VI is called, even if I have changed all the data being displayed and have ‘selected’ a different row programmatically.
Anyone know a way to get this to work as desired?
Thanks,
-John
-
thanks guys. I think the short term fix is to use the tick counter. the long term fix might involve some of these more complex signaling techniques.
-
Ok. I see where you are going with this. I am not sure this would fit into my application. In my case, I have a consumer loop that is monitoring a feed from a producer that enqueues data from an external source. The consumer will issue an exit condition in the following cases:
- The external source reports it is done.
- There is an error (of any kind).
- The user presses abort in the UI.
- The maximum time is exceeded.
The consumer loop executes at least once a second to check the time. It will execute faster if there is data to process from the producer.
So, I actually want some polling of the time. IF I implement some sort of external event structure, I imagine I would want to simply let it run until timeout and then assert some sort of signal that the consumer could monitor. I would then also need the event structure to have a user event that allows the consumer to abort it if a different exit condition occurs.
This does seem a lot more complex than a simple polling style timeout check. But if it is the only way to make this more reliable I may have to try it.
- The external source reports it is done.
-
So, in your example, the tick counter is safe to use, even through a rollover, as long as the timeout limit is less than 25 days. Correct?
-
I know that we had trouble with tick count rollover back in LV4.1. Maybe I was just so burned by that case that I have been unwilling to give it another try.
Can anyone confirm that rollover is a non-issue with Tick Count?
-
I have some processes where I need to time an external device and issue a timeout if that device fails to respond in a certain amount of time. These timeouts can be in seconds or minutes or even longer in some rare cases.
I have accomplished this in the past by getting a time stamp outside the loop that monitors the external device and then in each iteration of the loop I get another time stamp, subtract the original time stamp and then take action on the result if it exceeds the limit.
I have used the time stamp instead of the tick counter because I am concerned that the tick counter can roll over and cause a problem with my elapsed time calculation.
The problem is, once in a while, the clock on my machine is 'adjusted' by the network time service to bring it back in line. If this happens while the loop is running, the time stamp calculation will be thrown off and my code will think the external device has not responded in the allotted time when in reality it still has more time left to finish. When this happens, I issue a timeout condition that is not real.
So, anyone have a suggestion for how to solve this or at least make it more reliable? Our IT guys are not willing to disable the NTP service on my machine to prevent these adjustments so I need to find another way.
-John
-
1) Buy LabVIEW 8.6 in October 2008 (get one year of SSP)
2) Get all 8.6 bug and maintenance releases.
3) Under SSP, you upgrade to LV2009 when NI releases it in August 2009.
4) You do not renew SSP in October 2009
5) You still get the 2009f2 and f3 fixes, but not SP1 as your SSP has expired
If this is the case, then you paid for one version of LV, got that version, the SP for it and then a whole new version as well, all for one price.
So, if you want to continue getting new versions (and subsequent SP) then you can pay the SSP fee. If you don't want to pay, then you can still use the version you actually bought (8.6) and all it's SP (8.6.1) and consider the LV2009 a bonus.
That is unless you are considering LV2009 a bug fix to LV 8.6.1.
So, when you buy a version of LV, you always get that version and all it's bug fixes.
Any way you look at this, I think NI is being quite fair. I have a lot of software that is constantly being updated and bug fixed, but I only get those updates if I pay for ongoing support.
Now, if for some reason NI found a major bug in LV8.6.1 and released a SP called 8.6.2, then I would expect that to be free to all LV8.6 licence holders.
-
I still don't see any way anyone is actually paying for SP1. If you are, can you tell us how that happened?
-
I thought a new version of LV always came with one free year of SSP? So, the service pack should be free for anyone who bought a copy of LV2009, right?
And for those of us who maintain SSP, it is free anyways (or at least covered by the SSP fees)
Maybe the student edition of LV does not come with the 1 year of SSP, but checking the NI web site, the base, full, pro and dev suite versions all include one year of SSP in their price.
So, who is actually paying for this service pack? Anyone?
-
Here is a new idea I just posted. Please take a look and Kudo it if you agree!
-
Send the snow to BC. They are screwed with all the warm weather and lack of snow for the Olympics. I think the snowboard competition is going to have to be done with skateboards this year!
-
now to try this in my real world application and see if Python likes it!
Confirmed! This solution works in all my test cases for my Console app!
Thanks to smenjoulet!
I owe you a beer at the next NI Week!
-
OK, I got piping/redirection to work.
Sweet! This works for me. Only caveat is I cannot call it from the command line using start /wait to force it to wait until completion. However, calling it with "cmd /c myapp.exe" does work, will wait and redirection works too.
Thanks! now to try this in my real world application and see if Python likes it!
-
What about using WriteFile instead of WriteConsoleA? That might make the redirection work.
Nope. Back to the drawing board...
Beware of the Get Variant Attribute function
in Application Design & Architecture
Posted
I have been unable to build a simple example of this bug so I have not reported it to NI yet, but I figured this was annoying enough to warn people about. Not sure if all the steps are needed to repro this, but I included them all anyways.
I have discovered in some complex code in my application that the 'Get Variant Attribute' function can sometimes behave abnormally. Here is what I am seeing:
I start with an empty variant (Top Variant).
I call 'Get Variant Attribute' to get a specific attribute (Parent Attribute 1) (if it does not exist, I should get an empty default variant).
I then add a sub attribute (Child Attribute 1) to the 'found' (or empty if not found) Parent attribute.
I then replace the Parent attribute in the Top Variant with this new variant (with the sub attribute attached). This is basically a tree structure.
So far, I have this:
-Top Variant
--Parent Attribute 1
----Child Attribute 1
I continue this until my Parent has several children:
-Top Variant
--Parent Attribute 1
----Child Attribute 1
----Child Attribute 2
----Child Attribute 3
----Child Attribute 4
----Child Attribute 5
I then remove these one by one by getting the Parent variant, calling 'Delete Variant Attribute' with a child as the attribute to remove and then replacing the Parent into the Top Variant. I leave child 3, however. Now I have this:
-Top Variant
--Parent Attribute 1
----Child Attribute 3
Now, I replace the Parent with an empty variant to 'Flush' the tree. Now I have this:
-Top Variant
--Parent Attribute 1
Here is where the bug comes in. Now I repeat the whole process, but for Parent Attribute 2. When I call Get Variant Attribute on the Top Variant and give it the name 'Parent Attribute 2', it should give me a default empty variant because that attribute does not exist in the Top Variant. Instead this is what I get:
-Top Variant
--Parent Attribute 1
--Parent Attribute 2
----Child Attribute 1
----Child Attribute 2
----Child Attribute 3
----Child Attribute 4
----Child Attribute 5
WTF?
The new attribute seems to inherit all the child attributes that ever existed in the new Parent's sibling (which still exists, but is empty)
The fix is easy, however. Just wire an empty variant to the default value terminal of the 'Get Variant Attribute' function when you try to get an attribute and the problem goes away.
Just don't trust that the unwired default will really be an empty variant.
Now, as I said, I cannot seem to reproduce this with an example VI, but I can instrument my code and see this happening. I dump the whole Top Variant tree to a file before the call to 'Get Variant Attribute' and then right after. I also confirmed that the 'Found' output is false and the value output contains the 5 child attributes, even though nothing is wired to the 'default value' input.