GET_LAST w/ virtual dev array
vining
Posts: 4,368
I just ran into a problem using GET_LAST w/ a virtual dev array. I assumed using GET_LAST would work to retrieve the index postion of the virual device initiating the online event or level event but it doesn't work as I expected. My virtuals all use the same dev.number and they vary by port only and from what I gather GET_LAST only checks the dev.number to return the array index not the entire DPS. Not a big problem since I just changed my get_last to var = data.device.port since they are in the same sequential order and numbers but I would have thought when using get_last on a dev array it would check the entire DPS not just the DEV.Number. I often like to keep like devices for module instances using the same dev number and just set_virtual_port_counts then rebuild. It just seemed easier but now I'm not so sure.
0
Comments
Diagnostics:
Also notice that GET_LAST starts at the end of the array while looking for a match not the beginning. Since GET_LAST apparently only cares about dev.number of the DPS it see index postion 16 as the match every time. So if you're going to use virtuals like this don't use nVirtual_Indx= GET_LAST(vVirtual_Arry) ; use nVirtual_Indx= DATA.DEVICE.PORT instead.
Paul.
Well someone at AMX must have thought it was a useful idea/method and that's why they gave us the SET_VRTUAL_PORT_COUNT command to allow us to do this. Changing the dev.number or dev.port gives each virtual a different D:P:S. The olny downside I see isn't really to do with changing ports instead of numbers but that GET_LAST on dev arrays doesn't actually compare all the devs paremeters. It only compares dev.numbers and not the complete D:P:S.
What if you have devs on different masters with the same D:P: and different system numbers and you build an array of these devs on the different masters GET_LAST won't work on them either. I think using GET_LAST on dev arrays the function should check the entire D:P:S not just the first parameter of the 3.
If GET_LAST worked properly then using this method makes following code a bit easier IMHO. If you working on code and you know the dev.number and want to look at the virtual for say KP 16 then that's the port, easy to follow, not 33026 (starting number) + 16 = ??.
I didn't say it shouldn't be allowed. Obviously there are times when you absolutely need the capability of having a virtual device with multiple ports. But it sounds like what you are doing is using the port number to differentiate between virtual devices rather than the device number, and now finding the unintended consequences of that. If they are different devices then they should have different device numbers. If its the same device with multiple ports then that is how is should be coded. Again, I see no advantage in doing this. If there is one, let us know.
I wouldn't do that. Different devices get different device numbers unless you like opening Pandora's box just to see what's inside. Its these types of programming errors that can cause very difficult, hard to trace bugs and I am just not that masochistic.
Seems like a strained example. When using get_last I don't care about anything but an index. As long as the correct index comes back then I am happy. I generally don't do arithmetic on virtual device numbers ever. The way I address my virtuals is at the very end of programming before installation I highlight the whole column and hit Alt+M. The numbers are more or less arbitrary and IMHO adding significance to arbitrariness is asking for trouble. It sounds like you might be one of those programmers that thinks its clever to use the channel number of a button to recall a TV station with the excuse that you can tell the station just by looking at the channel number. Down this road lies madness.
Paul.
As the appointed goodwill ambassador of GET_LAST(), I feel the need to defend her honor.
GET_LAST() with an array of virtual devices even with the same device number and different ports works fine for me. DUET modules use this method all the time.
You didn’t post any code that we could actually compile and test but I think the problem is most likely in your code someplace and not GET_LAST().
Here is the code that I tested against:
And here are the results which are exactly as I would expect them to be. A virtual device comes online and then a debug statement using GET_LAST() is printed correctly and then the next device comes online and a debug statement and so on. If you swap vdvPort1 and vdvPort16 in the vdvArray then you’ll see that index 16 port 1 comes online first and then 2-15 and the last device to come online is index 1 port 16. Everything seems to report as expected.
If you look at the first three lines of your output the 2 debug messages look correct after port 1 comes online. But then the rest of the 16 ports come online before we see any more of your debug messages. There is something fishy going on like maybe a wait or something someplace after the first device comes online? It’s hard to tell since you’re not showing us enough of the picture.
If you run the code I posted are your results different than mine?
Here's the entire .axi. I have to run out now and play so I'll look through my code and see if maybe I duplicated a virtual and then test your code if I find nothing.
There was one or two times that I thought the code (GET_LAST) worked properly and my fears subsided, then I ran this last test which obviously didn't work. I'd love nothing more than to have GET_LAST work on the entire D:P:S but even if I duplicated the virtual or had a wait somewhere how can you explain the results of side by side comparison. It obviously isn't working in this example and I can think of anything that could cause this in code.
a-riot42 wrote: I wasn't reffering to doing math on a virtual in code but rather in my head when doing diagnotics and setting up notification options. I know if I want to watch zone 16's virtual and can just type that in with out thinking too hard otherwise I don't care what numbers they are.
My other thought is that something else happening during the initialization sequences is goofing up the online events; overrunning a buffer or stalling the message queue.
I think I know why the there's a delay for port's higher than 1 coming online. The online event doesn't trigger until you call set_virtual_port_count(), so those devices don't come online until define_start runs.
I used to use multiple ports on virtual devices, but I ran into some weird issues with certain AMX modules, including one that refused to function at all on anything other than port 1. I haven't tried it in a few years, though I'm tempted to do so again since all of the few AMX-sourced modules I use at this point are Duet based, and I don't recall having any problems with any of my own modules. It'd make things a bit neater.
When you get down to it, virtually everything you aren't controlling over IP is a device with multiple ports. It's either a NI series controller of some kind or a netlinx control card of some kind, or a touchpanel of some kind. The distinction you're drawing here is artificial.
I don't follow. A controller device has a device ID of 5001 and you access the different ports using the D:P:S nomenclature but since its the same device the device number doesn't change. If you open the online tree you will see each virtual device has a different device number, not the same device number with a different port. I don't think the distinction between a device, port and system is artificial at least not in my experience. A dev is a structure with these three fields I believe, and using them for purposes other than what they were designed could lead to a lot of hair pulling. Netlinx gives you enough rope to hang yourself, but that doesn't mean you should.
Paul
If you number your keypad virtuals at say 33101 through 33116 then doesn't that accomplishe the same thing without having to contort the DPS paradigm?
Paul
Anyway back to the issue. I went through my code and didn't see any duplicated virtuals and then loaded the newest NI3100 firimware. I was running v3.50.430 and now I'm running v3.50.439. Of course now I can't reproduce the error but I don't think it was fixed by the firmware change. I think it's just a flaky issue.
I was thinking that it could be caused by my base DPS used in the SET_VIRT_PORT_COUNT since that was 33048:0:0. I was thinking maybe the "0" for the port might screw up the function. Of course here I think the function would only care about the dev.number but who knows. I wanted to use this as my dummy DPS which is why I set the port to zero but I now set it to 1 and created a legitimate dummy outside the DPS range of the used keypads. Still changing it back and forth from 0 to 1 I still couldn't replicate the error. I do feel that using a DPS with a legitimate port number is probably better and it's also what Joe used. Otherwise the both code blocks are pretty much the same and his worked while mine didn't. Maybe his gremlins were sleeping while mine were up and active. Now today they're back to sleep.
rfletcher wrote: That's what I was thinking too and probably the case.
I'm sorry, reading that again I don't think I did a good job of explaining what I meant clearly. Let me try again.
If I understood you correctly, you are saying here that you should not use multiple ports on a virtual device unless the device you are controlling has multiple ports. However, at the base level nearly every non-virtual device we can control has multiple ports, be it an NI controller, a control card, the master and it's IP ports, or a touch panel, or some other native netlinx device. It's only when you abstract out a layer and ignore the serial port (or whatever interface you're using) itself that it appears you have devices with only a single port.
So either multiple ports on a virtual device should never be used to control anything, or it's ok to use multiple ports on a virtual device to control anything, but saying that multiple virtual ports should only be used with devices that have multiple ports doesn't seem to make any sense to me, as there are (almost) no non-virtual devices that have only a single port.
Hopefully that makes a bit more sense...
Duet modules use different ports for outputs on a single switch for instance but they still use the same device number for the same device. In Duet if you had two switchers and wanted to do what Vining is doing it would look like this:
get_last will work with any device array, it just returns the index of the device that last triggered the event. That's why I don't think the issue has anything to do with get_last and may be one of those hard to trace bugs that only crop up in certain circumstances caused by doing unorthodox programming. Like you mention get_last has no issues differentiating between devices with different port numbers but same device number so obviously get_last isn't the problem here.
Paul
Guy goes to a doctor and say, "it hurts when I move my arm like this." Doctor responds, "then don't move your arm like that." I thought that joke was funny when I was about five, these days I find it about as funny as a rubber crutch.
Granted it may be considered unorthodox by a real programmer and when I find one I'll ask him or her what they think but for now I'd just like to know why something that by the books should work, doesn't. It may be very well be a bug and maybe I can't do this the way I want and that's ok. It very well may be my code and that's fine too. But for now there's an issue and it would be nice to know why and just because it's not something you do doesn't make it wrong or unorthodox it's just not something you do and the rest of this imaginary issue you have with it is just in your head and that's ok too.