Home AMX User Forum AMX Technical Discussion
Options

Multiple Rooms, Multiple Panels - Get_Last????

Hi Guys,

I am busy doing a residential job which has grown from one TP in one area to eight TP's controlling eight
zones. Ordinarily, this would not be too bad but the customer has asked for every TP to have the facility
to control any zone.
I have created Zone pages which have fixed volume buttons for each zone and then call for the matrix changes,
turn on screens, amps etc in an include for each TP. The source buttons are popup pages.
Initially I have built all the source equipment include files to have Dev Arrays for 10 touch panels but I am
struggling slightly on the page flips as the include file for each TP's pageflips is getting HUUGE and too complicated.

Is there a way of using GET_LAST to send the pageflips only to the panel that the trigger button is pressed on?

IE. If I am in the Master Bedroom the Sky HD1 box activity button for the room is 1:22. If this is pressed,
it triggers;

CASE 22: //Masterbedroom Watch Sky 1
{
IF ((cTVLock == 'on') & (cMBRTvLift == 'Down'))
{
SEND_COMMAND dvTP10,"'@PPN-Alert - TV Locked'"
}
ELSE IF ((cTVLock == 'off') & (cMBRTvLift == 'Down'))
{
SEND_COMMAND dvTP10,"'@PPN-Alert - TV Open Sky1'"
}
ELSE
{
CALL 'TP10 BEDROOM WATCH SKY1'
}
}

Is there a way of using GET_LAST TO only send the pageflips or popups to the touch
panel that pushed the button?

Thanks as always...

Comments

  • Options
    rrdbstudiosrrdbstudios Posts: 160
    see this thread from the other day:

    http://www.amxforums.com/showthread.php?9393-Netlinx-port-codes

    it talks about using get_last with a touch panel dev array, so you can track which touch panel was used and send feedback or page flips, etc just to that one
  • Options
    Thanks thats perfect. I just need to figure out how to use this in nested waits now =)
  • Options
    ericmedleyericmedley Posts: 4,177
    Nested waits..

    Yeah, you're going to find the use of get_last a bit sketchy there.

    You're going to have to figure out some kind of framework to store and track your index returns.

    To be honest, I'd actually rethink the use of nested waits myself. Perhaps if you could post some code on how you wish to handle this. We might be able to suggest a little better way.
    E
  • Options
    Joe HebertJoe Hebert Posts: 2,159
    If you don’t need the index into the device array (a TP array in your case) for anything else and simply want to send a command to the device that generated the event, you can use the built in objects – free of charge.

    Inside a BUTTON_EVENT you can use:
    SEND_COMMAND BUTTON.INPUT.DEVICE,<the command you want to send>

    And inside a DATA_EVENT you can use:
    SEND_COMMAND DATA.DEVICE,<the command you want to send>
  • Options
    This is exactly what I needed....
    Joe Hebert wrote: »
    Inside a BUTTON_EVENT you can use:
    SEND_COMMAND BUTTON.INPUT.DEVICE,<the command you want to send>

    And inside a DATA_EVENT you can use:
    SEND_COMMAND DATA.DEVICE,<the command you want to send>

    Thanks you! Thank you! Thank you! This is exactly what I was trying to do. Its basically for multiple
    TP's to be able to control any zone so for page flips or certain feedback, I only wanted to send the action
    back to the originating panel. Using the Get_Last, it was possible for another panel to intercept and
    become the newer Get_Last so this is much better.

    Just when you think you are getting better at Netlinx programming, a pro comes along and shows
    you something basic that really humbles you =)
  • Options
    John NagyJohn Nagy Posts: 1,734
    So you are OK with the limitation that only one panel at a time can ever control a given source or room? If more than one does, and you only update one, others will show conditions or offer pages that are no longer current.

    This design is more akin to a stack of universal remotes than to an integration. Although it may be all that the job requires.
  • Options
    John Nagy wrote: »
    So you are OK with the limitation that only one panel at a time can ever control a given source or room? If more than one does, and you only update one, others will show conditions or offer pages that are no longer current.

    This design is more akin to a stack of universal remotes than to an integration. Although it may be all that the job requires.

    How do you approach these sorts of jobs John? I have tested it with two ipads and copying the current device number to a DEV variable for each room seems to work well without a hitch. I could write seperate panel includes for every panel and for every device i guess....
  • Options
    John NagyJohn Nagy Posts: 1,734
    There's another thread going now discussing this sort of thing and various approaches.

    http://www.amxforums.com/showthread.php?9393-Netlinx-port-codes

    Our company built a database approach to the problem, tracking all panels, rooms, sources, devices. Everything is a request, no page flips done by the panels. The central database tells the panels what page to show, so we don't need to ask them where they are. All panels can select and control any room, and all panels controlling the same room at the time will be sent the same updates and navigation. "PLAY" on any panel for any device is the same code and port. Since we know where the command came from, we know what to do with it. All touch panels are alike in all systems, driven to show what is needed by the situation of the moment. The central code is the same in every job, driven by data files that define what devices, ui's, rooms, and features the job has. So new jobs are just new data, no programming.

    That's more than you will probably want to program yourself, but the concepts are useful when designing your code; think about building an intelligent system instead of a relay race.
  • Options
    Sounds awesome, one day..... :)
    Till then its programming for every job. We are still a small business that has been doing AMX for the last couple of years.
    I dont know why but every job seems very different ( except the commercial installs) and the customers want completely different looks and logic behind theit interfaces.
    Perhaps we should be more stringent in what we offer but I get a real buzz in offering the customers completely bespoke solutions.
    I just need to learn how to programme them properly and efficiently..
    Thanks for all the help and feedback!
  • Options
    DHawthorneDHawthorne Posts: 4,584
    I'm with John on this. My programs are no where near as extensive as his, so instead of a database per se, I'm using several structures to track what every UI device is doing, and what every room is doing. In addition, I also use structures to designate what every room and component is capable of. It comes out to a defacto database, really. So when you pick the kitchen, for example, GET_LAST on my room select button list tells me that's room 3, and I set my controller structure to say it's now controlling room 3 ... if that room has no TV, the video buttons all disappear, the available sources do appear, etc. I can essentially use the same program for all my jobs, and just fill in the appropriate structures.
  • Options
    ericmedleyericmedley Posts: 4,177
    I'm with Dave and John too. If you think you don't have the time, expertise and/or know how to create a system like we're describing, you certainly won't have time to manage and/or change all these one-off systems you're planning on designing.

    I cannot say who made this statement but there's wisdom in it.



    Look at it like a client who wants a high-end automobile.

    They can get one custom made from scratch. It will be completely unique. But it will cost 10s of times more to design at the customers specification, engineer, draw up, build and install. Then they need time to tweak and change things.

    Or they can buy an off the shelf Fararri that has taken years to engineer build and has been tested thoroughly and runs like a champ. It will cost less and they'll really enjoy driving it. It goes fast and looks awesome.

    When it comes down to it, we're all just turning stuff on and off and routing stuff from here to there. The idea of something truly 'custom' is not really honest. The 'custom' part really isn't that uncommon after all and usually causes more headaches in the end.

    I'd recommend creating a really solid REPEATABLE system that works every time and is easy to set up and run.

    I can help you on your way. Design a system with one touch panel. Then rethink it so you can add as many touch panels to the system as you like without writing another line of code. Do that and you'll have your repeatable system!
  • Options
    truetrue Posts: 307
    The way I do this is tracking on a per-subsystem basis (typically AV and "all other" depending on control type) and each of these subsystems is managed independently (which AV room is selected, if controlling a pool or lighting, etc). This way different control types can be plugged in as needed. I then have a general panel control which manages global features and subsystem selection. Each subsystem and the general control has similar TP arrays with the same indexes, and on button pushes, panel onlines or inputs the index is grabbed is passed around appropriately.

    Say a panel 2 selects AV room 1 which is a global-access control (as opposed to selecting AV controls then Room 1), I would make this button be part of the global panel controls. Tapping the button would fire the button event and determine panel index 2, set the control type to AV, call sys_panel_update(2) which determines it needs to call av_panel_update(2), which does all of the AV panel updating. Obviously there are no on-panel flips. When a panel comes online, it also runs a sys_panel_update(idx) so it shows up exactly where it left off previously. (It also passes an online parameter just in case the panel should show something else if just coming online, like perhaps a rarely used distributed audio control returning to the main page).

    Any events caused by other panels in subsystems or by devices can call a panel_update_all which refreshes all online panels to update feedback.

    I have a basic layout with different subsystems that I generally create my projects from and it works well and is easy to maintain. And as ericmedley points out, adding more panels isn't a problem. I typically have a bunch pre-loaded into these arrays so adding a new panel is as simple as loading it and addressing it (so long as the panel needs to work just like existing panels ;))

    It's pretty easy / simple...I can give code / pseudocode examples if desired.
  • Options
    Thanks true that sounds good. Please can I have a look at your examples as I am desperate to improve on this and whilst the concepts seem understandable, putting them to practice is unfortunately completely out of my league. Hopefully seeing some ideas might help me start on the right road. Cheers, Mike
  • Options
    a_riot42a_riot42 Posts: 1,624
    Nested waits aren't what you want so I wouldn't worry about losing those constructs to take advantage of get_last. The reason the compiler stops you from using a variable in a wait is because it leads to undefined results. So even if you could use it you don't want to. I barely use waits never mind nested waits, and the systems are better for it. wait_until is evil as well so I've banned it from my projects. Same with all the combine thingies and select/active. With get_last you tend not to need those things anyway.
    Paul
  • Options
    viningvining Posts: 4,368
    a_riot42 wrote: »
    Nested waits aren't what you want so I wouldn't worry about losing those constructs to take advantage of get_last. The reason the compiler stops you from using a variable in a wait is because it leads to undefined results. So even if you could use it you don't want to. I barely use waits never mind nested waits, and the systems are better for it. wait_until is evil as well so I've banned it from my projects. Same with all the combine thingies and select/active. With get_last you tend not to need those things anyway.
    Paul
    whatta ya got against select/active? I was with ya til I got to that.
  • Options
    a_riot42a_riot42 Posts: 1,624
    vining wrote: »
    whatta ya got against select/active? I was with ya til I got to that.

    whatta ya got against if/else, or switch/case? Its fewer letters to type, and no colons involved, and conforms to standard practices. I also think the select and active keywords were poor choices since I so often use those terms in my code for other things, so its confusing to me to see them as keywords. I would end up having to look at code like this:
    define_function selectDisplay()
    {
      SELECT
      {
       ACTIVE (getActiveProj(iActiveProj)) :
       {
          selectProjector()
       }
       ACTIVE (isTVActive) :
       {
          selectTV()
       }
       ACTIVE (iCurrentActivity) :
       {
          selectActivity()
       }
      }
    }
    
  • Options
    Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote:
    Nested waits aren't what you want...
    I agree. Ugh.

    a_riot42 wrote:
    The reason the compiler stops you from using a variable in a wait is because it leads to undefined results...
    The compiler lets you use global variables or local variables inside of a wait. When the wait expires the value that is used is the current value of the variable which is not necessarily the value of the variable when the wait was put in the queue. The compiler only stops you from using a stack_var because the variable will (most likely or at least could) be out of scope when the wait expires.

    a_riot42 wrote:
    wait_until is evil as well so I've banned it from my projects
    I used to think that way also but there have been a handful of times over the years where a wait_until was the absolute perfect tool. As long as you understand how it works, there is nothing evil about it. Some tools you use all the time and some are specialty tools.

    a_riot42 wrote:
    Same with all the combine thingies and select/active...
    As the official spokesman for Select Active I take exception to your comments. I’m going to speak to my lawyer in the morning. I may be filing a libel case (pun intended.)

    a_riot42 wrote:
    whatta ya got against if/else, or switch/case?
    I’ve been bit by the Switch Case bug before so unless I’m Casing something consecutive and simple like 1,2,3,4 I stay away from it.
  • Options
    a_riot42a_riot42 Posts: 1,624
    Joe Hebert wrote: »
    The compiler lets you use global variables or local variables inside of a wait.

    Yes, I meant stack variables. I try to discourage the use of local variables as well though. I haven't used local_var since back in the previous millenium.
    Joe Hebert wrote: »
    When the wait expires the value that is used is the current value of the variable which is not necessarily the value of the variable when the wait was put in the queue. The compiler only stops you from using a stack_var because the variable will (most likely or at least could) be out of scope when the wait expires.

    I don't think you can set a wait to be fast enough to outrun the processor, so the variable will always be out of scope. Its more that the variable no longer exists, more than its value is incorrect. You'd end up with a segmentation fault if the compiler allowed it. Even if you use wait 0 it still won't compile even though theoretically the variable is still in scope when the wait expires.
    Joe Hebert wrote: »
    I used to think that way also but there have been a handful of times over the years where a wait_until was the absolute perfect tool. As long as you understand how it works, there is nothing evil about it. Some tools you use all the time and some are specialty tools.

    I think programmers that use wait_until a lot are absolute perfect tools :)
    Joe Hebert wrote: »
    As the official spokesman for Select Active I take exception to your comments. I’m going to speak to my lawyer in the morning. I may be filing a libel case (pun intended.)

    That's first amendment protected free speech. I would have to counter sue for malicious prosecution, defamation of character, tortious business interference, and probably some civil rights claims.
    Joe Hebert wrote: »
    I’ve been bit by the Switch Case bug before so unless I’m Casing something consecutive and simple like 1,2,3,4 I stay away from it.

    You do have to be careful of the Switch Case bug, but I'm certain select/active has its share of bugs as well does it not? Being the grand poobah of select/active you must have encountered one or two during your reign.
    Paul
  • Options
    Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote:
    I would have to counter sue for malicious prosecution, defamation of character, tortious business interference, and probably some civil rights claims.
    And then I would have to tell on you. Mom...
    a_riot42 wrote:
    You do have to be careful of the Switch Case bug, but I'm certain select/active has its share of bugs as well does it not? Being the grand poobah of select/active you must have encountered one or two during your reign.
    Nope, never encountered one ever.
    And it’s Mr. Grand Poobah to you.
  • Options
    viningvining Posts: 4,368
    a_riot42 wrote: »
    whatta ya got against if/else, or switch/case?

    Nuttin, I like them too. Select/active isn't really interchangable with switch/case which has bugs or had bugs and since I don't remember If the bugs are still there I use it sparingly but even with the bugs I still like it.

    Active():
    Esle if()

    Yep, that colon should be a deal breaker. :). For me when I start adding else if's it's time to consider select/active but sometime when I'm writing code I just start with a select/active with only one active and maybe a deafault (active(1)) just in case it expands as I continue to build the code. Often I end up with many more active's but sometimes it remains at one and in my world that's fine. Your world is obviously different. :)
  • Options
    DHawthorneDHawthorne Posts: 4,584
    SWITCH...CASE is fine if you don't get too fancy. I generally won't use it with anything but simple data types. For a GET_LAST result, it works perfectly. I use SELECT...ACTIVE when the logic is more complex, as when you need to test for several conditions per case. I have a hangup about nesting IF...ELSE statements, but honestly they work pretty much just like SELECT...ACTIVE, and are just as easy to follow in code if you write them like this:
    IF(<condition1>)
       <action1>
    ELSE IF(<condition2>)
        <action2>
    

    I think someone did a test and found that nested IFs actually run faster than a SELECT...ACTIVE, but I imagine that varies with the complexity of the tests.
Sign In or Register to comment.