I have a rule in the current version of the Rule machine that gets updates from a thermometer in my freezer and texts me if the temperature exceeds a set temperature (referencing a hub variable). Occasionally, when the freezer temp grows near (but does not exceed) the notification threshold temperature (e.g. a defrost cycle), the rule fires. In other words, the rule machine is firing and notifying me when the comparison condition is "8.5 > 1 0.0", which should never happen. This only happens when the freezer temp gets within about 2 degrees of the 10.0 threshold.
As such, is there something possibly wrong with the greater-than logic?
The code involved is as follows:
Select Actions for ALRT - First Floor Freezer Temperature Exceeded Limits
Set First Floor Freezer Temp to Temp 04 (Iris) First Floor Freezer Temperature(2.27)
IF (Temperature of First Floor Freezer Temp(2.27) is > First Floor Freezer UpperLimit(10.0)(F) [FALSE]) THEN
Notify Sendmail V3 to Ul's balis.com address (Routine email), Sendmail V3 to Ul's cell phone (Routine SMS), Sendmail V3 to Jen's Cell Phone (Routine SMS): 'First Floor Freezer on %time%, %date% exceeded maximum temperature limit (%First Floor Freezer UpperLimit%) with %First Floor Freezer Temp%F.'
Thanks for your reply. I have enabled logging and will provide logs as soon as the error happens again. The hub details are as follows: 2.4.1.177 and C-8
The logging proved very useful and is included below. I think we have a simple race condition, where the assignment of the device to the hub variable is taking place after the IF statement's comparison, which is why this only happens when the freezer is recovering from a defrost cycle and the temperature is actively decreasing. What appears to be happening is that the comparison takes place utilizing the prior hub variable value, which triggers the if statement to be true, and then the variable updates to the current sensor setting. Hence, when I get the text message, it shows the current in-range temperature, which is below the threshold for triggering the statement. Am I doing something wrong in expecting the hub variable to be instantiated prior to the comparison, which takes place in the very next statement after assignment, or is this an unexpected race condition in the rules engine that warrants some type of event "catch up" logic? Or, am I not aware of some "catch up" command that I should be using prior to the temperature comparison to avoid race conditions?
As a quick thought, I can certainly just make the comparison against the device temperature itself, as this would erase the possibility of a race condition. However, declaring "defeat" in doing this would suggest that hub variables are not to be trusted as realtime sources of truth. Certainly, in any of the production languages that I use (Rust, C++, C-Sharp, etc.), I've never had to consider latency of variable updates inside a single linear thread, so if it's really the case that Hubitat isn't updating variables between an initial instantiation and the very next statement that uses that variable, I would offer that you have a potential (and significant) vulnerability in Hubitat's scripting language.
You can test your theory by putting a "Wait for events: Elapsed time" before your next action. A few seconds should be more than enough. I don't think I've heard of this happening before, however, so I'm not sure. It doesn't seem impossible, as a rule simply performs one action and proceeds with the next, and if one of your actions is something like sending a command, there's no guarantee any resulting event would have happened by the time you get to the next action. Hub variables should be a lot faster since there are no devices involved, but I suppose it's still possible. A local variable should not have this issue, if there is one at all.
But: is there anything else going on in your particular rule? It doesn't look like you've ever shared the whole rule (not just actions or a subset of them). Note that screenshots are generally preferred.
That makes sense -- just wanted to make sure you didn't have anything that could be doing something that was not apparent from the previous description (e.g., re-triggering the rule or something else).
Is this a hub variable? If you aren't using it outside the rule, a local variable would work and shouldn't be subject to the above problem, if that is in fact what's happening -- but you don't even need that here since you could just use the device attribute directly in your conditional and, given your trigger event (one reason it's always good to share the whole rule ) use the built-in %value% variable for in the notification text instead of making your own.
Yes - presently the sensor temp is being stored as a hub variable. I chose that approach over a local variable, as my long-term intent is to make a status dashboard than will be able to access multiple temperatures, which are all in the form of hub variables. As such, having multiple temperatures centrally placed as hub variables seemed like a good idea at the time. Also, I use Hub variables for the upper and lower temperature limits, so it also seemed logical to make the comparison logic between separate hub variables, as they would be expected to reside nearby each other in memory space.
That makes sense for use of a hub variable, then. If you want to keep using it and suspect that the problem is as guessed above, then any of the alternative solutions for the other parts of this rule should work as I described in my posts above.
Anything you're doing on the hub is way too high-level to worry about any of this. (The platform is primarily Groovy running in a JVM. Rule Machine is a Groovy app, not unlike any other app on the hub, and your selections in the UI are not code or anything special per se, just the same thing you can do in other app UIs that ultimately cause the app itself to perform your configured behavior in response to whatever events, schedules, etc. you've caused it to care about.)
I'm pretty sure that the hub isn't a real-time OS.
In certain high-load situations (even if brief), you can't really count on the order of execution between different rules, events, etc.
I've had situations where I needed to add a 1 sec wait to allow an asynchronous event to complete.
As I recall, I set a Private Boolean for rule B from rule A, then called Rule B from Rule A--and had the PB test fail to work as expected in Rule B. A 1 sec wait inserted either before Rule A called Rule B or before the test in Rule B seemed to fix it.
This was related to an issue where there was something going on with certain actions that made them take longer than expected (I believe than issue was corrected), but it is an example of where things can run a bit out of sync.
When you have multiple rules triggered from the same event, that seems to load up the hub, so some waits can help things run more predictably.
I appreciate all the helpful comments. I've now definitely gained a better appreciation for the asynchronous nature of even adjacent rule entries in the actions list. By placing a ten-second wait after the initial hub variable setting statement, the race condition no longer takes place. This is analogous to the need for various types of "catch up" commands in other languages (e.g., "Application.DoEvents" in C Sharp). As mentioned, with the "Wait for event --> Elapsed Time" statement now in place, the rule works as it should. I suspect that other anomalous glitches I've noted with some of my more complex rules may be caused by similar race conditions (I use the Hubitat to control essentially all aspects of a home theater via the bridge to Harmony, and it occasionally glitches on startup ).