Event triggered by variable change
mlschuh
Posts: 12
Howdy Everyone,
I'm looking for a way to trigger an event/function if a variable is changed. This would be applied to an array of structures so having active monitoring of every single variable would easily create a massive amount of code as well as not being flexible for updates.
I've thought about using virtual devices but run into problems with storing LONGs and CHAR arrays that are somehow tied to that virtual device (and thusly monitored for changes).
These must be events or function calls from the trigger due to GUI updates as well as IP commands being sent to many other devices.
I'm trying to avoid the following:
Any ideas? I'm thinking Duet can do this with listeners but that would be a hard push to get with this being the only reason.
--
Mitch
I'm looking for a way to trigger an event/function if a variable is changed. This would be applied to an array of structures so having active monitoring of every single variable would easily create a massive amount of code as well as not being flexible for updates.
I've thought about using virtual devices but run into problems with storing LONGs and CHAR arrays that are somehow tied to that virtual device (and thusly monitored for changes).
These must be events or function calls from the trigger due to GUI updates as well as IP commands being sent to many other devices.
I'm trying to avoid the following:
sSTATUS = 'STARTING_UP' CALL 'UPDATE_STATUS' ... sSTATUS = 'STARTED' CALL 'UPDATE_STATUS'
Any ideas? I'm thinking Duet can do this with listeners but that would be a hard push to get with this being the only reason.
--
Mitch
0
Comments
I?ve always thought a PROPERTY_EVENT would make Netlinx a more powerful language. Something like this:
Is that along the lines you are thinking?
I come from a C/C++ so am a bit bias towards their layout of classes.
That way it will work within structures themselves and you don't need to make odd arrays if you want to modify variables within structures (if it's even possible to make those arrays, I haven't put much thought into it yet).
Example:
I'm confused, what triggers the CASE? Would you just have a WAIT_UNTIL set on every variable you want to monitor?
Sorry - that was just pulled out of my code in the power on sequence. The CASE was which source (in this instance - CD) was selected in the function.
Basically, when someone selects the CD source, I'm going to WAIT_UNTIL the CD changer is powered up (variable changed elsewhere in code when it receives a specific string back from it), and then do some specific things. You can add a name to it to cancel it if a difference source is selected.
Recently I used TIMED_WAITs with three driveway sensors. There's one at the entry (near the street), one in front of the house and one near the garage. I set a variable once the first sensor was tripped, and then did a TIMED_WAIT_UNTIL until either sensor two or three was tripped. Once one of those triggers fired, the variable changed and fired specific code. Of course all of the waits were named and could be canceled.
--Mitch
Or - just put it in DEFINE_PROGRAM like earlier suggested. What you're looking for is achievable - just not in a .NET style.
I'd love to put them all as IFs in mainline but I'm looking at around 15 properties for ~20 zones which is at least 300 lines of just if statements, along with all of the temporary variables to go along with it and a nightmare to adjust if I add a single property to the structure.
Netlinx is just so close to being a very, very powerful language but I guess I have to look towards Duet to really pull out all of the stops.
You can kind of fake 'listeners' using virtual devices and channel_events. But I am wondering if there might be an issue with your design if what you are trying to achieve doesn't present any elegant solution. What is it you are trying to achieve exactly?
Paul
Here's just a quick sample structure:
In various locations throughout the remainder of the code, all of the various integers change. When these variables change, I need to add the changes to logs as well as send the change to a central controller (Not AMX). There are also many, many zones (this particular one is 21) so a structure array is the best way that I've found to work with everything.
Other structures contain LONGs and CHAR arrays so I sadly cannot use virtual devices.
The workaround is to just call the update function every time the variable change, which is what I'm doing now. Not the ideal, but that's all I've found so far.
--Mitch
I wish AMX would open up the compiler so I could write some patches against it. A lot of the issues are syntax that would be easy to do, some are features like these.
I am thinking that there are a finite number of states, so as an example, I will use inputs 1-10 and off.
I am not sure this will line up to what you need, but it helps me to think of the virtual device as a structure of pointers and values if you will. You get multiple elements by grouping the channel codes. Such as channel 200 is a boolean indicator for power off, chans 201-220 are inputs, level 1 is volume level, channel 26 is Mute indicator, and so on.
Using the channels is nice because if the same input is selected again, the event won't trigger again. You can also access the channel states for conditionals ... if([vdvDevice,200]). Levels can be nice as the event only occurs if the level is different, but they can be a little tricky as the level drops to 0 when a device goes offline. You also have to do a little more work to get access to the value of the level outside of a level event, but it is not too difficult.
Jeff
Just a quick followup on what I ended up doing.
Ultimatly, what I was looking for was a variable watcher. As I kept looking for an answer, a way to impliment classes in Netlinx started to form in my mind and I pushed around some test code and sure enough, 95% of what I would need to do exists. However, the remaining 5% ground everything to a halt and made it much more trouble that it was worth (declaring extra variables, having includes in addition to modules, etc), so I canned that idea.
The solution that I came up with isn't the greatest way to do it, and I'm sure I'll get scolded by someone, but I created a module that gets passed a devchan (read: virtual 'listener' device) and a variable name. That module contains the if in the mainline (like TurnipTruck suggested) and manages the temporary check variable. It then just pulses the devchan when the variable changes. A grand total of 4 lines of code. However, I think it will help with organization within the actual code by making it so you only need to declare your devchan (or device/channel pair however you want) and then just defining the module rather than having to manage the temporary variable and the if statements.
To me, it's right on the border of lazy vs useful, but I found it much easier to essentially say "Hey, I want a listener on here!" rather than actually building the listener every time.
When I get this fully implemented in my system, I'll run some speed checks to make sure that the if's aren't loading down anything too much (I highly doubt it, but it can't hurt to check). PM me if you would be interested in the results.
Oh, and the full motivation behind this: create a standard event driven programming layout that can coexist with other types of programming environments. Namely, Medialon.
--Mitch
That's exactly what I ended up doing.
-Mitch