Home AMX User Forum NetLinx Studio
Options

Netlinx port codes

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

Comments

  • Options
    viningvining Posts: 4,368
    Create arrays of virtual devices used to control each device, an array of the devices themselves and then an array to track which device any particular UI is supposed to control. When a button is pushed on any UI use a get last to get's its index in the UI array then you can use that index to see what dev index it's supposed to be controlling and then route your push to it's corresponding virtual which inturn will control it's associated device. You could go directly to the device too if that's the way your code is designed.

    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.
  • Options
    Thanks for the reply. Is there any manual/example on how to create virtual devices and arrays of devices or structures? I checked netlinx studio help but cant find any...
  • Options
    the8thstthe8thst Posts: 470
    It's early... I'm still in a good mood.

    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.
    (***********************************************************)
    (*          DEVICE NUMBER DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_DEVICE
    
    	dvDeviceControlTP1 	= 10001:1:0
    	dvDeviceControlTP2	= 10002:1:0
    	dvDeviceControlTP3	= 10003:1:0
    	
    	dvDevice1 					= 5001:1:0
    	dvDevice2 					= 5001:2:0
    	// Do this to define all identicle devices
    	dvDevice40 					= 5001:40:0
    
    
    (***********************************************************)
    (*               CONSTANT DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_CONSTANT
    
    	integer maxNumTPs = 3
    	
    	// Array of touch panels
    	dev dvTouchPanels[] = {
    		dvDeviceControlTP1,
    		dvDeviceControlTP2,
    		dvDeviceControlTP3
    	}
    
    	// Array of identicle devices to control
    	dev dvDevicestoControl[] = {
    		dvDevice1,
    		dvDevice2,
    		// add all devices here
    		dvDevice40
    	}
    	
    	// These are for selecting current device
    	// They can be a different TP port or simply channels
    	// That are above the highest channel you use for the devices
    	integer deviceSelectButtons[] = {
    		301,302,303,304,305,306,307,308,309,310,
    		311,312,313,314,315,316,317,318,319,320,
    		321,322,323,324,325,326,327,328,329,330,
    		331,332,333,334,335,336,337,338,339,340
    	}
    
    (***********************************************************)
    (*               VARIABLE DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_VARIABLE
    
    	integer currentDevice[maxNumTPs]
    
    (***********************************************************)
    (*                THE EVENTS GO BELOW                      *)
    (***********************************************************)
    DEFINE_EVENT
    
    	// This is where you select which device the TP is going to control
    	// It is normally a source select page or whatever
    	button_event[dvTouchPanels,deviceSelectButtons]
    	{
    		push: {
    			stack_var integer touchPanelIndex
    			stack_var integer deviceIndex
    			
    			touchPanelIndex = get_last(dvTouchPanels)
    			deviceIndex = get_last(deviceSelectButtons)
    			
    			currentDevice[touchPanelIndex] = deviceIndex
    			// Here you can send individual device names and page flips
    		}
    	}
    	
    	// This is a "catch-all" button event for the actual device controlling buttons
    	button_event[dvTouchPanels,0]
    	{
    		push: {
    			stack_var integer touchPanelIndex
    			stack_var integer buttonChannel
    			
    			touchPanelIndex = get_last(dvTouchPanels)
    			buttonChannel = button.input.channel
    			
    			if(buttonChannel < deviceSelectButtons[1]) {
    				to[dvDevicestoControl[currentDevice],buttonChannel]
    			}
    			// You can use push, to, min_to, send_command, [device],"'SP',chan", etc
    		}
    		// hold and release events go here
    	}
    
  • Options
    First of all thanks a lot for all the effort!
    Seems i wasn't good in explaining what i want to do.
    Maybe this code will clear a bit what i was talking about
    PROGRAM_NAME='test'
    
    DEFINE_DEVICE
    extron       = 5001:1:0		// some extron matrix switcher 8x8
    
    dvTP1	= 10001:1:0		// touch panel 1 port1
    dvTP2	= 10001:2:0		// touch panel 2 port2
    dvTP3	= 10001:3:0 		// ...i want to skip this defining if possible...
    dvTP4	= 10001:4:0
    dvTP5	= 10001:5:0
    dvTP6	= 10001:6:0
    dvTP7	= 10001:7:0
    dvTP8	= 10001:8:0		// touch panel 2 port8
    
    DEFINE_VARIABLE
    integer temp_port
    integer temp_butt
    integer extron_butt[]={ 1,2,3,4,5,6,7,8 }
    
    DEFINE_EVENT
    BUTTON_EVENT[dvTP1,extron_butt]
    BUTTON_EVENT[dvTP2,extron_butt]
    BUTTON_EVENT[dvTP3,extron_butt]
    BUTTON_EVENT[dvTP4,extron_butt]
    BUTTON_EVENT[dvTP5,extron_butt]
    BUTTON_EVENT[dvTP6,extron_butt]
    BUTTON_EVENT[dvTP7,extron_butt]
    BUTTON_EVENT[dvTP8,extron_butt]
    {
        PUSH:
        {
    	temp_port=button.input.device.port
    	temp_butt=button.input.channel
    	send_string extron,"itoa(temp_butt),'*',itoa(temp_port),'!'"
        }
    }
    

    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 :)
  • Options
    rrdbstudiosrrdbstudios Posts: 160
    alan.heric wrote: »
    First of all thanks a lot for all the effort!
    Seems i wasn't good in explaining what i want to do.
    Maybe this code will clear a bit what i was talking about
    PROGRAM_NAME='test'
    
    DEFINE_DEVICE
    extron       = 5001:1:0		// some extron matrix switcher 8x8
    
    dvTP1	= 10001:1:0		// touch panel 1 port1
    dvTP2	= 10001:2:0		// touch panel 2 port2
    dvTP3	= 10001:3:0 		// ...i want to skip this defining if possible...
    dvTP4	= 10001:4:0
    dvTP5	= 10001:5:0
    dvTP6	= 10001:6:0
    dvTP7	= 10001:7:0
    dvTP8	= 10001:8:0		// touch panel 2 port8
    
    DEFINE_VARIABLE
    integer temp_port
    integer temp_butt
    integer extron_butt[]={ 1,2,3,4,5,6,7,8 }
    
    DEFINE_EVENT
    BUTTON_EVENT[dvTP1,extron_butt]
    BUTTON_EVENT[dvTP2,extron_butt]
    BUTTON_EVENT[dvTP3,extron_butt]
    BUTTON_EVENT[dvTP4,extron_butt]
    BUTTON_EVENT[dvTP5,extron_butt]
    BUTTON_EVENT[dvTP6,extron_butt]
    BUTTON_EVENT[dvTP7,extron_butt]
    BUTTON_EVENT[dvTP8,extron_butt]
    {
        PUSH:
        {
    	temp_port=button.input.device.port
    	temp_butt=button.input.channel
    	send_string extron,"itoa(temp_butt),'*',itoa(temp_port),'!'"
        }
    }
    

    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.
    DEV dvTPs[] = {
    dvTP1, dvTP2,dvTP3,.... 
    }
    
    .. 
    
    BUTTON_EVENT[dvTPs,extron_butt]
    {
        PUSH:
        {
    	local_var INTEGER nPanel
    local_var INTEGER nButton
    nPanel = GET_LAST(dvTPs)
    nButton = GET_LAST(extron_butt)
    
    ....
    }
    }
    


    maybe this is what you are trying to find out??
  • Options
    this helps a lot but still i have the issue of declaring panel 40 times :)

    Thanks
  • Options
    viningvining Posts: 4,368
    alan.heric wrote: »
    this helps a lot but still i have the issue of declaring panel 40 times :)

    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.
  • Options
    Alan,
    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:
    BUTTON_EVENT [dvTouchPanels, nDeviceTransportButtons]
    {
         PUSH:
         {
             PULSE[dvDevicestoControl[currentDevice[GET_LAST(dvTouchPanels)]], nDeviceIRChannels[GET_LAST(nDeviceTransportButtons)];
         }
    }
    

    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.
  • Options
    jjamesjjames Posts: 2,908
    That's the way to do it

    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.
  • Options
    travistravis Posts: 180
    Sometimes I write the device and variable definitions in excel and them paste them in to netlinx. Handy for when there are a bunch of the same type of device. Lot's of =CONCAT
  • Options
    the8thstthe8thst Posts: 470
    travis wrote: »
    Sometimes I write the device and variable definitions in excel and them paste them in to netlinx. Handy for when there are a bunch of the same type of device. Lot's of =CONCAT

    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.
  • Options
    the8thst wrote: »
    . 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.

    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.
  • Options
    HedbergHedberg Posts: 671
    OK, I understand both methods (multiple ports and touch panel pages versus device tracking/flagging using get_last or another method) and I have used both. Never with 40 touch panels controlling 40 devices, true. But recently with a dividable room with 4 touch panels and 4 conference mixers/telephone hybrids. When you have a small number of devices (four, for example), the touch panel file is pretty easy to set up and maintain. Adding a button to the four pages and updating the port assignments takes but a minute or two.

    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.
  • Options
    John NagyJohn Nagy Posts: 1,734
    The port-per-source method to manage control and feedback is a limiting strategy. It removes the problem of tracking at the cost of flexibility.

    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.
  • Options
    viningvining Posts: 4,368
    Same thing but in rerverse. You're tracking variable tells you which device the TP is supposed to control but it also tells what dev or instance of a dev feedback it should be routed to.

    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.
  • Options
    HedbergHedberg Posts: 671
    vining wrote: »
    Same thing but in rerverse. You're tracking variable tells you which device the TP is supposed to control but it also tells what dev or instance of a dev feedback it should be routed to.

    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.
  • Options
    viningvining Posts: 4,368
    Yeah it's pretty basic and once you track the instance a UI is on I create a function to send channels, Commands, variable text and levels.

    Here's an example of my VT function:
    DEFINE_FUNCTION fnFB_DoSend_VT(INTEGER iUI_Indx,INTEGER iCHAN,CHAR iStrMSG[]) 
         
         {
         STACK_VAR INTEGER n;
         STACK_VAR INTEGER nTPCount; 
         STACK_VAR INTEGER nLoopStart; 
         STACK_VAR CHAR cUNI_STR_2[MAX_4096];
         STACK_VAR WIDECHAR cUNI_STR_1[MAX_4096];
         
         if(iUI_Indx)
    	  {
    	  nTPCount = iUI_Indx;
    	  nLoopStart = iUI_Indx;
    	  }
         else
    	  {
    	  nTPCount = sSBS.sPlayer.nNum_UIs;
    	  nLoopStart = 1;
    	  }
         //fnDevMod_DeBug("'SEND_VT: ',iStrMSG,' :DEBUG<',itoa(__LINE__),'>'");
         if(length_string(iStrMSG))
    	  {
    	  cUNI_STR_1 = WC_DECODE(iStrMSG,WC_FORMAT_UTF8,1); 
    	  cUNI_STR_2 = WC_ENCODE(cUNI_STR_1,WC_FORMAT_TP,1);
    	  }
         for(n = nLoopStart; n <= nTPCount; n++)
    	  {
    	  if(nUI_ActiveArry[n] == sSBS.sPlayer.nDev_Instance)//means it on this SB & ACTIVE on page
    	       {
    	       SWITCH(nUI_TypeArry[n])
    		    {
    		    CASE UI_TYPE_iPHONE:
    		    CASE UI_TYPE_iTOUCH:
    		    CASE UI_TYPE_iPAD:
    		    CASE UI_TYPE_G4:
    		    CASE UI_TYPE_R4:
    		    CASE UI_TYPE_MIO_DMS:
    			 {
    			 if(length_string(cUNI_STR_2))
    			      {
    			      STACK_VAR CHAR cUniSend[MAX_4096];
    			      STACK_VAR INTEGER nAppend;
    			 
    			      cUniSend = cUNI_STR_2;
    			 
    			      WHILE(LENGTH_STRING(cUniSend))
    				   {
    				   STACK_VAR CHAR cTMP[UNI_STR_SIZE];
    			 
    				   if(LENGTH_STRING(cUniSend) > UNI_STR_SIZE)
    					{
    					cTMP = GET_BUFFER_STRING(cUniSend,UNI_STR_SIZE);
    					}
    				   else
    					{
    					cTMP = GET_BUFFER_STRING(cUniSend,LENGTH_STRING(cUniSend));
    					}
    				   if(nAppend)
    					{
    					SEND_COMMAND dvUI_SBSArry[n],"'^BAU-',ITOA(iCHAN),',0,',cTMP";   //Append Unicode to Modero Panels
    					}
    				   else
    					{
    					SEND_COMMAND dvUI_SBSArry[n],"'^UNI-',ITOA(iCHAN),',0,',cTMP";   //Unicode to Modero Panels
    					}
    				   //fnDevMod_DeBug("'SEND_COMMAND UNI, APPEND-[ ',itoa(nAppend),' ], CHNL-[ ',itoa(iCHAN),' ], STR-[ ',cTMP,' ] :DEBUG<',ITOA(__LINE__),'>'");
    				   nAppend++;
    				   }
    			      }
    			 else//we need to clear text fields too, duh!
    			      {
    			      SEND_COMMAND dvUI_SBSArry[n], "'^TXT-',itoa(iCHAN),',0,',cUNI_STR_2"; 
    			      }
    			 }
    		    CASE UI_TYPE_G3:
    		    	 {
    			 //////fnDevMod_DeBug("'^TXT- TP INDX: ',itoa(n),', CHNL: ',itoa(iCHAN),' :DEBUG<',ITOA(__LINE__),'>'");
    			 SEND_COMMAND dvUI_SBSArry[n], "'^TXT-',itoa(iCHAN),',0,',iStrMSG"; 
    			 }
    		    CASE UI_TYPE_METKP:
    		    CASE UI_TYPE_UNKNOWN:
    		    CASE UI_TYPE_VIRTUAL:
    			 {
    			 //DO NOTHING
    			 }
    		    }
    	       }
    	  }
    	  
         RETURN;
         }
    
    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:
    fnFB_DoSend_VT(iUI_Indx,SBS_BTN_BASELO_LIST + nLoop,"sLevelList[nLevel].cItem[nLoop],' '");
    
    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:
    fnFB_DoSend_VT(UI_UPDATE_ACTIVE,nBase+4,sSBS.sNowPlaying.cAppTitle);
    
    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:
    fnFB_Update_UI(nUI_Indx,FORCE,NOCLEAR);
    
    to
    
    DEFINE_FUNCTION fnFB_Update_UI(INTEGER iUI_Indx,INTEGER iForce,INTEGER iClear)
         
         {
         fnDevMod_DeBug("'fnFB_Update_UI, UI-[ ',itoa(iUI_Indx),' ], LVL-[ ',itoa(sSBS.sBrowseState.nLevel),' ], REMOTE-[ ',itoa(sSBS.sNowPlaying.nRemote),' ] :DEBUG<',ITOA(__LINE__),'>'");
         fnFB_Btn_isApp_SHO(iUI_Indx,sSBS.sNowPlaying.nRemote);
         fnFB_SetCoverArtPath(iUI_Indx,iForce,iClear);//takes the longest so go first 
         fnFB_CurPlyLists(iUI_Indx,iForce);//zero refreshes both arrays
         fnFB_CurPlyListIndx(iUI_Indx,iForce);
         fnFB_DeBugBtn(iUI_Indx,iForce);
         fnFB_BrowseList(iUI_Indx,iForce,iClear);
         //fnFB_CurQList(iUI_Indx,iForce,iClear);
         //fnFB_IR_Volume(iUI_Indx,iForce);
         //fnFB_Mixer(iUI_Indx,iForce);
         fnFB_PlayerName(iUI_Indx,iForce);
         fnFB_Power(iUI_Indx,iForce);
         fnFB_Repeat(iUI_Indx,iForce);
         fnFB_Shuffle(iUI_Indx,iForce);
         fnFB_SongTime(iUI_Indx,iForce);
         //fnFB_SleepTime(iUI_Indx,iForce);
         fnFB_Transport(iUI_Indx,iForce);
         fnFB_UpdateScrollBar(iUI_Indx,iForce);
         fnFB_UpdateNowViewing(iUI_Indx,iForce);
         
         fnFB_ABRepeat(iUI_Indx,iForce);
         fnFB_DoSend_VT(iUI_Indx,SBS_BTN_FAV_0,' ');
         if(sSBS.sBrowseState.nLevel > 1)
    	  {
    	  fnFB_DoSend_UI_CMD(iUI_Indx,"'^SHO-',itoa(SBS_BTN_SHOW_LIST),',1'");
    	  fnFB_DoSend_UI_CMD(iUI_Indx,"'^SHO-',itoa(SBS_BTN_BACK_LEVEL),',1'");
    	  }
         else
    	  {
    	  fnFB_DoSend_UI_CMD(iUI_Indx,"'^SHO-',itoa(SBS_BTN_SHOW_LIST),',0'");
    	  fnFB_DoSend_UI_CMD(iUI_Indx,"'^SHO-',itoa(SBS_BTN_BACK_LEVEL),',0'");
    	  }
         }
    
    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:
    DEFINE_FUNCTION fnFB_DoSend_CHNL(INTEGER iUI_Indx,INTEGER iChannel,INTEGER iCHState)
    
         {
         STACK_VAR INTEGER n;
         STACK_VAR INTEGER nTPCount; 
         STACK_VAR INTEGER nLoopStart; 
         
         if(iUI_Indx)
    	  {
    	  nTPCount = iUI_Indx;
    	  nLoopStart = iUI_Indx;
    	  }
         else
    	  {
    	  nTPCount = sSBS.sPlayer.nNum_UIs;
    	  nLoopStart = 1;
    	  }
         //////fnDevMod_DeBug("'fnFB_DoSend_CHNL: Running FB! :DEBUG<',ITOA(__LINE__),'>'");
         for(n = nLoopStart; n <= nTPCount; n++)
              {
    	  if(nUI_ActiveArry[n] == sSBS.sPlayer.nDev_Instance)
    	       {
    	       SWITCH(nUI_TypeArry[n])
    		    {
    		    CASE UI_TYPE_iPHONE:
    		    CASE UI_TYPE_iTOUCH:
    		    CASE UI_TYPE_iPAD:
    		    CASE UI_TYPE_G4:
    		    CASE UI_TYPE_R4:
    		    CASE UI_TYPE_MIO_DMS:
    		    CASE UI_TYPE_G3:
    		    CASE UI_TYPE_METKP:
    		    CASE UI_TYPE_VIRTUAL:
    		    CASE UI_TYPE_UNKNOWN://leave this SWITCHin in CASE we choose to limit number of channels
    			 {               //to specific types of devices (no online or comms status for keypads, etc)
    			 SWITCH(iCHState)
    			      {
    			      CASE CH_OFF://0
    				   {
    				   OFF[dvUI_SBSArry[n],iChannel];
    				   }
    			      CASE CH_ON://1
    				   {
    				   ON[dvUI_SBSArry[n],iChannel];
    				   }
    			      CASE CH_PULSE://2
    				   {
    				   PULSE[dvUI_SBSArry[n],iChannel];
    				   }
    			      CASE CH_TOGGLE://3
    				   {
    				   [dvUI_SBSArry[n],iChannel] = (![dvUI_SBSArry[n],iChannel]);
    				   }
    			      }
    			 }
    		    }
    	       }
    	  }
            
         RETURN;
         }
    
    With these I usually perform the evaluation in the parameter like:
    fnFB_DoSend_CHNL(iUI_Indx,SBS_BTN_SCROLL_FWD,(sLevel[nLevel].nStartItem + (sSBS.sBrowseState.nNumLines-1)) < sLevel[nLevel].nMaxItem);
    

    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.
  • Options
    travistravis Posts: 180
    I don't usually have to use more than 2 or 3 panels in one system, so I'm used to different needs. I usually use one module per device and pass an array of touch panels (on different panel ports) to the each module. Recently I had more devices than I wanted to create separate pages/ports for, so I did something like this:

    STACK_VAR _tp
    _tp = tp_Module
    _tp.port = 1

    SEND_COMMAND _tp ....
  • Options
    travistravis Posts: 180
    I there a thread about what kinds of feedback are worth checking if the panel is online and on a certain page for?
  • Options
    a_riot42a_riot42 Posts: 1,624
    travis wrote: »
    I there a thread about what kinds of feedback are worth checking if the panel is online and on a certain page for?

    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
  • Options
    JOHNBONZJOHNBONZ Posts: 99
    Netlinx port codes

    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
  • Options
    viningvining Posts: 4,368
    Try using rebuild_event() after you create your arrays in define start. Also search the forums for that function for more info.
  • Options
    JOHNBONZJOHNBONZ Posts: 99
    Netlinx port codes

    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
  • Options
    a_riot42a_riot42 Posts: 1,624
    Not sure what you are trying to accomplish. Netlinx isn't really all that flexible, and what you'll find is if you bend the rules, very weird things will happen. DEFINE_START is just to initialize global variables on boot, it isn't really for doing much more than that. If you want to try coloring outside the lines, you are welcome to do it, and Netlinx will let you, but you may not end up with a pretty picture.
    Paul
Sign In or Register to comment.