Home AMX User Forum NetLinx Studio

Timeline IDs and modules

I find myself using timelines more and more, as I discover just how wonderful they are. I find it's easiest to declare the constants for the IDs all sequentially in the main .axs to keep all the IDs straight.

My understanding is that apparently you can't pass a constant in the parameter list to a module, so if you wanted to have a timeline within a module, how would you get to its ID to be sure to set it to something different from what's in the main program? And if you used multiple instances of the same module, how could you get each ID to be different?

If you knew you were only ever going to use one instance of a module in a program you could always hard code the ID to be something high, like 99, unlikely to be reached in a program. Has anyone else been here before?

OP

Comments

  • Timeline IDs and Modules

    Oliver,

    Of the two issues, let's look at the unique ID issue first. I use modules extensively and I also use timelines quite a bit (in modules). To solve the uniqueness problem, I define all of my TIMELINE IDs in an INCLUDE file (.axi) and then I include it in any module that requires a timeline. This way, I have a central location where all timeline IDs are defined, all modules have access to them, and you do not have to worry about the restriction that a module parameter must be a CONSTANT. As an aside, there used to be Netlinx runtime command that would dynamically return you a TIMELINE ID for use that was guaranteed to be unique. That call is no longer available and its demise probably had something to do with the fact that EVENTs required the devices, channels, levels, timelines, etc. to be defined at compilation time. Now that REBUILD_EVENT() is available which will re-compute the event trigger list, it would be nice to get that dynamic timeline ID call back for use in the multiple module instance as it would simplify things.

    There are other ways to define your timeline IDs globally so as to ensure uniqueness and to then pass them into the modules. You could conceivably, although I have not tried this yet, define your timelime ID constants, put them into a non-constant array, and then pass the array into a module. You could then take advantage of the REBUILD_EVENT() to have Netlinx build the trigger list using the IDs defined in the array passed to the module. I have not tried this as of yet but conceptually I think it is workable.

    I have encountered the multiple module instance/Timeline ID situation you noted. I handle this by defining a TIMELINE ID uniquely for the maximum number of module instances I ever expect to declare. When I define the module instance (whether it be in the Main program or elsewhere), I pass an integer value to the module which is essentially its instance ID. I then declare a TIMELINE_EVENT handler that triggers for all TIMELINE IDs that are defined for that module and then in the handler I check the TIMELINE.ID structure element to see if it corresponds to the TIMELINE ID for that module instance. In other words, using the TIMELINE IDs defined in the global header file, I create an array of those IDs that can be indexed by TIMELINE.ID. Since all of the timeline IDs I define for a module are sequential, simple math lets me determine the relative module instance for any given timeline ID. If the TIMELINE_EVENT determines that the event was for another module instance, the code is simply skipped. In other words, the TIMELINE_EVENT handler for the module encapsulates all of the code within an IF() statement that first ensures that the timeline event is for that instance of the module. It sounds more complex than it really is but it does work.

    I have been meaning to go back and re-work some of the multiple module instances that use timelines to use REBUILD_EVENT() to see if it works correctly and if it simplifies the code.

    Hope this helps,

    Reese
  • The issue with timeline IDs was definitely a concern when they were introduced, and at first glance the TIMELINE_ID call to generate a unique value was thought of, but that was never implemented. Instead it was determined to enforce that the NetLinx master ensure all timelines across modules be unique by including the module defining the timeline as part of how it keeps track of timelines. In other words (extremely simplified for clarity), if Module A has a timeline of ID 1, the master treats that as timeline A1, and if Module B has a timeline of ID 1, the master treats that as timeline B1.

    This enforces that as long as modules keep multiple timelines inside the module unique, multiple modules (even multiple instances of the same module) with always will have unique timelines.

    This reduces the burden on the programmer to keep from having to ensure unique IDs across modules, especially since some modules may not provide the source or documentation of what timelines are defined.

    HTH,

    Chuck
  • DHawthorneDHawthorne Posts: 4,584
    To clarify what Chuck said, define the timeline inside th module and it doesn't matter if the ID duplicates an ID in the main code. The compiler instances them so there is no conflict.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Originally posted by cwpartridge
    if Module A has a timeline of ID 1, the master treats that as timeline A1, and if Module B has a timeline of ID 1, the master treats that as timeline B1.

    I haven't thought of an implementation, but is there a way to address the module timelines in the main program? Tell me there is a way to do this and I'll develop a problem that can be solved by it ;)

    Jeff
  • Originally posted by Spire_Jeff
    is there a way to address the module timelines in the main program?
    All timeline calls internally are prepended with the Module ID of the calling module. This would make it prohibitive to create a timeline in one module, and act upon that timeline in another module. At first glance, I don't see any way to do what you asked with the current implementation.
  • This has been really a helpful response. So it seems like I was worrying unnecessarily because of this "instancing" within modules - I can go ahead and have TimeLine IDs in my main .AXS starting 1,2,3, for any timelines not in modules. Any modules referenced in that program can also have Timeline IDs hardcoded in them starting 1,2,3 etc and everything is still OK. Great.

    Thanks all.

    OP
  • Spire_JeffSpire_Jeff Posts: 1,917
    Originally posted by cwpartridge
    At first glance, I don't see any way to do what you asked with the current implementation.

    Ok, no worries... saves me the time of developing a problem to fit the solution ;) I just like lots of options because you never know when you'll run into that one problem that just doesn't get solved with your normal set of solutions(normally this consists of a hammer and a bigger hammer). This one was a long shot solution to a completely nonexistant problem, but I appreciate the response.

    Jeff
  • Spire_JeffSpire_Jeff Posts: 1,917
    Originally posted by cwpartridge
    All timeline calls internally are prepended with the Module ID of the calling module. This would make it prohibitive to create a timeline in one module, and act upon that timeline in another module.

    As I typed my previous response, I just couldn't help but think about a solution to this nonexistant problem. You could have the timeline event in the module turn on/off a virtual channel and then in the main code or another module have a channel event that monitors this virtual channel. If the timeline was generating events every thousandth of a second, this would be a rather poor implementation, but if the timeline only triggered on the minute, it might be feasible. I'm still working on why you would need this functionality, but I have a solution should I ever find the problem.

    Jeff
  • Timeline IDs and modules

    Thanks to Oliver for starting the thread and for Chuck's input since I learned something I had never seen documented. I did not realize that the TIMELINE IDs were instanced and this can certainly be used in the future to simply my code where multiple module instances and timelines are used. It does however mean that TIMELINE_EVENTs will not behave like all other EVENT handlers where you can have multiple instances of them in different modules doing module specific code for the same event triggers. I am not sure that this is a significant issue (as Jeff said, tell us the solution for it and we will find a problem that requires it) but it does put TIMELINE_EVENTs in a special category of event in this reagrd. Since it is the only event not to use a DEVICE argument in the first place, I guess it has always been a little unique. I had never seen the module instance handling for TIMELINE IDs documented anywhere - would make for a very nice Tech Note.

    Reese
  • DHawthorneDHawthorne Posts: 4,584
    Originally posted by Spire_Jeff
    As I typed my previous response, I just couldn't help but think about a solution to this nonexistant problem. You could have the timeline event in the module turn on/off a virtual channel and then in the main code or another module have a channel event that monitors this virtual channel. If the timeline was generating events every thousandth of a second, this would be a rather poor implementation, but if the timeline only triggered on the minute, it might be feasible. I'm still working on why you would need this functionality, but I have a solution should I ever find the problem.

    Jeff
    Here's your problem: you have a mission critical system that is not in an ideal location; let's say it's subject to power failures or environmental hazard, and you absolutely must know if it fails; or perhaps there is some equipment attached that might possibly lock up the whole thing, and you need to know if this happens. Your timeline setting a virtual channel becomes a heartbeat, another master on the network is monitoring the heartbeat to make sure it is alive, and notifies you on a failure. I actually planned something like this - I had some dodgy code that was locking up a processer, but only like once every two weeks. It was driving me nuts trying to troubleshoot, since it wouldn't appear once I reset the master, but I couldn't have it failing and upsetting the customer. So I was about to use an approach very much like this to reset the power on the system that was acting up if the "hearbeat" stopped, so at least the entire system didn't fail. I wound up finding the problem before I had to resort to that, but I've kept it in mind.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Thank you Dave. I knew if we tried hard enough, we could develop atleast one problem for the solution. ;)

    Jeff
Sign In or Register to comment.