Define_Event vs Define_Program

John PaulJohn Paul Junior MemberPosts: 143
I have to check the feedback of a device and it has to be constantly updated over different masters. So i put it up under define_program section. Now the master seems to go offline and then all the commands goes as in queue. Now i can also put the feedback section in the string part of data_event

What is the use of define_program?
what are the advantages of it over define_event?
if you need to update the feedback based on a change do u put it up in define_program or data_event

Comments

  • Spire_JeffSpire_Jeff Formerly Caffeinated Programmer Posts: 1,917
    My personal preference is to put feedback related to incoming data into the string event, especially if the update requires strings to be sent to the panel(s). I do tend to track the feedback data in a variable and when a panel comes online, or switches to the device in question, I will update the feedback based on the stored information.

    That being said, I have also used the define_program section for some feedback. The ONLY feedback I put in define_program is channel related. (ie. [dvTp,1] = [vdvDVD,PLAY]). Netlinx only sends channel feedback if the state changes.

    The advantage to using define_program is that it is less coding. The disadvantage is that depending on what you do, it can be very easy to send to much data and lock up panels or the processor.

    Jeff
  • John PaulJohn Paul Junior Member Posts: 143
    Thanks Jeff

    These are the two feedback options which i have put up in the define_program section . Here there are 6 controllers and about 25 touch panels.

    1. Tango feedback.
    I keep track of the 8 audio sources and 32 rooms which can have any of them and i update the audio maps in the panels over the house.
    DEFINE_PROGRAM
    [virtualTPFLRTangoSwt,nRoomAudioStatusSource1buttons[1]]=_sRoom[1].nInput=1
    [virtualTPFLRTangoSwt,nRoomAudioStatusSource2buttons[1]]=_sRoom[1].nInput=2
    [virtualTPFLRTangoSwt,nRoomAudioStatusSource3buttons[1]]=_sRoom[1].nInput=3
    [virtualTPFLRTangoSwt,nRoomAudioStatusSource4buttons[1]]=_sRoom[1].nInput=6
    [virtualTPFLRTangoSwt,nRoomAudioStatusSource5buttons[1]]=_sRoom[1].nInput=5
    [virtualTPFLRTangoSwt,nRoomAudioStatusSource6buttons[1]]=_sRoom[1].nInput=4
    [virtualTPFLRTangoSwt,nRoomAudioStatusSource7buttons[1]]=_sRoom[1].nInput=7
    [virtualTPFLRTangoSwt,nRoomAudioStatusSource8buttons[1]]=_sRoom[1].nInput=8

    ....

    2. Lutron homeworks feeedback
    For the 32 rooms, i update the lights feedback based on which button in the lutron virtual or real keypad is pressed. There are maximum 2 processors, 4 links, 32 keypad address and 25 buttons on the lutron keypads. This throws up a null pointer error in diagnostic. for example
    Line 235 (20:56:45):: SetVariable - Error 1 Tk=0x0000
    Line 236 (20:56:45):: Ref Error ^LEDS Index to large
    Line 237 (20:56:45):: Ref Error ^LEDS Null Pointer
    Line 238 (20:56:45):: Ref Error ^LEDS Null Pointer
    Line 239 (20:56:45):: SetVariable - Error 1 Tk=0x0000
    Line 240 (20:56:45):: Ref Error ^LEDS Index to large
    Line 241 (20:56:45):: Ref Error ^LEDS Null Pointer
    Line 242 (20:56:45):: Ref Error ^LEDS Null Pointer
    Line 243 (20:56:45):: SetVariable - Error 1 Tk=0x0000
    Line 244 (20:56:45):: Ref Error ^LEDS Index to large

    DEFINE_PROGRAM


    //Basement lobby
    [dvTP_LutronBasementARRAY,1] = LEDS [2] [4] [1] [1] // this is the KP address, will be different for wireless


    [dvTP_LutronBasementARRAY,2] = LEDS [2] [4] [1] [2] // this is the KP address, will be different for wireless


    [dvTP_LutronBasementARRAY,3] = LEDS [2] [4] [1] [3] // this is the KP address, will be different for wireless


    [dvTP_LutronBasementARRAY,4] = LEDS [2] [4] [1] [4] // this is the KP address, will be different for wireless

    [dvTP_LutronBasementARRAY,5] = LEDS [2] [4] [1] [5] // this is the KP address, will be different for wireless

    [dvTP_LutronBasementARRAY,6] = LEDS [2] [4] [1] [6] // this is the KP address, will be different for wireless
  • Spire_JeffSpire_Jeff Formerly Caffeinated Programmer Posts: 1,917
    First the tango. Personally, I would create a timeline that fires every second (at the fastest) and use a for() loop to go through the feedback. I don't know that you will see any performance difference in that tho.

    As for the Lutron, I would check the parsing you are doing and the variable declaration. If the variable declaration is at least: volatile integer LEDS[2][6][32][24] and the parsing routine looks correct, there might be extraneous data coming in the is matching the conditions for LED updates. You can add checks to make sure that the array pointers you are using fall within the bounds of the array. Here is an example:
    					REMOVE_STRING(cINC_DATA_LUTRON, 'KLS, [', 1) 
    					
    					nHWI_PROC = ATOI(REMOVE_STRING(cINC_DATA_LUTRON, ':', 1)) 
    					nHWI_LINK = ATOI(REMOVE_STRING(cINC_DATA_LUTRON, ':', 1)) 
    					nHWI_KP = ATOI(REMOVE_STRING(cINC_DATA_LUTRON, '], ', 1)) 
    					if(nHWI_PROC and nHWI_LINK and nHWI_KP){
    						FOR(nBTN_CNTR = 1;nBTN_CNTR<=24;nBTN_CNTR++)
    						{
    							cHWI_BTN_VALUE = GET_BUFFER_STRING(cINC_DATA_LUTRON,1)
    							nHWI_BUTTONS[nHWI_PROC][nHWI_LINK][nHWI_KP][nBTN_CNTR] =  ATOI(cHWI_BTN_VALUE)
    						}
    					}
    

    Jeff
  • John PaulJohn Paul Junior Member Posts: 143
    This is the function for which the lutron parsing is done in my code, i will modify it according to your code.

    define_function TESTkp(char buff[])
    //lutron sent: $0D$0AKLS, [01:06:02], 000000000000000000000000$0D$0A

    {
    stack_var char temp[30]

    stack_var char tProc[5]
    stack_var char tLink[5]
    stack_var char tKP [5]
    stack_var char tBtns [35]

    stack_var integer btn

    stack_var integer arr_proc
    stack_var integer arr_link
    stack_var integer arr_kp
    stack_var integer arr_btn
    stack_var integer arr_status

    temp = remove_string(buff, 'KLS, [', 1)

    // Only care about LED feedback
    if (!length_string(temp))
    {
    return
    }
    tProc = remove_string(buff, ':', 1) // get Processor #
    set_length_string(tProc, length_string(tProc) - 1)
    arr_proc = ATOI(tProc)

    tLink = remove_string(buff, ':', 1) // get Link #
    set_length_string(tLink, length_string(tLink) - 1)
    arr_link = ATOI(tLink)

    tKP = remove_string(buff, '], ', 1) // get KP #
    set_length_string(tKP, length_string(tKP) - 3)
    arr_kp = ATOI(tKP)

    tBtns = remove_string(buff, "$0D" , 1) // get Btn string

    set_length_string(tBtns, length_string(tBtns) - 2)
    // SEND_STRING 0,"'tBtns=',tBtns"
    // SEND_STRING 0,"'arr_kp=',ITOA(arr_kp)"
    // could nest next section within loops for links and processors if required
    FOR(J=1;J<=24;J++) // buttons on KP
    {
    LEDS [arr_proc] [arr_link] [arr_kp] [J] = ATOI(MID_STRING(tBtns,J,1)) // possible states of lutron buttons
    //SEND_STRING 0,"'LEDS [arr_proc] [arr_link] [arr_kp] [J] =',tProc,' ,',tLink,' ,',tKP,' ,',itoa(J),' '"

    }
    //SEND_STRING 0,"'LEDS [2] [4] [5] [15] =',itoa(LEDS [2] [4] [5] [15]),' '"

    }


    Also for the tango when do i need to fire the timeline ?
  • John PaulJohn Paul Junior Member Posts: 143
    Thanks Jeff for the suggestions. Also i had declare the variable
    INTEGER LEDS [2] [4] [32] [25] // change as needed for multiple processors, new links, etc.

    i will declare the variable as volatile from now on
  • Spire_JeffSpire_Jeff Formerly Caffeinated Programmer Posts: 1,917
    John Paul wrote: »
    Also for the tango when do i need to fire the timeline ?

    I would start the timeline as soon as the first touch panel comes online and stop it when all touch panels are offline. (or if you want to get fancy, only start it when a touch panel is viewing the pages that require the feedback and stop it when no touch panels are viewing the pages)

    Jeff

    P.S.
    There is nothing jumping out as wrong with your parsing code, but you are doing a little extra work that is not necessary. ATOI will ignore nonnumerical characters until it finds the first numerical character. It will then use that character up to the next nonnumerical character.

    There is one potential problem in the LEDS declaration. Are you sure you are only have keypads on link 4? if you have keypads on link 5 or 6, those errors might be generated. Also, why 25 buttons? I am pretty sure that Lutron still has a max of 24 buttons. Remember that every slot in the 4th dimension takes up 2*4*32 spaces and if you never use it, it is wasted space.
  • viningvining X Member Posts: 4,348
    There's an example of using the atoi as Jeff explained here. http://amxforums.com/showthread.php?t=6410&highlight=nLink
    Coincidentally this is for Lutron also but for the dimmer levels "DL" responses. However this post was completely off the mark since I thought they were discussing Lutron when in fact they were discussing the Prog Practical.
  • patbpatb Junior Member Posts: 140
    I've done a lot of master-to-master FB tracking and there are a couple of general guidelines that seem to work. There might be exceptions, but for the most part this has worked for me.

    Always use a timeline for feedback - never use DEFINE_PROGRAM. I have edited my netlinx "new" template to include a FB timelineee (along with other things that I always use)

    Keep track of the feedback in the master where the device in question is actually attached. I use a virtual device to track of the FB. In the case of the Lutron you could have a single virtual "device" for each lighting master processor (if there even are multiple), use a "port" on the device for each keypad, then set the channel on the port on/off depending on the state of the button. So in your define device each keypad has its own "device" which you could assign in a dev array.

    FB inside of the timeline would look something like this : (assuming that you have defined dvTPLights and dvKPArray as dev arrary and omitting the loop structure which obviously would have to be there)

    [dvTPLights[ndx],1] = [dvKPArray[ndx],1]
    [dvTPLights[ndx],2] = [dvKPArray[ndx],2]
    [dvTPLights[ndx],3] = [dvKPArray[ndx],3]
    [dvTPLights[ndx],4] = [dvKPArray[ndx],4]
    [dvTPLights[ndx],5] = [dvKPArray[ndx],5]
    [dvTPLights[ndx],6] = [dvKPArray[ndx],6]
    [dvTPLights[ndx],7] = [dvKPArray[ndx],7]
    [dvTPLights[ndx],8] = [dvKPArray[ndx],8]
    [dvTPLights[ndx],9] = [dvKPArray[ndx],9]
    [dvTPLights[ndx],10] = [dvKPArray[ndx],10]

    You still have to parse the strings coming in to assign the channels on/off, but it's just as easy to assign a channel in a dev array as it is a variable. But you only have to do it ONCE in the actual master where the RS-232 port is connected to the Lutron. You would assign the devices in each local master and have the FB timeline written locally referencing the virtual devices on the main lighting master. PM me if it doesn't make sense - I've done it and it works very well.

    Now in each master you declare the virtual devices in each local master, but you don't have to actually write any code to manage the feedback other than the timeline - it's already done.

    Same logic applies to the audio. The added bonus is that in addition to channels on a virtual device/port that can track the button states you also have levels to track the audio level.

    Added bonus is that by using channels you don't eat up memory that those multi-dimensional variables you are using take up.
Sign In or Register to comment.