Data Sharing between controlers
Hi guys
how can I share the data of the statuses between cotrolers?
For example, in the Master that connected to the Lutron lighting system, I will hold a table with the current states of the lighting system (ONLY on this Master)
How will you recommend to share the data beween all home controllers that need to enter to the lighting screen and to fetch the current statuses?
As I see it ths simple way is to make all the relevant lighing screens handling in this controller for all the TP.
But what if now I have some screens that relate to other controller that need to get status from this controller?
I don't want to listen to status change in each controller.
Any tricks for this?
thank
Adys.
how can I share the data of the statuses between cotrolers?
For example, in the Master that connected to the Lutron lighting system, I will hold a table with the current states of the lighting system (ONLY on this Master)
How will you recommend to share the data beween all home controllers that need to enter to the lighting screen and to fetch the current statuses?
As I see it ths simple way is to make all the relevant lighing screens handling in this controller for all the TP.
But what if now I have some screens that relate to other controller that need to get status from this controller?
I don't want to listen to status change in each controller.
Any tricks for this?
thank
Adys.
0
Comments
Assuming that the second controller isn't meant to change the data on the first controller - the transfer is one-way:
You could set up a mechanism so that any state change on one controller is immediately replicated to the other. It would be easy to code, assuming limited state volatility wouldn't add excess load, and would be plenty fast.
Ideally hold the state in a generic format eg an array of integers subscripted by a set of constants. Always update the state indirectly through a routine which also checks for a change of state and sends a notification string (array subscript plus new value) to the other controller. On the other controller accept the string and update an array that mirrors the first.
This code is of course very reusable. Here is a first draft neither compiled nor tested:
define_constant nStateSize = 1000 nStateLight1 = 1 nStateLight2 = 2 etc define_variable integer nState[nStateSize] define_function integer StateGet( integer nArgSubscript) { return nState[nArgSubscript]; } define_function StateSet( integer nArgSubscript, integer nArgValue) { if (nState[nArgSubscript] <> nArgValue) { nState[nArgSubscript] = nArgValue send_string vOtherController,"'STATE',nArgSubscript,nArgValue" } }SOLUTION 2
Alternatively use one or more virtual devices in the same way. I haven't done this but I believe it works. It would be good to hear from someone who has done it.
In controller 1, create a virtual device and use its levels and channels as places to store information in the same way that I use the generic repository in the method above. Channels are binary repositories; levels offer values 0-255.
Master-to-master makes that device and its attributes seamlessly visible on controller 2.
If you access this device at both ends via a single routine (or two), you can change your mind about it, extend it, or re-implement it very easily. That is, for instance, you can change from solution 1 to 2 without messing with your code.
This code is also very reusable.
(**********************************************************************************)
(* MASTER-TO-MASTER COMMUNICATIONS: THE vdvCOMM VIRTUAL DEVICE POINTS TO THE *)
(* MASTER IN THIS ROOM. CHANNELS ARE SET TO INDICATE THE STATUS OF VARIOUS *)
(* OPERATIONS. *)
(* CHANNEL 1 ON INDICATES THAT A IS IN COMBINED MODE WITH B. *)
(* CHANNEL 2 ON INDICATES THAT A IS IN COMBINED MODE WITH C. *)
(* CHANNEL 2 CAN NOT BE ON UNLESS CHANNEL 1 IS ALSO ON. *)
(* CHANNEL 11 ON INDICATES THAT ROOM B IS IN USE. *)
(* CHANNEL 12 ON INDICATES THAT ROOM C IS IN USE. *)
(* ROOM A CONTROLS CHANNELS 1 AND 2. ROOM B CONTROLS CHANNEL 11 AND *)
(* ROOM C CONTROLS CHANNEL 12. IF SATELLITE ROOMS ARE IN USE INDICATED BY *)
(* CHANNELS 11 OR 12, THEN A WILL NOT BE ABLE TO ENTER COMBINED MODE WITH *)
(* THAT ROOM. *)
(* LEVEL 1 WILL CONTAIN THE VALUE OF THE ROOM CURRENTLY CONTROLING THE VTC *)
(* LEVEL 2 WILL CONTAIN THE VALUE OF THE ROOM CURRENTLY CONTROLING THE DVD *)
(* LEVEL 3 WILL CONTAIN THE VALUE OF THE ROOM CURRENTLY CONTROLING THE VCR *)
(* LEVEL 4 WILL CONTAIN THE VALUE OF THE ROOM CURRENTLY CONTROLING THE WIRELESS *)
(* MICROPHONES. *)
(* A VALUE OF 3 INDICATES THAT THE DEVICE IS FREE. *)
(**********************************************************************************)
vdvCOMM = 33050:1:201 // INTER-ROOM COMMUNICATION
This particular application had three rooms, each having a master. The rooms could be combined (0 and 1 or 0 and 1 and 2) or used as separate systems. There are four devices that are shared by the three rooms. These are the Video Conferencing system, the DVD, the VCR, and the wireless mics.
In the setup of each room, I assign a room number to a persistent variable. For the shared devices, the room that has the device "reserved" sends their room number as the level value for that particular device. When the value is 3, the device is available. If I do it again, I would probably number the rooms 1, 2, and 3 and have the 0 to indicate that the device is available. I don't know where my head was that day.
Anyway, I use send_level, level_event, channel_event, and so on against this virtual device to maintain the status of the system. Since the device buttons are available on the touch panel in each room, I use the level of a particular device to change the icon on the buttons, so that if room 1 is using the DVD player, the circle and slash symbol appears on the DVD buttons on the touch panels for rooms 0 and 2.
In other sites, I have also used channels to indicate which lighting preset is currently in use by the main room, so that if the rooms are combined I can tell the Lutron in each system to select the same lighting preset.
This method is easy to use, and the response is good since you use channel and level events to keep the mutiple systems in sync.
the second solution look good to me too.
Can anyone give a few words/resource/examples on channels and levels?
I looked at the programming manuals - very few words on those subjects and I think I miss the basic idea on channels and levels...
thanks
Ady
DEFINE_DEVICE dv232_Lights = 5001:1:0 //Lighting control attached to this system dvTPA_LIGHTS = 10001:1:0 //Touchpanel attached to this system dvTPB_LIGHTS = 10001:1:2 //Touchpanel attached to another system DEFINE_CONSTANT dvTP_LIGHTS[ ] = {dvTPA_LIGHTS, dvTPB_LIGHTS} dvTPBT_LIGHTS[ ] = {1, 2, 3, 4, 5, 6, 7, 8,, 9, 10} dvTPFB_LIGHTS[ ] = {11,12, 13, 14, 15, 16, 17, 18,, 19, 20} DEFINE_EVENT BUTTON_EVENT[dvTP_LIGHTS,nTPBT_LIGHTS] { PUSH: { STACK_VAR iTp, iButton iTp = GET_LAST(dvTP_Lights) iButton = GET_LAST(nTPBT_LIGHTS) TO[BUTTON.INPUT] SEND_COMMAND dv232_Lights,"'KBP',ITOA(nRoomLights[iTp],':',ITOA(iButton)")) } } TIMELINE_EVENT[tlTPAFB_LIGHTS] TIMELINE_EVENT[tlTPBFB_LIGHTS] { STACK_VAR iTp, i iTp = GET_LONG(TIMELINE.ID,tlTPFB_LIGHTS) FOR(i=1,i<=10,i++) { nTPFB_LIGHTS[iTp][i] = nKpFb_Lights[i] } }Neither compiled nor tested:
define_variable char cState[8] device vState define_start (* Associate cState array with levels *) stack_var integer nCounter for (nCounter = 1; nCounter<=8; nCounter++) { create_level vState,nCounter,cState[nCounter] } define_function integer StateGetBoolean( integer nArgSubscript) (* 1..255 *) { return [vState,nArgSubscript]; } define_function StateSetBoolean( integer nArgSubscript, (* 1..255 *) integer bArgValue) (* 0,1 *) { [vState,nArgSubscript] = bArgValue } define_function char StateGetChar( integer nArgSubscript) (* 1..8 *) { return cState[nArgSubscript]; } define_function StateSetChar( integer nArgSubscript, (* 1..8 *) char cArgValue) (* 0..255 *) { send_level vState,nArgSubscript,cArgValue }PROGRAM_NAME='Sample' (***********************************************************) (* FILE CREATED ON: 02/25/2007 AT: 18:39:48 *) (***********************************************************) (***********************************************************) (***********************************************************) (* FILE_LAST_MODIFIED_ON: 02/25/2007 AT: 18:52:37 *) (***********************************************************) (* System Type : NetLinx *) (***********************************************************) (* REV HISTORY: *) (***********************************************************) (***********************************************************) (* DEVICE NUMBER DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_DEVICE (**********************************************************************************) (* MASTER-TO-MASTER COMMUNICATIONS: THE vdvCOMM VIRTUAL DEVICE POINTS TO THE *) (* MASTER IN THIS ROOM. CHANNELS ARE SET TO INDICATE THE STATUS OF VARIOUS *) (* OPERATIONS. *) (* CHANNEL 1 ON INDICATES THAT A IS IN COMBINED MODE WITH B. *) (* CHANNEL 2 ON INDICATES THAT A IS IN COMBINED MODE WITH C. *) (* CHANNEL 2 CAN NOT BE ON UNLESS CHANNEL 1 IS ALSO ON. *) (* CHANNEL 11 ON INDICATES THAT ROOM B IS IN USE. *) (* CHANNEL 12 ON INDICATES THAT ROOM C IS IN USE. *) (* ROOM A CONTROLS CHANNELS 1 AND 2. ROOM B CONTROLS CHANNEL 11 AND *) (* ROOM C CONTROLS CHANNEL 12. IF SATELLITE ROOMS ARE IN USE INDICATED BY *) (* CHANNELS 11 OR 12, THEN A WILL NOT BE ABLE TO ENTER COMBINED MODE WITH *) (* THAT ROOM. *) (* LEVEL 1 WILL CONTAIN THE VALUE OF THE ROOM CURRENTLY CONTROLING THE VTC *) (* LEVEL 2 WILL CONTAIN THE VALUE OF THE ROOM CURRENTLY CONTROLING THE DVD *) (* LEVEL 3 WILL CONTAIN THE VALUE OF THE ROOM CURRENTLY CONTROLING THE VCR *) (* LEVEL 4 WILL CONTAIN THE VALUE OF THE ROOM CURRENTLY CONTROLING THE WIRELESS *) (* MICROPHONES. *) (* A VALUE OF 3 INDICATES THAT THE DEVICE IS FREE. *) (**********************************************************************************) vdvCOMM = 33050:1:201 // INTER-ROOM COMMUNICATION (***********************************************************) (* CONSTANT DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_CONSTANT (***********************************************************) (* DATA TYPE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_TYPE (***********************************************************) (* VARIABLE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_VARIABLE PERSISTENT INTEGER cfgROOMNUM // 0=A, 1=B, 2=C VOLATILE INTEGER nROOM_MODE // 0= OFF, 1= PRESENTATION, 2= VTC, // 3= AUDIO ONLY VOLATILE INTEGER nCONFIG_MODE // 0= NORMAL,1=COMBINED W/Room B, 2=COMBINED W/Room B&Room C VOLATILE INTEGER nB_STATUS // 0=IDLE, 1=IN USE VOLATILE INTEGER nC_STATUS // 0=IDLE, 1=IN USE (***********************************************************) (* LATCHING DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_LATCHING (***********************************************************) (* MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_MUTUALLY_EXCLUSIVE (***********************************************************) (* SUBROUTINE/FUNCTION DEFINITIONS GO BELOW *) (***********************************************************) (* EXAMPLE: DEFINE_FUNCTION <RETURN_TYPE> <NAME> (<PARAMETERS>) *) (* EXAMPLE: DEFINE_CALL '<NAME>' (<PARAMETERS>) *) DEFINE_FUNCTION ALL_OFF () { IF (VTC_STATUS = cfgROOMNUM) { SEND_COMMAND vdvTandberg,'HOOK=0:ON' SEND_LEVEL vdvCOMM,1,3 } IF (DVD_STATUS = cfgROOMNUM) { SEND_LEVEL vdvCOMM,2,3 } IF (VCR_STATUS = cfgROOMNUM) { SEND_LEVEL vdvCOMM,3,3 } IF (WIRELESS_STATUS = cfgROOMNUM) { SEND_LEVEL vdvCOMM,4,3 } SEND_COMMAND vdvTP,'PAGE-Logo' SEND_COMMAND vdvTP,'PPON-Shutdown' WAIT_UNTIL (nPROJECTOR1_POWER = 0) { nCONFIG_MODE = 0 SEND_COMMAND vdvTP,'PPOF-Shutdown' } } (***********************************************************) (* STARTUP CODE GOES BELOW *) (***********************************************************) DEFINE_START (***********************************************************) (* THE EVENTS GO BELOW *) (***********************************************************) DEFINE_EVENT BUTTON_EVENT[vdvTP,21] // VTC RESERVE { PUSH: { IF (VTC_STATUS=cfgROOMNUM) // IF ALREADY SELECTED, DESELECT { SEND_LEVEL vdvCOMM,1,3 SEND_STRING dvMixer,"'#70 MACRO 2',13" // DISABLE 430 VTC } ELSE { IF (VTC_STATUS=3) // IF AVAILABLE, SELECT SEND_STRING dvMixer,"'#70 MACRO 1',13" // DISABLE 430 VTC { SEND_LEVEL vdvCOMM,1,cfgROOMNUM } } } RELEASE: { } } BUTTON_EVENT[vdvTP,22] // DVD RESERVE { PUSH: { IF (DVD_STATUS=cfgROOMNUM) // IF ALREADY SELECTED, DESELECT { SEND_LEVEL vdvCOMM,2,3 } ELSE { IF (DVD_STATUS=3) // IF AVAILABLE, SELECT { SEND_LEVEL vdvCOMM,2,cfgROOMNUM } } } RELEASE: { } } BUTTON_EVENT[vdvTP,23] // VCR RESERVE { PUSH: { IF (VCR_STATUS=cfgROOMNUM) // IF ALREADY SELECTED, DESELECT { SEND_LEVEL vdvCOMM,3,3 } ELSE { IF (VCR_STATUS=3) // IF AVAILABLE, SELECT { SEND_LEVEL vdvCOMM,3,cfgROOMNUM } } } RELEASE: { } } BUTTON_EVENT[vdvTP,24] // WIRELESS RESERVE { PUSH: { IF (WIRELESS_STATUS=cfgROOMNUM) // IF ALREADY SELECTED, DESELECT { SEND_LEVEL vdvCOMM,4,3 SEND_STRING dvMixer,"'#70 MACRO 4',13" // DISABLE 430 WIRELESS } ELSE { IF (WIRELESS_STATUS=3) // IF AVAILABLE, SELECT { SEND_LEVEL vdvCOMM,4,cfgROOMNUM SEND_STRING dvMixer,"'#70 MACRO 3',13" // ENABLE 430 WIRELESS } } } RELEASE: { } } BUTTON_EVENT[vdvTP,28] // INDIVIDUAL MODE SELECTED { PUSH: { } RELEASE: { nCONFIG_MODE = 0 MIC_MODE = 0 AUDIO_INDIVIDUAL_MODE() OFF[vdvTP,8] // MICS UNMUTED } } BUTTON_EVENT[vdvTP,29] // Combined MODE with Room B SELECTED { PUSH: { } RELEASE: { MIC_MODE = 0 IF (nB_STATUS) // Room B IN USE { SEND_COMMAND vdvTP,'PPON-Room B Busy' WAIT 100 { SEND_COMMAND vdvTP,'@PPX' SEND_COMMAND vdvTP,'PAGE-[Room Setup]Mode 3' } } ELSE { nCONFIG_MODE = 1 SEND_COMMAND vdvTP,'@PPX' SEND_COMMAND vdvTP,'PAGE-Main Page' SEND_COMMAND vdvTP,'PPON-[Nav 7]Nav 7' ON[vdvCOMM,1] AUDIO_COMBINED_AB_MODE () OFF[vdvTP,8] // MICS UNMUTED } } } BUTTON_EVENT[vdvTP,30] // Combined MODE with Both SELECTED { PUSH: { } RELEASE: { MIC_MODE = 0 IF (nB_STATUS) // Room B IN USE { SEND_COMMAND vdvTP,'PPON-Room B Busy' WAIT 100 { SEND_COMMAND vdvTP,'@PPX' SEND_COMMAND vdvTP,'PAGE-[Room Setup]Mode 3' SEND_COMMAND vdvTP,'PPON-[Nav 7]Nav 7' } } ELSE { IF (nC_STATUS) // Room C IN USE { SEND_COMMAND vdvTP,'PPON-Room C Busy' WAIT 100 { SEND_COMMAND vdvTP,'@PPX' SEND_COMMAND vdvTP,'PAGE-[Room Setup]Mode 3' SEND_COMMAND vdvTP,'PPON-[Nav 7]Nav 7' } } ELSE { nCONFIG_MODE = 2 SEND_COMMAND vdvTP,'@PPX' SEND_COMMAND vdvTP,'PAGE-Main Page' SEND_COMMAND vdvTP,'PPON-[Nav 7]Nav 7' ON[vdvCOMM,1] ON[vdvCOMM,2] AUDIO_COMBINED_ABC_MODE() OFF[vdvTP,8] // MICS UNMUTED } } } } BUTTON_EVENT[vdvTP,41] // DVD SELECTED { PUSH: { ON[vdvTP,41] } RELEASE: { IF (DVD_STATUS = 3) { DO_PUSH (vdvTP,22) } IF (DVD_STATUS = cfgROOMNUM OR DVD_STATUS = 3) { SEND_COMMAND vdvTP,'@PPX' // CLEAR POPUPS SEND_COMMAND vdvTP,'PAGE-[DVR]DVR' SEND_COMMAND vdvTP,'PPON-[Nav 7]Nav 7' SWITCH (nCONFIG_MODE) { CASE 0: // INDIVIDUAL MODE { AVSWITCH2_TIE (1,3) IF (nPROJECTOR1_INPUT <> 8) { nPROJECTOR1_INPUT = 8 SET_PROJECTOR1_INPUT(nPROJECTOR1_INPUT) } } CASE 1: // COMBINED WITH B { AVSWITCH2_TIE (1,3) IF (nPROJECTOR1_INPUT <> 8) { nPROJECTOR1_INPUT = 8 SET_PROJECTOR1_INPUT(nPROJECTOR1_INPUT) } AVSWITCH2_TIE (1,2) IF (nPROJECTOR2_INPUT <> 8) { nPROJECTOR2_INPUT = 8 SET_PROJECTOR2_INPUT(nPROJECTOR2_INPUT) } } CASE 2: // COMBINED WITH B AND C { AVSWITCH2_TIE (1,3) IF (nPROJECTOR1_INPUT <> 8) { nPROJECTOR1_INPUT = 8 SET_PROJECTOR1_INPUT(nPROJECTOR1_INPUT) } AVSWITCH2_TIE (1,2) IF (nPROJECTOR2_INPUT <> 8) { nPROJECTOR2_INPUT = 8 SET_PROJECTOR2_INPUT(nPROJECTOR2_INPUT) } AVSWITCH2_TIE (1,1) IF (nPROJECTOR3_INPUT <> 8) { nPROJECTOR3_INPUT = 8 SET_PROJECTOR3_INPUT(nPROJECTOR3_INPUT) } } } } } } LEVEL_EVENT[vdvCOMM,1] // STATUS OF VTC { VTC_STATUS = LEVEL.VALUE IF (VTC_STATUS = cfgROOMNUM OR VTC_STATUS = 3) { SEND_COMMAND vdvTP,'^ICO-2,1&2,0' // NO ICON, DEVICE IS AVAILABLE } ELSE { SEND_COMMAND vdvTP,'^ICO-2,1&2,1' // NOT ICON, DEVICE IS not AVAILABLE } } LEVEL_EVENT[vdvCOMM,2] // STATUS OF DVD { DVD_STATUS = LEVEL.VALUE IF (DVD_STATUS = cfgROOMNUM OR DVD_STATUS = 3) { SEND_COMMAND vdvTP,'^ICO-41,1&2,0' // NO ICON, DEVICE IS AVAILABLE } ELSE { SEND_COMMAND vdvTP,'^ICO-41,1&2,1' // NOT ICON, DEVICE IS not AVAILABLE } } LEVEL_EVENT[vdvCOMM,3] // STATUS OF VCR { VCR_STATUS = LEVEL.VALUE IF (VCR_STATUS = cfgROOMNUM OR VCR_STATUS = 3) { SEND_COMMAND vdvTP,'^ICO-42,1&2,0' // NO ICON, DEVICE IS AVAILABLE } ELSE { SEND_COMMAND vdvTP,'^ICO-42,1&2,1' // NOT ICON, DEVICE IS not AVAILABLE } } LEVEL_EVENT[vdvCOMM,4] // STATUS OF WIRELESS { WIRELESS_STATUS = LEVEL.VALUE IF (WIRELESS_STATUS = cfgROOMNUM OR WIRELESS_STATUS = 3) { SEND_STRING dvMixer,"'#70 MACRO 3',13" //ENABLE WIRELESS IN 430 } ELSE { SEND_STRING dvMixer,"'#70 MACRO 4',13" //DISABLE WIRELESS IN 430 } } CHANNEL_EVENT[vdvCOMM,11] // ROOM B STATUS { ON: { nB_STATUS = 1 // ROOM IS BUSY } OFF: { nB_STATUS = 0 // IN AVAILABLE MODE } } CHANNEL_EVENT[vdvCOMM,12] // ROOM C STATUS { ON: { nC_STATUS = 1 // ROOM IS BUSY } OFF: { nC_STATUS = 0 // IN AVAILABLE MODE } } (***********************************************************) (* THE ACTUAL PROGRAM GOES BELOW *) (***********************************************************) DEFINE_PROGRAM (***********************************************************) (* END OF PROGRAM *) (* DO NOT PUT ANY CODE BELOW THIS COMMENT *) (***********************************************************)Danny, thanks for the example, much clear how to do it now.
What generate the channel event?
I searched anywhere for info on levels and channel, and there very basic informaion on this topics...
It works just like normal channel events. Any of the masters in the system with the virtual device defined can make changes to channels and levels.