Home AMX User Forum AMX General Discussion

Hold event bug

If I have two or more of the same module defined, and then print out what the virtual device number is on a push, I see two strings in diagnostics that print out the two virtual devices that get passed to the 2 modules. However, on a hold of the same button, only one string appears of one virtual, and its always the first one to get declared. So even through both modules hold events should execute just like both pushes did, only one executes and its always the first to be declared. Can someone load this demo code and see if they are seeing the same behavior? I saw this on the latest v4 firmware and also the last v3.
Thanks,
Paul

Comments

  • John NagyJohn Nagy Posts: 1,742
    Per my my second-hand understanding such as it is regarding HOLDs.... which we have discussed a lot and programmed around to prevent runs...

    HOLDS are imputed, not explicit, the NetLinx OS calculates that a HOLD occurred if enough time passes after a PUSH before a RELEASE. Since the HOLD is a conclusion made by the OS and not an externally detectable state, it may not process through your dual code as you might expect, the first instance may clear the hold so the second never sees it. You may need to make a HOLD detection process and pass that as a state explicitly to both parts of the following code.
  • viningvining Posts: 4,368
    Probably something to do with the master trying to track essentially 2 holds for the same TP even though you would think you'd have 2 instances of an identical event table.

    If you change your code a bit it seems to work fine:
    Line      1 (08:47:30)::  Mod-[ 1 ], Push button Sanity Check.  vdvDevice = 33001:1:0
    Line      2 (08:47:30)::  Mod-[ 2 ], Push button Sanity Check.  vdvDevice = 33002:1:0
    Line      3 (08:47:31)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line      4 (08:47:31)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line      5 (08:47:31)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line      6 (08:47:31)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line      7 (08:47:32)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line      8 (08:47:32)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line      9 (08:47:32)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     10 (08:47:32)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     11 (08:47:33)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     12 (08:47:33)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     13 (08:47:33)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     14 (08:47:33)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     15 (08:47:34)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     16 (08:47:34)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     17 (08:47:34)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     18 (08:47:34)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     19 (08:47:35)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     20 (08:47:35)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     21 (08:47:35)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     22 (08:47:35)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     23 (08:47:36)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     24 (08:47:36)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     25 (08:47:36)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     26 (08:47:36)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     27 (08:47:37)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     28 (08:47:37)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     29 (08:47:37)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     30 (08:47:37)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     31 (08:47:38)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     32 (08:47:38)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     33 (08:47:38)::  Mod-[ 1 ], Hold button Sanity Check.  vdvDevice = 33001:1:0
    Line     34 (08:47:38)::  Mod-[ 2 ], Hold button Sanity Check.  vdvDevice = 33002:1:0
    Line     35 (08:47:38)::  Mod-[ 1 ], Release button Sanity Check.  vdvDevice = 33001:1:0
    Line     36 (08:47:38)::  Mod-[ 2 ], Release button Sanity Check.  vdvDevice = 33002:1:0
    
    MAIN:
    PROGRAM_NAME='Hold Test'
    
    DEFINE_DEVICE
    dvTP							= 11001:1:0
    vdvDevice1						= 33001:1:0
    vdvDevice2						= 33002:1:0
    
    DEFINE_CONSTANT
    
    DP_MAX_HOLD	= 80;//8 seconds
    INSTANCE[]	= {1,2};
    
    define_module 'Generic Module' mdlModule1 (vdvDevice1, dvTP,INSTANCE[1])
    define_module 'Generic Module' mdlModule2 (vdvDevice2, dvTP,INSTANCE[2])
    
    DEFINE_EVENT
    
    button_event[dvTP,1]
         
         {
         push:
    	  {
    	  DO_PUSH_TIMED(vdvDevice1,1,DP_MAX_HOLD);
    	  DO_PUSH_TIMED(vdvDevice2,1,DP_MAX_HOLD);
    	  }
         release:
    	  {
    	  DO_RELEASE(vdvDevice1,1);
    	  DO_RELEASE(vdvDevice2,1);
    	  }
         }
    
    DEFINE_PROGRAM
    
    MODULE:
    MODULE_NAME='Generic Module' (dev vdvDevice,dev dvTP,INTEGER Instance)
    
    define_function char[32] dsptoa(dev dvDev)
         {
         return "itoa(dvDev.number),':',itoa(dvDev.port),':',itoa(dvDev.system)";
         }
    
    DEFINE_EVENT
    
    button_event[vdvDevice,1]
         
         {
         push:
    	  {
    	  send_string 0, "'Mod-[ ',itoa(Instance),' ], Push button Sanity Check.  vdvDevice = ' , dsptoa(vdvDevice)"
    	  }
         hold[5, repeat]:
    	  {
    	  send_string 0, "'Mod-[ ',itoa(Instance),' ], Hold button Sanity Check.  vdvDevice = ' , dsptoa(vdvDevice)"
    	  }
         release:
    	  {
    	  send_string 0, "'Mod-[ ',itoa(Instance),' ], Release button Sanity Check.  vdvDevice = ' , dsptoa(vdvDevice)"
    	  }
         }
    
    DEFINE_PROGRAM
    
  • a_riot42a_riot42 Posts: 1,624
    I'm not sure how that made a difference. Simply adding another parameter makes it work correctly? Or am I missing something? If I can not use the hold event, then one third of the button events is unreliable which is a little lame. I don't see the difficulty in keeping track of touch panels push and release states. Essentially if a touch panel button has been pushed and not released before the hold timeout, the hold section should be running for any affected module. If I have 20 modules for a DVR and want all 20 DVRs to be controlled from one touch panel, all 20 hold events should run, not just one. I'll have to try your modification when I get to work, thanks for trying that. I was hoping I was wrong and no workaround would be needed but that appears to not be true.
    Paul
  • a_riot42a_riot42 Posts: 1,624
    So you are activating the button event from main and push the virtual. That's a different thing altogether.
    That works as expected, and a TP should be the same.
    Paul
  • a_riot42a_riot42 Posts: 1,624
    Interestingly it works as expected when I do nothing other than change the name of the module slightly.

    define_module 'Generic Module' mdlModule1 (vdvDevice1, dvTP)
    define_module 'Generic Module 2' mdlModule2 (vdvDevice2, dvTP)

    Line 1 (11:17:25.484):: Push button Sanity Check. vdvDevice = 33001:1:0
    Line 2 (11:17:25.484):: Push button Sanity Check. vdvDevice = 33002:1:0
    Line 3 (11:17:25.515):: Release button Sanity Check. vdvDevice = 33001:1:0
    Line 4 (11:17:25.515):: Release button Sanity Check. vdvDevice = 33002:1:0
    Line 5 (11:17:28.437):: DDD.handleDynamicDevice(): new DPD - 10.40.62.93
    Line 6 (11:17:28.734):: Push button Sanity Check. vdvDevice = 33001:1:0
    Line 7 (11:17:28.734):: Push button Sanity Check. vdvDevice = 33002:1:0
    Line 8 (11:17:29.234):: Hold button Sanity Check. vdvDevice = 33001:1:0
    Line 9 (11:17:29.234):: Hold button Sanity Check. vdvDevice = 33002:1:0
    Line 10 (11:17:29.734):: Hold button Sanity Check. vdvDevice = 33001:1:0
    Line 11 (11:17:29.734):: Hold button Sanity Check. vdvDevice = 33002:1:0
    Line 12 (11:17:30.234):: Hold button Sanity Check. vdvDevice = 33001:1:0
    Line 13 (11:17:30.234):: Hold button Sanity Check. vdvDevice = 33002:1:0
    Line 14 (11:17:30.734):: Hold button Sanity Check. vdvDevice = 33001:1:0
    Line 15 (11:17:30.734):: Hold button Sanity Check. vdvDevice = 33002:1:0
    Line 16 (11:17:31.234):: Hold button Sanity Check. vdvDevice = 33001:1:0
    Line 17 (11:17:31.234):: Hold button Sanity Check. vdvDevice = 33002:1:0
    Line 18 (11:17:31.734):: Hold button Sanity Check. vdvDevice = 33001:1:0
    Line 19 (11:17:31.734):: Hold button Sanity Check. vdvDevice = 33002:1:0
    Line 20 (11:17:32.234):: Hold button Sanity Check. vdvDevice = 33001:1:0
    Line 21 (11:17:32.234):: Hold button Sanity Check. vdvDevice = 33002:1:0
    Line 22 (11:17:32.484):: Release button Sanity Check. vdvDevice = 33001:1:0
    Line 23 (11:17:32.484):: Release button Sanity Check. vdvDevice = 33002:1:0

    That just looks like a bug to me. Clearly the firmware can do what is needed, but for some reason an instantiation of the same module breaks it.
    Paul
  • a_riot42a_riot42 Posts: 1,624
    Doing some further investigation, it looks like if you have a module declared more than once, the only module that exists in memory during a hold event is the first one. Even trying to print a modules variables doesn't work. So if you have a variable in a module, and print the data in a hold event, you will only ever get the variable from the first declaration. Even if you hard code the other modules virtual device number to do something like print a string from the structure, you get null. Its like in a hold, only one module exists in memory no matter how many times you define it.

    This means that you can't even set a variable in the hold, start a timeline, or even check if a hold was run in a module, since it simply doesn't exist. I would never have predicted this in a million years and find it hard to believe I haven't run across it before but there it is. The point of a module is to reuse code but it can't be done if you ever need a hold event to run, which I often do. I hope they can fix this, but the bug must be deep in the bowels of the firmware. Yikes!
    Paul
  • DHawthorneDHawthorne Posts: 4,584
    You could probably fake it by setting a timer via WAIT on the PUSH handler, and canceling it on the RELEASE. Dark, but it should at least work.
  • a_riot42a_riot42 Posts: 1,624
    DHawthorne wrote: »
    You could probably fake it by setting a timer via WAIT on the PUSH handler, and canceling it on the RELEASE. Dark, but it should at least work.

    That does seem a bit dark, but thanks for the suggestion. I think I might try starting a timeline in the push and killing it in the release. Wasn't much point in fixing get_last to work in hold events considering this behavior in modules.
    Paul
Sign In or Register to comment.