Home AMX User Forum NetLinx Studio

Standardization

So after about six years of programming, I'm coming to the conclusion that in order to be even more efficient - I need to start standardizing a lot of aspects of the code. I'm doing a job totally from scratch with this plan I've been working out in my head for the past few months - just now putting it in action.

One of my biggest things I'm having trouble standardizing is the transport list, and I'm wondering if I even should. For example, I know some programmers go the route of breaking up a button event to control a device by source, ex:
button_event[dv_tp,i_dvd_transport]
{
   // handle only dvd controls
}

button_event[dv_tp,i_cable_transport]
{
  // handle only cable controls
}
etc, etc.

I have for years done this:
button_event[dv_tp,i_transport]
{
  push:
  {
    // switch..case followed by available sources, and format strings / commands as needed by the current source
  }
}

I can see the advantages of both. Part of the problem though, is not ALL sources have the same control attributes; for example - cable boxes, VCRs and satellite boxes CAN record while blu-rays cannot (I've yet to see one that does.) Blu-ray, cable boxes and satellite boxes typically have an A,B,C,D button group (or red,yellow,green,blue - or both), however I've not seen this for iPods. So if I were to standardize A,B,C,D as buttons 61, 62, 63, and 64 - these would be blank for iPods as there'd be no equivalent.

I'd like to do this for several reasons. First, when I set up my serial controlled devices, I lay them out just like an IR file where the first string the array is play, second is stop, etc. This way, in my transport section of code, I can just reference the index of the button press (using get_last.) I'm not doing anything revolutionary here, just stuck in as far as how I should go about this to standardize my code. If you have a list you'd like to share for reference, that'd be awesome, or any tips and pointers would be great too.

While I object to a standardized coding style or format proposed in recent months, I personally would less likely object to a standardized "command list." I could see something like a list saying index 1 is always play, index 2 is always stop, etc., etc. helping a lot of people with their code completion.

Lastly, I have a feeling someone is going to say either one of the following: "This is why SNAPI was written." or "Use the G4API." As we all know - what's great for one isn't always great for another. Plus, I feel SNAPI and G4API are a bit too convoluted.

Comments

  • the8thstthe8thst Posts: 470
    I basically pass through the channel numbers from the touch panel file to the end source device. This way I just have to alter 1 or 2 touch panel files if something changes on a source device.

    I use a variable in a simple structure to track which source each touchpanel is currently controlling, a dev array for all source devices, and I also program serial devices to respond like standard IR devices.

    I have found that it is also helpful to use the same channel for all display power and input commands to simplify the power on macros without worrying about which model TV it is or if the input is component 1, 2, hdmi, etc. I aways use non-standard channels of 227, 228, 229, 230. Then I just copy the IR correct IR commands to those locations for each display and don't have to change my power functions. This also works out well when systems are designed by the sales guys and I don't have enough outputs to dedicate an IR output to every device (not that that would ever happen).

    A simplified version of what I do is this:
    iDEFINE_DEVICE
    
    	dvTP1_One	= 10002:1:0
    	dvTP1_Three     = 10002:3:0
    	
    	dvTP2_One 	= 10003:1:0
    	dvTP2_Three     = 10003:3:0
    	
    	dvTP3_One	= 10004:1:0
    	dvTP3_Three     = 10004:3:0
    	
    DEFINE_CONSTANT
    	integer nSourceSelectBtns[] = {
    		101,		// Sat 1
    		102,		// Sat 2
    		103,		// CD
    		104,		// BDP 1 (232)
    		105		// BDP 2 (232)
    	}
    
    	dev dvSourceDevices[] = {
    		dvSat1,
    		dvSat2,
    		dvCD,
    		vdvBluray1,
    		vdvBluray2
    	}
    
    	dev dvAudTPs[] = {
    		dvTP1_One,
    		dvTP2_One,
    		dvTP3_One
    	}
    	
    	dev dvSourceTPs[] = {
    		dvTP1_3,
    		dvTP2_3,
    		dvTP3_3
    	}
    
    
    DEFINE_EVENT
    
    	button_event[dvAudTPs,nSourceSelectBtns] {
    		release: {
    			stack_var integer tpIndex
    			stack_var integer nInput
    			
    			tpIndex = get_last(dvAudTPs)
    			nInput = get_last(nSourceSelectBtns)
    			
    			uTPinfo[tpIndex].input = nInput
    			
    			// do all source switching here
    			// track states and outputs here as well
    		}
    	}
    	
    	button_event[dvSourceTPs,0]
    	{
    		push: {
    			stack_var integer nInput
    			stack_var integer nChan
    			
    			nInput = uTPinfo[get_last(dvSourceTPs)].input
    			nChan = button.input.channel
    			
    			if (nInput) {
    				if (nChan <= 255) {		// if valid IR channel
    					send_command dvSourceDevices[nInput],"'SP',nChan"
    				}
    			}
    		}
    		hold[3,repeat]: {
    			// do the same for repeating functions
    		}
    		release: {
    			stack_var integer nInput
    			
    			nInput = uTPinfo[get_last(dvSourceTPs)].input
    			
    			if (nInput) {
    				send_command dvSourceDevices[nInput],"'IROFF'"
    			}
    		}
    	}
    

    This is a simplified version of what I use. The 232 devices respond to the same 'SP' commands and 'IROFF' commands (clear queue).
  • jjamesjjames Posts: 2,908
    Nice. I too just pass that button number right through to the device, but I assume you write all of your own 232 modules in order to handle the SP command. I like that, however right now there's not enough time to do that. As far as device control, do you have or use a set list of commands? Or are they made up on the fly?

    As I'm sure we all know, we can define our own templates in IREdit with some modification to the Access database that holds them all - this made me think, it'd be pretty slick if we had a 232Edit where it'd be only for serial strings and just drop in the files that we need to read from. Perhaps I'm getting a little too cinematic though for short-term reality. I realize sound & stable systems don't happen overnight and a lot of planning goes into it.
  • the8thstthe8thst Posts: 470
    I wrote a 232_comm module that I use for all basic source equipment. It lets you pass in a prefix, delimiter, and an array of 232 commands. For integra I pass it !2, 13, and an array (PWR01,PLY, etc).

    The array of 232 commands is indexed to match the standard IRedit templates.

    Then when I create the touch panel file I just have IRlite open in the corner of the monitor to reference my channel numbers with. My standard TP template then contains a few different bluray pages ( ie [Bluray]Integra, [Bluray]Sony, etc) and I enter the bluray manufacturer into the main program which controls the page flips.

    I also have separate pages named [Cable]SciAtlanta, [Cable]Motorola, [Cable]DirecTV, etc.

    Modifying channel numbers in touch panel files works really well and goes fast when you need to make changes or create a new page for a new device. I even have 1 installer trained enough that he can pull a TP file from the panel, create a new IR file, modify TP channels, and download everything when a customer changes source equipment.

    It is nice knowing that I don't have to change any programming if the homeowner changes bluray brands or switches from satellite to cable.

    I do have standard IR files that I reuse for every job that cover most of our commonly used sources too.
  • DHawthorneDHawthorne Posts: 4,584
    AMX created an API for this when VA came out, and it has since been refined for Duet and AMX.home. But in the process of creating a standard that necessarily must cover a lot of different devices, the standard itself became so cumbersome that I lost patience with it altogether. It's quicker and easier just to pass the button channel to the IR device. Conforming to the Duet API might make everything completely interchangeable, but that's not even how AMX publishes IR files. In the end, I just couldn't be bothered when it only takes a few minutes to change devices anyway. I spend more time switching and creating buttons for functions that aren't shared than I do switching the IR.
  • ericmedleyericmedley Posts: 4,177
    "The great thing about standards is there are SO many to choose from..." ~ me
  • jjamesjjames Posts: 2,908
    the8thst wrote: »
    Then when I create the touch panel file I just have IRlite open in the corner of the monitor to reference my channel numbers with. My standard TP template then contains a few different bluray pages ( ie [Bluray]Integra, [Bluray]Sony, etc) and I enter the bluray manufacturer into the main program which controls the page flips.

    I also have separate pages named [Cable]SciAtlanta, [Cable]Motorola, [Cable]DirecTV, etc.

    I've been thinking about doing this - but of course there is so little time right now to make things super shiny, that I just need to make it shiny and be done.
    DHawthorne wrote: »
    Conforming to the Duet API might make everything completely interchangeable, but that's not even how AMX publishes IR files.
    True, but how do you think they do it in MeetingRoom?
  • truetrue Posts: 307
    Mine is something like so:
    define_constant
    TP_COUNT = 1
    
    define_device
    dev1 = 5001:9:0
    dev2 = 5001:10:0
    dev3 = 34108:1:0
    
    ctl_tp1 = 10001:1:0
    
    define_variable
    volatile integer ctl_active[TP_COUNT]
    volatile dev ctl_devs[] = {
        dev1, dev2, dev3
    }
    volatile dev ctl_tp[] = {
        ctl_tp1
    }
    
    define_event
    button_event[ctl_tp, 0] {
        push: {
            if (ctl_active[get_last(ctl_tp)]) {
                to[ctl_devs[ctl_active[get_last(ctl_tp)]], button.input.channel]
            }
        }
    }
    

    ctl_active is set per tp depending where the user is at - if in the video or audio sections, what output they're viewing, etc.

    Whatever buttons are on the panel are the ones that matter. Each source type will have its own UI popup/page/whatever. All are on the same channel.

    This is for one-way, or at least the input-side of the control (two-way devices have been controlled this way if channel control exists, or if not, via an intermediate module). Two-way is done a little differently.

    As DHawthorne states, the "standards" are a bit of a mess. The only one I try to conform to is standard channel numbers.

    I just wrote this up so I don't know if it works as given. ;)
  • the8thstthe8thst Posts: 470
    I stopped using the TO keyword once R4s were introduced into all of our systems. The system missed the release command on a button enough times that I no longer wanted to rely on it.

    That is why I switched to the "SP', repeat "SP" while held and if time is less than hold_max, "IROFF" when button is released (to prevent runaway from extra IR codes queued because of the SP command).

    I wish I could stick with the TO keyword because it scrolls a little faster and smoother, but I don't trust the button release event to always trigger.

    I would love to see a better method.
  • Spire_JeffSpire_Jeff Posts: 1,917
    the8thst wrote: »
    I stopped using the TO keyword once R4s were introduced into all of our systems. The system missed the release command on a button enough times that I no longer wanted to rely on it.

    That is why I switched to the "SP', repeat "SP" while held and if time is less than hold_max, "IROFF" when button is released (to prevent runaway from extra IR codes queued because of the SP command).

    I wish I could stick with the TO keyword because it scrolls a little faster and smoother, but I don't trust the button release event to always trigger.

    I would love to see a better method.

    You could recreate the TO functionality with the code you are using. Just do an SP for the push, then on the hold turn the channel ON. Create a WAIT hold_max OFF chan. Turn the channel off in the release section. You could move to a timeline or a couple other ways as well depending on what you prefer, but then you get the faster scrolling and the timeout functionality.

    Jeff
  • truetrue Posts: 307
    I used to use another method (probably like yours and anyone elses), but with recent firmware, R4s are improves - they fairly reliably tell you when they are offline or asleep. I have a data event that turns off anything controlled by a tp when the tp goes offline. R4s used to be an issue since they wouldn't even say they were going offline but since the zigbeepro firmwares or thereabouts using TO does not seem to be an issue.

    This said, nothing wrong with having an R4-specific handler in there...
Sign In or Register to comment.