Netlinx port codes
alan.heric
Posts: 18
I have a project with over 40 identical devices to control.
My idea was to use same design for all BUT with different channel ports, then in the code just do a switch depending on the device port and coding is done.
My question is:
I defined over 40 touch panels in DEFINE_DEVICE (ugly and big chance of mistake).
Can i define one device that will catch all that is coming from a single touch panel with no need of defining it 40 times with different ports?
Example:
DEFINE_DEVICE
TP_PORT1 = 10001:1:0
TP_PORT2 = 10001:2:0
TP_PORT3 = 10001:3:0
... and so on till ±40
can it be done like
TP= 10001:0:0 - i know 0 is setup port so didnt even tried it like that
Hope you can understand what i wanna do
Thanks,
Alan
My idea was to use same design for all BUT with different channel ports, then in the code just do a switch depending on the device port and coding is done.
My question is:
I defined over 40 touch panels in DEFINE_DEVICE (ugly and big chance of mistake).
Can i define one device that will catch all that is coming from a single touch panel with no need of defining it 40 times with different ports?
Example:
DEFINE_DEVICE
TP_PORT1 = 10001:1:0
TP_PORT2 = 10001:2:0
TP_PORT3 = 10001:3:0
... and so on till ±40
can it be done like
TP= 10001:0:0 - i know 0 is setup port so didnt even tried it like that
Hope you can understand what i wanna do
Thanks,
Alan
0
Comments
You can use multiple arrays or a structure depending on what you're comfortable with. When you select a device to control just set the tracking array value for that UI index to the index of the device to be controlled. That index will then correspond to the index of the Virtual or dev to be controlled then you just need one port and one touch panel page.
This should get you started. It will control all 40 devices from a single touchpanel page/popup/port. The whole "separate port per device thing" is a horrible method to teach in AMX training. It is very wasteful both in processor resources and in touchpanel creation/editing labor time.
This method can control all 1-way devices in a system whether they are the same or not, just use different panel pages with corresponding button channels and labels.
Seems i wasn't good in explaining what i want to do.
Maybe this code will clear a bit what i was talking about
in this case i just use 8 ports so its not that much, but as i said when you have 40 ports in use then it becomes a different story.
my question was just the part about DEFINE_DEVICE - is there a way to define device so that i can register it in BUTTON_EVENT and see the port of the pushed button.
Thanks once more for your previous answer. It game me some nice ideas
you just need a DEV array of your touch panels, then grab which panel its from if you want it to act indepently.
maybe this is what you are trying to find out??
Thanks
With the examples provided you only need to define 1 DPS per touch panel to control any of the 40 devices. You will need to define 40 different DPS's for each device though and then put all of them into one DEV array. Do the same for virtual DEVs if you using them for modules, if not forget the virtuals.
Then on your TP create your device selection buttons, an earlier example suggested buttons 301-340. Create a variable to track what DEV the TP is controllong. Now when you decide to control device 4 the user pushes button 304, in your button event handle the push and subract 300 from the button value and store the remainder, 4, in yor dev tracking var. now when any other buttons are pushed other than buttons 301-340 you route it to the dev array index position held by your dev tracking var.
There are Netlinx Master memory considerations when defining different ports on a touch panel. We allocate memory for all of the possible channels/levels/ports etc. for EACH port defined PER panel. As your system grows, and the number of panels increases, this can become an issue and is not a good practice to get into if you are just starting out. While it may seem faster, the suggested approaches are far superior from a code logic standpoint.
As Pete pointed out, defining the first port on your panel would be preferred here. Using a flag to track the last source selected from your button array of 40 source options is the cleanest, and most memory friendly approach. Additionally, it is preferred from a TPDesign approach. Under your proposed approach, if you wanted to add a button to a page, you would have to add it to each page. Then, you would need to change the port on that button across 40 pages. The panel file would be un-necessarily large and time consuming to manage.
The concept of GET_LAST will be very helpful to comprehend as it relates to index values and arrays - button or device.
Let's use an example where you have 40 IR controlled devices, and in Pete's code you already defined your device array and your button array for source selection. In my example, I would define an additional array that mapped button channels to IR file channels (if you push a nDeviceTransportButtons, pulse the corresponding IR channel in nDeviceIRChannels).
Your event statement could look something like this:
The benefit here is that the event statement is fairly fixed moving forward. If you add a panel to the system, add it to the array definition for panels. If you add a button, add it to the button array and the corresponding IR channel array. This would allow you to scale this rapidly and with minimal TPDesign work.
The last explanation by vining is exactly what you should do.
A DPS is much more costly (in terms of memory & efficiency) than it is to use a single char (byte).
Edit: Chris' way would also be a way to do it; as you can see, there are many "right" ways to do it.
Sublime Text 2 is a code editor that has a "multiple cursor" function that I use for the same purpose. Sometimes it is faster than excel.
Two tools, same results.
That's like saying the front brake is the most dangerous part on a motorcycle. Learning how to use it properly will turn it into the safest part on that bike.
I think you will find in developing truly scalable and maintainable code for large system deployments that limiting yourself to a single port on a touchpanel will be... limiting.
So, I understand how to control devices, but what is not obvious to me is how to control the feedback using the one-page method. If, for example, there are 40 panels and 40 devices and a button is pushed on one of the panels and this button push requires a change in feedback, how is this feedback updated to other panels which are currently controlling the same device? I'm not seeing a simple way to do this but with the multi-port method, it's real easy.
If you track what source is in use per zone, and what panel is CURRENTLY operating what zone, you can tell both where to send control pushes from the panels and where to direct feedback from devices. Now you can let any panel control any zone too... several at a time can control the same room now, and different ones later. All get what they need and control only what they are supposed to, all with a single control page per source TYPE.
This is more programming work, but creates a more intelligent system that can expand and change without agonizing TP revision. And the logic is reusable, as is the TP.
When i have feedback to send to my UIs i run it through a for loop on my tracking array and if the UI index position holds the value of the instance or dev then feedback is sent.
The tracking array gets set to the device or instance when you go on page and changed to zero or the next page when exited.
Ok, I can see that. It's somewhat more complicated, but you really only have to do it once and then it's cut and paste.
Here's an example of my VT function: Now anywhere in my device module code I need to send feedback I just pass it the parameters the functions calls for. If a UI just came on page my function call will look like this: And I pass the actual UI index so feedback is only sent to that UI. But when the device sends me data and I need to send to all the UIs that may be on this dev page/instance I have a constant called UI_UPDATE_ACTIVE which has a value of 0 like this: Now the function will go through the entire array and send to every UI on this dev/instance.
I also pass these parameters through from function to function so when a UI comes online the UI index is passed from here: which in turn calls all these functions but either the UI index value or UI_UPDATE_ACTIVE to update all active UIs is passed along the way until it reaches the sending function.
Here's my channel function: With these I usually perform the evaluation in the parameter like:
Again iUI_Indx could be an actually index position of a UI or 0 for UI_UPDATE_ACTIVE depending on what initiated the need for feedback.
But once you've done one it is just copy and past for my different devices. FYI, I still use multiple ports, usually a port per device type but only one port/UI Page set per type no matter how many instances are actually used. IMHO it does get a bit trickier to the only 2-3 ports per per system for everything that allot folks here do. I find both ways have their advantages and drawbacks so there hasn't been enough incentive to go the 2-3 port route so in my UI I can still have nearly 30 ports defined but only one port per type of device. The OP had 40 identical devices so for me that's just one port to control using 40 instances on a module and one UI page set.
STACK_VAR _tp
_tp = tp_Module
_tp.port = 1
SEND_COMMAND _tp ....
Most devices aren't chatty enough to really be a problem, depending on what you are doing. I don't typically worry about whether the user is looking at the HVAC page to send feedback that the temperature in the room has gone up one degree, I just send it. For the chattier devices I will worry about it but they are few and far between. A Sonos module for instance would be a good example of a device where you pretty much have to limit the feedback on a need to know basis.
Paul
I have 7 panels and 20 devices, so to set all this up in Define Device:
dvTPa01 = 10001:01:0;
dvTPa02 = 10001:02:0;
dvTPa03 = 10001:03:0;
dvTPa04 = 10001:04:0;
dvTPa05 = 10001:05:0;
dvTPa06 = 10001:06:0;
dvTPa07 = 10001:07:0;
dvTPa08 = 10001:08:0;
Then in DEFINE_VARIABLE I have
DEV dTP_MAIN[] = { dvTPa01, dvTPb01,dvTPc01,dvTPd01,dvTPe01,dvTPf01,dvTPg01 };
so when I do a BUTTON_EVENT
BUTTON_EVENT[dTP_MAIN,nbtKickoff] //nbtKickoff[] = { 91,92,93,94 }
So when user from touch panel 1 presses button 91 , then BUTTON_EVENT gets recognized.
But issue I have -- I have 7 panels and 20 devices, I have to define all these in DEFINE_DEVICE and DEFINE_VARIABLE (like above). Well I figured out a way to load all my panels with all devices in DEFINE_START section but this when I refer to the panels after loaded in DEFINE_START it does not recognize when Button is pushed. I think it is because it needs to be loaded at compile time and DEFINE_START is afterwards.
Does anyone know a way to load all Panels to all devices without hardcoding everything like above so system can recognize - maybe somewhere else besides DEFINE_START
It worked using REBUILD_EVENT();
But after I dynamically built my Dev array I had to set it equal to itself to get it to work (saw from another post) - like below:
dTP_MAIN = dTP_MAIN; //- main menu
dTP_THEAT = dTP_THEAT; //- theater
dTP_MUSIC = dTP_MUSIC; //- MUSIC
REBUILD_EVENT(); //rebuild the internal Event table
Thanks for your help!!!
Thanks
Paul