Home AMX User Forum NetLinx Studio

Emulate TP Button Press in Code

I would like to emulate a touch panel button press via code. Basically, I have several buttons that do predefined commands. I'd like to be able to "trigger" those buttons from elsewhere in the code, mainly online/offline event handlers.

Here is the main button event
BUTTON_EVENT[dvTP1,701]
{
   PUSH:
      //Something Occurs
}

Comments

  • Use the command do_push

    data_event[dvTV]
    {
    online:
    {
    do_push (dvTP1,701)
    }
    }
  • jabramsonjabramson Posts: 106
    Thanks, I knew it had to be something really simple.
  • PhreaKPhreaK Posts: 966
    You may also benefit from learning about functions. If you have a set of operations that you need to trigger from multiple areas it can help greatly improve your code readability.
    /**
     * Does something
     */
    define_function doSomething() {
    	// do stuff
    }
    
    
    define_event
    
    button_event[tp, 1] {
    
    	push: {
    		doSomething()
    	}
    
    }
    
    data_event[device] {
    
    	online: {
    		doSomething();
    	}
    
    }
    

    Although this may look excessive at first code is always read far more times than it is written. By using a logical name for your function if someone else (or even yourself) is working on your code in the future rather than seeing do_push(tp, 1) and then having to locate it and figure our what the hell its intended to do they can take an educated guess based on the function name - then investigate further if required.

    If you have a look in Help -> NetLinx Keywords Help form within NetLinx Studio it will provide you with some more info.
  • a_riot42a_riot42 Posts: 1,624
    Write a function that does what you need it to, and call it from the button press, and then call it as necessary from code. Using do_push can have some unwanted side effects, so I avoid it unless no other alternative exists.
    Paul
  • viningvining Posts: 4,368
    I don't beieve I've had any issues with using do_push but it may not be the most proper way of doing things. I've never been proper so it doesn't bother me. If you want to make it more desciptive so later you'll be able to look at that line of code and be able to determine what it does without jumping to the button_event it calls just use a desciptive constant in lieu of just the channel number. dvTP isn't helpful either and should be more descriptive if poosible like dvAVR_TP or something. If you're inside a module that's fine but then you probably wouldn't need a do_push.

    So if you create a function that just calls a do_push I'd probably just use the do_push but if you can send a direct command then by all means do so.
  • ericmedleyericmedley Posts: 4,177
    vining wrote: »
    I don't beieve I've had any issues with using do_push but it may not be the most proper way of doing things. I've never been proper so it doesn't bother me. If you want to make it more desciptive so later you'll be able to look at that line of code and be able to determine what it does without jumping to the button_event it calls just use a desciptive constant in lieu of just the channel number. dvTP isn't helpful either and should be more descriptive if poosible like dvAVR_TP or something. If you're inside a module that's fine but then you probably wouldn't need a do_push.

    So if you create a function that just calls a do_push I'd probably just use the do_push but if you can send a direct command then by all means do so.

    I too have had no issues with DO_PUSH as long as it is running on the same master as the program. However, I've seen issues with DO_PUSH when it references other masters using M2M. I tend to not use it as I typically do more than one master. But, as Vining says, I've never had it give me trouble on the same master.
  • DHawthorneDHawthorne Posts: 4,584
    I was once told that DO_PUSH was like GOTO in Basic: never use it. But any accomplished Basic programmer will tell you that if you don't go nuts with it, GOTO is just fine. Same as DO_PUSH. There are times its the only thing that makes sense, and times to avoid it like the plague. I use it a lot when button presses are part of a module; that's one of the times when trying to duplicate the code is just silly.
  • The biggest issue with DO_PUSH is calling the same DO_PUSH too soon:
    From the NetLinx Language Reference Guide:
    To prevent the program from stalling mainline too long, there is a 0.5 second timeout on DO_PUSH.

    DO_PUSH defaults to a 0.5 second push on a channel before issuing a DO_RELEASE for you (unless another DO_PUSH is executed for the same channel).

    NetLinx will forcibly exit the DO_PUSH after 0.5 seconds, regardless of the operation it is executing.

    If the channel is already ON, no event is generated.

    Note: The timeout feature is used to prevent un-released pushes and out of control ramping.


    The unfortunate thing is, a second DO_PUSH doesn't run the "PUSH" again. It simple restarts the DO_RELEASE timer, and until the RELEASE event happens, the PUSH event won't be available.

    Take this bit of pseudo code as an example:
    DEFINE_START
        RUNNING = TRUE
        RUN EVENT_1
        
    EVENT_1:
    {
        IF(RUNNING)
        {
            DO_PUSH on BUTTON_1
            
            PULSE CHANNEL_2
            
            WAIT 5
            {
                SEND_STRING 0, 'WAIT COMPLETED'
            }
    
            RUN EVENT_2
        }
    }
    
    EVENT_2:
    {
        RUN EVENT_1
    }
    
    BUTTON_EVENT[BUTTON_1]:
    {
        PUSH:
        { 
            SEND_STRING 0, "'BUTTON_1 PUSHED'";
        }
        RELEASE:
        {
            RUNNING = FALSE;
            SEND_STRING 0, "'BUTTON_1 RELEASED'";
        }
    }
    
    CHANNEL_EVENT[CHANNEL_2]:
    {
        ON: { SEND_STRING 0, "'CHANNEL_2 ON'"; }
        OFF: { SEND_STRING 0, "'CHANNEL_2 OFF'"; }
    }
    

    if you ran that silly bit of code you'd see:
    BUTTON_1 PUSHED
    CHANNEL_2 ON
    (.5 seconds later)
    WAIT COMPLETED
    CHANNEL_2 OFF
    CHANNEL_2 ON
    (.5 seconds later)
    WAIT COMPLETED
    CHANNEL_2 OFF
    CHANNEL_2 ON
    (... for eternity)
    
    You'd never see the "BUTTON_1 RELEASED".
  • viningvining Posts: 4,368
    That same would also apply to code that uses "pulse" to trigger channels in modules. I don't think the .5 second delay is really an issue for the majority of code where it would make sense using a do_push. If you think there could be an issue you could use do_push followed immediately by a do_release or simply use a do_push_timed for.1 seconds.
  • vining wrote: »
    That same would also apply to code that uses "pulse" to trigger channels in modules.
    True that it applies to a pulse in that a second pulse in .5 seconds will register nothing. However, a pulse will still timeout in .5 seconds, whereas a second DO_PUSH restarts the timer, extending the release out to almost a second after the initial push or, like my example shows, indefinitely.

    Another downfall of the DO_PUSH compared to a PULSE is being able to test the state. A pulsed channel can be tested with something like "IF([dvDevice, CHANNEL])". A DO_PUSH however initiates the change on the Input channel (like a regular button press) and, at least as far as I know, you can only test that state if you've followed the PUSH by setting the corresponding channel ON:
    DO_PUSH[dvTP, 2]
    
    IF([dvTP, 2]) // FALSE! :-(
    
    ON[dvTP, 2]
    
    IF([dvTP, 2]) // TRUE! :-)
    

    vining wrote: »
    If you think there could be an issue you could use do_push followed immediately by a do_release or simply use a do_push_timed for.1 seconds.
    I agree with following any DO_PUSH immediately with a DO_RELEASE. This places the release event immediately behind the PUSH and makes the PUSH immediately available for a second use.

    I guess my point is, even .1 seconds can be too long when you aren't *absolutely* sure you will *never* want to run a bit of code more than once in a row. I agree with PhreaK that functions are the better way to handle this sort of thing. To me a DO_PUSH is like duct tape; it's fine once and a while to fix the problem at hand, but making a habit of it is a bad idea.
  • DubbledexDubbledex Posts: 17
    I have a virtual button question too!

    Hi everyone, Was not sure whether I should just reply to this thread as it seems to be quite related to my question, or to start a new thread.. I'm sure someone will tell me!

    Okay, On a channel event (a master power switch going off) my colleague had programmed this to shut down the projectors. However, this is not triggering the electric screens to go back up.
    What I thought that instead of sending an off string to the projector, I could emulate the " turn off projector 1" button press, so all the events needed would run. Here is the code below:

    CHANNEL_EVENT[DIGITALIO,MasterPower1] // Master Power Warnings

    {ON: {IF((PowerSaving)&&(Proj1Power)) {do_push: [vPanelOne,2]}} // this is my bodged line
    //{ON: {IF((PowerSaving)&&(Proj1Power)) {SEND_STRING PROJ1,ProjPowerOff} //this is my colleagues original line
    // IF((PowerSaving)&&(ProjModeSELECT=2)&&(Proj2Power)) {SEND_STRING PROJ2,ProjPowerOff}}
    OFF: { }}


    FYI, this is what Button_Event[vPanelOne,2] does:

    Button_Event[vPanelOne,2] // Projector 1 Power OFF
    {Push:
    {CALL'PROJ1_POWER_OFF'
    ON[PROJ1_COOLING_SWITCH]
    ON[Proj1FakeCooling] WAIT 1200 {OFF[Proj1FakeCooling]}
    Proj1ErrorTrap = 11
    CALL'PROJ1_COOLING'
    IF (PROJ2_ON_SWITCH || PROJ2_OFF_SWITCH)
    {SWITCH (Proj2Source)
    {CASE 'PC': CALL 'PC_SELECT_PROJ2'
    CASE 'Laptop': CALL 'LAPTOP_SELECT_PROJ2'
    CASE 'Doc Cam': CALL 'DOCCAM_SELECT_PROJ2'
    CASE 'DVD': CALL 'DVD_SELECT_PROJ2'
    CASE 'VHS': CALL 'VHS_SELECT_PROJ2'}}}}


    Also, how do you paste code in not like I have done above? I see it in its own box within a post when most other people do it.. Seems a much more sensible way to do it.

    Thanks again,

    David
  • viningvining Posts: 4,368
    Your do_push is wrong.
    {ON: {IF((PowerSaving)&&(Proj1Power)) {do_push: [vPanelOne,2]}} // this is my bodged line
    Should be:
    {ON: {IF((PowerSaving)&&(Proj1Power)) {do_push(vPanelOne,2)}} //
    
  • DubbledexDubbledex Posts: 17
    Thanks for that Vining, been totally swamped at work today and not much time to change this code, but I will get it put in ASAP!
  • Dubbledex wrote: »
    Also, how do you paste code in not like I have done above? I see it in its own box within a post when most other people do it.. Seems a much more sensible way to do it.


    To get the code box, you use the BB code [noparse]"
    "[/noparse]. BB codes work just like HTML tags except you use square brackets instead of angle brackets.
    
    So if you type this in your post:
    
    [size=+1][font=Courier][noparse][code]This is a code box
    
    [/noparse][/font][/size]

    You'll get this:
    This is a code box
    


    See this page for all the BB codes: http://www.amxforums.com/misc.php?do=bbcode

    -Nick
Sign In or Register to comment.