Home AMX User Forum NetLinx Studio

REBUILD_EVENT Problems

First, here is the code:
define_function fnInitFavDevice(dev myFBDev,
								dev myControlDev,integer myDevIndex,
								integer myEnterChan, integer myDashChan,
								char myFileName[], integer myDevType){
	nFavDevInsertPtr++
	if(nFavDevInsertPtr and nFavDevInsertPtr < 31){
		vdvFbBoxes[nFavDevInsertPtr] = myFBDev;
		dvBoxes[nFavDevInsertPtr] = myControlDev;
		nBoxMode[nFavDevInsertPtr] = myDevIndex;
		nDevDashBtn[myDevIndex] = myDashChan;
		nDevEnterBtn[myDevIndex] = myEnterChan;
		nDevType[myDevIndex] = myDevType;
		sDevFilenames[myDevIndex] = myFileName;
		wait 30 REBUILD_EVENT(); //This should fix the channel event to populate favs on devices as they are selected.
		#warn 'Check here if probs when selecting devices with favs';
		fnReadFromFile(myDevIndex);
	}
	
} 	

Now the problem... As you see, I put in a wait 30 in front of the REBUILD_EVENT command to try and fix things. This function is called 3 to 10 times at boot (depending on the job). When this is called, the processor seems to hang for 10 minutes or more. It is really just rebuilding the events as far as I can tell. I had to severely delay the call of this function because it was causing the processor to miss a bunch of the commands sent to modules in the device ONLINE event. This meant a bunch of settings for the modules were lost and the modules did not initialize properly.

Does anyone have any tips for taming the REBUILD_EVENTS command? From the documentation, I thought that it was restricted to the variable(s) within the {}s that contain it, but it seems like it must be rebuilding everything with the time it is taking.

Any help is appreciated,
Jeff

Comments

  • viningvining Posts: 4,368
    Have you tried to use the wait 30 to call the functiuon fnInitFavDevice and then eliminate the wait inside the function for REBUILD_EVENT(). Wait 30 also seems short for init type stuff. I often wait a minute or more before running init type stuff.

    Was REBUILD_EVENT() taking along time when using the wait or when not using the wait? I've never used a wait with rebuild_event so I wonder if it sees the braces with the wait in place, when it executes maybe it can't see above the wait and if it doesn't see anything specific to rebuild maybe then it goes ahead and rebuilds all the event tables?
  • Spire_JeffSpire_Jeff Posts: 1,917
    Ok, I changed to the following:
    define_function fnInitFavDevice(dev myFBDev,
    								dev myControlDev,integer myDevIndex,
    								integer myEnterChan, integer myDashChan,
    								char myFileName[], integer myDevType, integer doRebuild){
    	nFavDevInsertPtr++
    	if(nFavDevInsertPtr and nFavDevInsertPtr < 31){
    		vdvFbBoxes[nFavDevInsertPtr] = myFBDev;
    		dvBoxes[nFavDevInsertPtr] = myControlDev;
    		nBoxMode[nFavDevInsertPtr] = myDevIndex;
    		nDevDashBtn[myDevIndex] = myDashChan;
    		nDevEnterBtn[myDevIndex] = myEnterChan;
    		nDevType[myDevIndex] = myDevType;
    		sDevFilenames[myDevIndex] = myFileName;
    		#warn 'Check here if probs when selecting devices with favs';
    		fnReadFromFile(myDevIndex);
    	}
    	if(doRebuild){
    		send_string 0,"'Starting REBUILD_EVENT ',TIME";
    		{
    		set_length_array(vdvFbBoxes,nFavDevInsertPtr);
    		REBUILD_EVENT();
    		}
    		send_string 0,"'REBUILD_EVENT completed ',TIME";
    	}
    } 	
    

    As for the wait 30, I was using that to prevent multiple REBUILD_EVENT runs. The code that calls the function uses a wait 3000 which starts after the virtual device comes online. When that happens, it calls the function a bunch of times, and I wanted to rebuild only after the last change to the array. I changed my function to reflect this. I also added the send_string 0 commands to get an actual runtime. Here is the readout from the diagnostics window:
    Line   1696 (14:41:21.343)::  READ From File FAILED! $96 Result = -2
    Line   1697 (14:41:21.343)::  READ From User File FAILED! $96 Result = -2
    Line   1698 (14:41:21.359)::  Starting REBUILD_EVENT 16:09:45
    Line   1699 (14:42:49.375)::  DDD.physicalDeviceOffline: 97:1:0 is offline
    Line   1700 (14:44:07.062)::  DDD.handleTimerEvent: dpd didn't exist
    Line   1701 (14:45:41.750)::  DDD.physicalDeviceOffline: 97:1:0 is offline
    Line   1702 (14:45:42.734)::  LutronHomeworksp5: Processing Exception: null
    Line   1703 (14:45:44.140)::  CarrierInfinity: Timer expired for command <S1MODE?> 3 consecutive times. Reinitializing...$0A
    Line   1704 (14:45:44.546)::  Carrier Infinity RS232 controlled 5012:1:1
    Line   1705 (14:45:44.968)::  TSET BAUD 9600,N,8,1 485 DISABLE
    Line   1706 (14:45:46.953)::  CarrierInfinity: Timer expired for command <S1MODE?> 3 consecutive times. Reinitializing...$0A
    Line   1707 (14:45:47.062)::  Carrier Infinity RS232 controlled 5012:2:1
    Line   1708 (14:45:47.250)::  TSET BAUD 9600,N,8,1 485 DISABLE
    Line   1709 (14:48:39.593)::  REBUILD_EVENT completed 16:17:03
    Line   1710 (14:48:42.968)::  Memory Available = 12474256 <69576>
    Line   1711 (14:48:43.140)::  Connected Successfully
    

    As you can see, the REBUILD is taking almost 8 minutes. During this time, no NetLinx code is executed, but it seems that the Java code keeps on ticking (the Carrier is a Duet module).

    Any thoughts?

    Also, here is the calling code, in case this helps:
    DATA_EVENT[vdvLoadSettings]{
    	online:{
    		wait 3000{
    /*
    	This is where you define the types of devices being used. You can implement 30 devices (with limitations).
    	for more info, consult the configuration manual. 
    	
    	fnInitFavDevice(vdvDevice12FB,dvDevice12,nCable1DevIndex,0,0,'CABLE_FAVS',nDevTypeCable);
    	
    	The first parameter is the virtual device from the UI processor that indicates when control 
    		for the actual device is active.
    		
    	The second parameter is the device used to control the actual device. For IR controlled devices,
    		this should be the actual device port. For devices controlled by a module, this should be
    		the virtual device of the module (These devices must be supported to function properly).
    		
    	The third parameter is the device index. This indicates how the device is controlled and the 
    		multiple instances of each device type are to allow multiple favorite files. If each box 
    		is dedicated for use by a specific person, then use a separate index for each box. If all
    		boxes are available to everyone and the favorites should be common to all boxes, use
    		instance 1 of the correct type for all devices. You can also use a combination of the two.
    		*** Radio devices are all set to the same list of favorites. Use the user buttons to define
    			individual favorites for each person in the house. (Can be modified with some coding,
    			look in Configuration manual for details)
    		The valid values are:
    			nCable1DevIndex 
    			nCable2DevIndex 
    			nCable3DevIndex 
    			nCable4DevIndex 
    			nCable5DevIndex 
    			nCable6DevIndex 
    			nSat1DevIndex 	
    			nSat2DevIndex 	
    			nSat3DevIndex 	
    			nSat4DevIndex 	
    			nSat5DevIndex 	
    			nSat6DevIndex 	
    			nRadio1DevIndex   	=  	Russound ST2_  AM/FM mode
    			nRadio2DevIndex   	=	Integra TUN3.7
    			nRadio3DevIndex   	= 	Future Use
    			nSirius1DevIndex	=	Russound ST2S Sirius/XM Mode
    			nSirius2DevIndex	= 	Sirius SCH-P2 Tuner
    			nSirius3DevIndex	=	Future Use
    			n232Sat1DevIndex
    			n232Sat2DevIndex
    			n232Sat3DevIndex
    			n232Sat4DevIndex
    			n232Sat5DevIndex
    			n232Sat6DevIndex
    
    	The fourth parameter is the channel number of the IR command to be used as an Enter Button.
    		Set this to 0 if you do not require an enter button after a channel number is entered.
    		
    	The fifth parameter is the channel number of the IR command to be used as the Dash/Period.
    		Set this to zero if there is no Dash/Period required when entering HD channels.
    		
    	The sixth parameter is the file name you want to use to save favorites. This should be unique
    		between the different index types. The last instance of an index initialized will dictate
    		the filename used.
    		
    	The seventh parameter indicates which file is used to populate the favorite channel dialogs.
    		Consult the configuration manual for the file names of the csv data used by each value.
    		These must be set for the service area of the house, or the channel information will be 
    		wrong.
    		Valid values are:
    				nDevTypeCable 	
    				nDevTypeDirecTV	
    				nDevTypeDishNet	
    				nDevTypeSirius 	
    				nDevTypeRadio	
    				nDevTypeCustom1	
    				nDevTypeCustom2	
    				nDevTypeCustom3	
    	
    */
    			fnInitFavDevice(vdvDevice12FB,dvDevice12,nSat1DevIndex,0,0,'SAT_FAVS',nDevTypeDirecTV,0);
    			fnInitFavDevice(vdvDevice13FB,dvDevice13,nSat1DevIndex,0,0,'SAT_FAVS',nDevTypeDirecTV,0);
    			fnInitFavDevice(vdvDevice14FB,dvDevice14,nSat1DevIndex,0,0,'SAT_FAVS',nDevTypeDirecTV,0);
    			fnInitFavDevice(vdvDevice15FB,dvDevice15,nSat1DevIndex,0,0,'SAT_FAVS',nDevTypeDirecTV,0);
    			fnInitFavDevice(vdvDevice16FB,dvDevice16,nSat1DevIndex,0,0,'SAT_FAVS',nDevTypeDirecTV,0);
    			fnInitFavDevice(vdvDevice17FB,dvDevice17,nSat2DevIndex,0,0,'SAT_MUSIC_FAVS',nDevTypeDirecTV,0);
    			fnInitFavDevice(vdvDevice22FB,dvDevice22,nSat1DevIndex,0,0,'SAT_FAVS',nDevTypeDirecTV,1);
    
    		}
    	}
    }
    

    Thanks,
    Jeff
  • a_riot42a_riot42 Posts: 1,624
    In the code you have posted, I don't see the event that requires the use of rebuild_event. Are you sure you even need to use it? Where are you modifyng a variable in an event declaration?
    Paul
  • Spire_JeffSpire_Jeff Posts: 1,917
    Here is the event that I believe needs the REBUILD_EVENT:
    CHANNEL_EVENT[vdvFbBoxes,nTP_CHANS]{
    	ON:{
    		STACK_VAR INTEGER nTPINDEX;
    		nTPINDEX = CHANNEL.CHANNEL;
    		if(!nCurUser[nTPINDEX])
    			nCurUser[nTPINDEX] = 1;
    		fnPopulateFavs(dvTP_SRC[nTPINDEX],getFavDevIndex(nTPINDEX),nTPINDEX);
    	}
    }
    

    I think I need it because the devices are set in code, not in the variable declaration. The code is not run until after the processor has booted, but it is not changed on the fly. Based on the code, the compiler could make a good guess at what is going to be in the variables as it would not change from compile time to execution, I just didn't think the compiler did that much optimization.

    Jeff
  • AuserAuser Posts: 506
    Spire_Jeff wrote: »
    The code that calls the function uses a wait 3000 which starts after the virtual device comes online.

    = 5 minutes. Is that what you intended, or only 30 seconds?

    You may also want to try moving the rebuild event statement for the affected device out to a function along with the equate in an attempt to reduce the scope of the event table changes:
    define_function SetFbBoxDevice(integer nIndex, dev dvDevice)
    {
      vdvFbBoxes[nIndex] = dvDevice;
      rebuild_event();
    }
    
  • a_riot42a_riot42 Posts: 1,624
    Spire_Jeff wrote: »
    I think I need it because the devices are set in code, not in the variable declaration. The code is not run until after the processor has booted, but it is not changed on the fly. Based on the code, the compiler could make a good guess at what is going to be in the variables as it would not change from compile time to execution, I just didn't think the compiler did that much optimization.

    Jeff

    Why are they set in code if they never change?
    Paul
  • Spire_JeffSpire_Jeff Posts: 1,917
    a_riot42 wrote: »
    Why are they set in code if they never change?
    Paul

    They change from job to job and when a client adds/removes devices. This more about convenience for me and others and if it really takes this long to rebuild the events, I can live with it. I just wanted to make sure I am not doing something wrong. Now that I have it so the processor isn't broken because of the code, I can wait the extra few minutes as it only occurs during the boot sequence.
    auser wrote:
    = 5 minutes. Is that what you intended, or only 30 seconds?

    I did intend for 5 minutes. The processor takes some time to boot and I wanted to make sure I was well past the point of other boot code executing. I had problems when the rebuild happened too soon (mainly, modules that are passed parameters never receiving the parameters).

    Jeff
  • a_riot42a_riot42 Posts: 1,624
    If you leave out the rebuild_event call does something break?
    Paul
  • Spire_JeffSpire_Jeff Posts: 1,917
    As I recall, the event I posted did not trigger. That was when I remembered rebuild_event and it started working. I also made some other changes (that I recall being unrelated to the event in question), so there is a possibility that something else I did fixed the problem. If I have some time in the next 40 hours, I will try it here, but I am out of town and out of time :) I will probably also speak with tech support tomorrow and I will post anything I learn that may be of use to others.

    Thanks for all of the help. In the least, this thread forced me to rewrite the function to only run rebuild_events once and (according to documentation) on the appropriate variable.

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Instead of using a:
    WAIT x

    You might want to consider a:
    WAIT_UNTIL (nInitialized)

    Where nInitialized is a variable that is set to 1 when you know your other startup code is ready to go.

    You might also want to consider offloading the DUET modules to another processor and see if that helps.

    I don’t know enough about your code but you may also want to look at using preprocessor directives if you haven’t already. Something like:
    #define __LUTRON__
    //#define __VANTAGE__
    
    
    #if_defined __LUTRON__
    //lutron code
    #end_if
    
    #if_defined __VANTAGE__
    //vantage code
    #end_if
    
  • a_riot42a_riot42 Posts: 1,624
    Spire_Jeff wrote: »
    As I recall, the event I posted did not trigger.


    I would have thought that as long as the variable didn't change, it would still work.

    The other alternative would be to leave the array in question alone and track it a different way using another array of integers. This is what I typically do. I don't like to mess with the event table at runtime so rather than manipulate devices in arrays that are also used in event declarations, I manipulate an array of integers that corresponds to the array of devices. This may be hard to refactor into a running system though without a lot of work.
    Paul
  • annuelloannuello Posts: 294
    It's interesting that your initial code example used a 3 second delay. One of my modules had a similar problem but it was calling timeline_reload() early after a bootup. Perhaps timeline_reload() calls rebuild_event() behind the scenes? In my case, the master would lock up and not come good even after several hours. A wait 30 before calling timeline_reload() avoided the lockup. (I played around with various wait times, and settled on 3 seconds.)

    IIRC there was an interesting quirk with the lockup, in that it would not occur on the reboot immediately after after a code transfer, but would occur on subsequent reboots. Bizarre.

    Roger McLean
    Swinburne University
Sign In or Register to comment.