[Reactor] Variables not updating correctly in latest-25201-2aa18550
-
Build 25272 now up for docker 64-bit only once again. A good bit of cleanup again.
@therealdb wrote:
But I'm reporting as an edge case, because I'm not sure it is supposed to work with the new behavior.
I'm keeping it this way (not working) for the moment, because it keeps it completely consistent with how Global variables work. But I see why you'd want to do what you did, and I think I can make it work... give me a day or two...
@toggledbits also using similar variables as @therealdb, so nice that there will be a "fix"
prevHour = dateparts(time()).hour - 1 currentHour = dateparts(time()).hour
-
Testing build 25272, and although the following findings may not be specific to this build, I'm reporting via this thread.
First, I noticed that if you have a long array in local expressions, UI is horizontally (over)stretched when viewing the rule (does not happen in edit mode). See below.
Secondly (and this can be user error), I was experimenting with failure handling and got the following:
The expression "isnull(blob?.data?.PriceWithTax) ? \"ERROR\" : blob.data.PriceWithTax" in variable "hourPriceBackup" of rule "Get prices" (rule-m0bb80xn) failed evaluation ReferenceError: Invalid scope in reference to member PriceWithTax of (number)0.10595 Last 20:55:07; this alert has repeated 2 times.
(PriceWithTax was intentionally left out from the response to cause error)
And below the actual expression:
What would be correct way to guard against this?
-
The error here is that
data
isn't an object, so you can't dereference through it. If you look at yourblob
, you've setdata
to a number (0.10595), and the error is telling you that you can't dereference through a number like an object. The coalesce operator isn't going to apply here, becausedata
is just the wrong type. I assert that your test case is broken and testing something you are never actually going to encounter in real life. Well-written APIs, for example, don't do things like this, at least, not without other clues (e.g. a type value in the response to tell you what kind of data is indata
, so that you can easily know how to handle it). -
The error here is that
data
isn't an object, so you can't dereference through it. If you look at yourblob
, you've setdata
to a number (0.10595), and the error is telling you that you can't dereference through a number like an object. The coalesce operator isn't going to apply here, becausedata
is just the wrong type. I assert that your test case is broken and testing something you are never actually going to encounter in real life. Well-written APIs, for example, don't do things like this, at least, not without other clues (e.g. a type value in the response to tell you what kind of data is indata
, so that you can easily know how to handle it).@toggledbits okay, maybe my test case wasn't the best possible... what about that UI issue (a long array)?
-
@toggledbits okay, maybe my test case wasn't the best possible... what about that UI issue (a long array)?
@tunnus already fixed for next build. Thanks for reporting!
-
Build 25278 now available, again docker 64-bit only, and only for the folks testing variables/expressions in this thread. Please read this for summary of behavior for global and rule-based variables in this build.
-
@toggledbits is alarm() a new thing? What's the best example to understand its use? IE: A global variable named christmas_time, that will be updated every hour/day with dateparts()? Thanks.
-
@toggledbits is alarm() a new thing? What's the best example to understand its use? IE: A global variable named christmas_time, that will be updated every hour/day with dateparts()? Thanks.
I think it's brilliant. My best example is to check if a
getEntity()
is not updated in X minutes by comparingtime()
withvalue.last_modified
but if the entity isn't updated the expression will not evaluate because nothing changed.
I'm now using other entities likereactor_system.reactor_uptime
for 1 minute interval checking but with the newalarm()
I believe I can skip that and set any interval suitable for each expression. -
@toggledbits is alarm() a new thing? What's the best example to understand its use? IE: A global variable named christmas_time, that will be updated every hour/day with dateparts()? Thanks.
@therealdb said in [Reactor] Variables not updating correctly in latest-25201-2aa18550:
A global variable named christmas_time, that will be updated every hour/day with dateparts()?
Yes.
alarm()
will do that.@Crille said in [Reactor] Variables not updating correctly in latest-25201-2aa18550:
My best example is to check if a getEntity() is not updated in X minutes by comparing time() with value.last_modified but if the entity isn't updated the expression will not evaluate because nothing changed.
Clever! One side effect, though...
getEntity()
creates an entity dependency for the expression, so that when the entity changes, the expression is re-evaluated. When the expression is re-evaluated, thealarm()
timer is not restarted if it is already running, the prior still-running timer is allowed to finish at its originally scheduled time. I'm guessing this may interfere with your intent — if you are using it to detect timeout, you probably want to push the clock out — but I can address that in the next build. -
My current simple use case does not have to be exactly X minutes.
do interval = getEntity( "reactor_system>system" ).attributes.reactor_system.reactor_uptime, meter = getEntity( "mosquitto-mqtt>smartmeter" ), (time() - meter.attribute_meta.x_uptime.value.last_modified) > 300000 ? bool(true) : bool(false) done
If I replace
interval
withalarm(60)
would that also start a new timer everytimemeter
updates or would I achieve the same behavior as now? -
My current simple use case does not have to be exactly X minutes.
do interval = getEntity( "reactor_system>system" ).attributes.reactor_system.reactor_uptime, meter = getEntity( "mosquitto-mqtt>smartmeter" ), (time() - meter.attribute_meta.x_uptime.value.last_modified) > 300000 ? bool(true) : bool(false) done
If I replace
interval
withalarm(60)
would that also start a new timer everytimemeter
updates or would I achieve the same behavior as now?@Crille said in [Reactor] Variables not updating correctly in latest-25201-2aa18550:
If I replace interval with alarm(60) would that also start a new timer everytime meter updates or would I achieve the same behavior as now?
No, if you replace
interval/getEntity()..reactor_uptime
withalarm(60)
, you won't get a new timer. Next build, you will be able to callalarm(0)
beforealarm(60)
(i.e.alarm(0), alarm(60), ...
) and that will cancel any existing timer first, then start a new timer for 60 seconds. In 25278, there's no way to stop the existing timer.