How to force variable setting to create an event every time

I have a USB "Temper" temperature sensor that I can query with Perl or Python code. I created a CGI script on my machine to display the temperature, and in Rule Machine I call that URL and assign the output to a variable. As described here "New App Features in 2.2.9" that variable assignment generates an event, but it only generates an event if the temperature being set hasn't changed since the last time it was set. Sometimes there can be hours between temperature changes large enough for Temper to return a different value.
I query the Temper every ten minutes.
How can I force an event to be generated every time I set the variable?

Not sure if you can with the variable approach, but it would be possible to have a virtual temp sensor driver that sends the event as a forced change. You would just have to update the virtual device instead of the variable. May have to create the driver, the system one probably does not force it.

I can probably fake out the system if after I set the variable I add 0.0001 to the value and set it again. But I don't know if Rule Machine will let me do math on the string returned from HTTP. I suppose I could also do it with string concatenation, if that's possible in Rule Machine.
EDIT: No, I can't do math on the string. Yes, I can force an update by immediately re-setting the variable with a value that has an extra zero added at the end: "%varname%0". As long as my temperatures have a decimal point, adding the zero forces an event with no serious side-effects. But really, I want a "force event when variable is set" option.

The platform doesn't send events that don't involve a change of state. This is true for variables and devices. These are, pretty much by definition, non-events.

1 Like

The platform will send an event if I set isStateChange:true in a driver, even if the value is the same. So the platform rightly doesn't limit "change of state" to mean only "change in value". It's me that decides what a change of state is, as it should be. If I want to issue multiple events for the same value because my idea of "change of state" isn't value-based, I can.

My state change decision for my Temper device events involves a change in time, not a change in value. The state is either "temperature update has been issued recently" or it's "not time yet". The state is evaluated based on a change in elapsed time, not on a changing value.

I want the same isStateChange:true capability for setting a variable as I already have if I were to write a driver to do it. The platform has the ability to do what I want; I just need easy access to it.

The platform doesn't support this for Hub Variables the way it does for sendEvent(), there not being a sendEvent method for a Hub Variable per se. You could do what you want with a virtual device, and a modified driver for a virtual device could use isStateChange:true. Or you could set a Hub Variable twice bam-bam to force a value change artificially.

Short answer: you can't.

I did it this way: I keep state in Rule Machine that knows the previous value I put into the variable, and if the new value hasn't changed from the previous value I add a useless zero to the end of the number and use that. Next time, the value won't have the zero and can be used directly. Next time, it will be the same as the previous value and will require the zero. Back and forth between these two states:



No need for a virtual device.

Except that it doesn't always work, because apparently in HE you can't accurately copy a hub variable into a local variable right after you have set the hub variable. Sometimes the local variable gets the old value of the hub variable, and sometimes it gets the new value that I just set. I would have expected that I always get the new value that I just set. There must be some HE internal timing or synchronization problem. I set up a test rule with a hub variable and a local variable:

Set hubvar to %hubvar%0
Set localvar to hubvar
Log: 'The local value is %localvar% and the hub variable is %hubvar%'

If I manually do "Run Actions" on this rule repeatedly, sometimes the localvar doesn't change value and the log message says the localvar and hubvar have different values:

info The local value is 12.3400 and the hub variable is 12.34000

I worked around the problem for my Temper rule by using a second local variable to hold the value that I was reading from the hub variable so that I don't have to read the hub variable again after setting it. I'll let that run for a while and see if that works every time.

Where is it documented that you can't accurately read a hub variable whose value you just changed? It would be helpful if Rule Machine would warn us not to do that.

I'm not sure that this behavior is specific to variables. This race condition pops up with devices as well where the trigger is also part of the actions (like an opening conditional statement). Easy fix is to add a one second delay before calling the variable again after the trigger.

1 Like

I don't follow why you illustrate this with a case where they are the same value. Also, we need to see the rule that causes this, and the logs for that rule running.

Please show us a specific example. Not aware of any race conditions around what you are saying, but can't possibly tell without a reproducible example.

I'm referring to the occasional post that pops up where someone is running an action against a device to change a state and then the next line is evaluating whether or not the state updated. That occasionally causes issues due to the device state not updating before the next line runs. There's, of course, a litany of reasons around the device itself that could cause that to happen.

So, just saying "it happens;" not necessarily trying to say there's a platform problem around it. Not that I've seen anyhow.

My example above was a poor one.

This post is a poor example also. If you turn on a switch that takes 200 msecs to turn on and report its new state, and you query the state of the switch 50 msecs later, of course it won't reflect its new state yet since it has not reported yet. This is not a race condition, this is expected behavior.

I say this because what @idallen says is happening is entirely a different thing. If one sets a Hub Variable to a value, and immediately reference the hub variable, it sure better have the value just set. If not, there is a serious problem to get sorted out in the platform.

2 Likes

No. 12.3400 and 12.34000 are not the same string values. One has an added zero.

I gave you the code for the rule. It's those three lines. Create a string hub variable, a string local variable, enter those three lines and push "Run Actions" a few dozen times. Eventually, the two values will differ when they should be the same. Here is is again:

Here are some log entries.

This is a race condition, so it doesn't always show up on every click of "Run Actions". I had to run this maybe seven times before it failed.

Below are two consecutive sets of log entries. idallenV1 is a hub string variable. localvar is a string variable local to the Test rule. The log set on the bottom shows correct behaviour: the local variable is being assigned the changed value of the hub variable: they are both 12.3400.

The log set on the top shows incorrect behaviour. The Set localvar to idallenV1 line is using the old value of the hub variable 12.3400, not the value 12.34000 that was just set immediately before. The Log line confirms that the two variable have different values (one has the added zero, the other does not) when they should be identical.

app:193 2023-05-13 22:34:04.874 info The local value is 12.3400 and the hub variable is 12.34000
app:193 2023-05-13 22:34:04.869 info Action: Log: 'The local value is %localvar% and the hub variable is %idallenV1%(The local value is 12.3400 and the hub variable is 12.34000)'
app:193 2023-05-13 22:34:04.855 info Action: Set localvar to idallenV1 variable(12.3400)
dev:133 2023-05-13 22:34:04.826 info idallenV1 variable is 12.34000
app:193 2023-05-13 22:34:04.805 info Action: Set idallenV1 to '%idallenV1%0(12.34000)'

app:193 2023-05-13 22:34:02.363 info The local value is 12.3400 and the hub variable is 12.3400
app:193 2023-05-13 22:34:02.358 info Action: Log: 'The local value is %localvar% and the hub variable is %idallenV1%(The local value is 12.3400 and the hub variable is 12.3400)'
app:193 2023-05-13 22:34:02.345 info Action: Set localvar to idallenV1 variable(12.3400)
dev:133 2023-05-13 22:34:02.321 info idallenV1 variable is 12.3400
app:193 2023-05-13 22:34:02.311 info Action: Set idallenV1 to '%idallenV1%0(12.3400)'

I rewrote the test to run itself every five seconds and count the iterations:

On run #21 the error appeared;

It happened again on runs #56, #92, #152, #171, #204, #325, #379, #512, etc.

This looks like some cache problem in the hub. We will look into it further.

3 Likes

The best approach here is to bypass a variable connector. There may indeed be a small delay between updating a variable and the time corresponding variable connector device is updated. Here is an example of the same logic that uses variable directly. I had it run for a while, and it hadn't failed yet.

A variable connector is a device, not a variable.

My comment about a Hub Variable having the correct value when referenced immediately after being set stands, and Victor is confirming that there is no observable failure associated with this. What I missed and Victor caught about your rule that fails, is that your rule references a connector device attribute, not a Hub Variable.

What you are doing is completely different, as your rule is setting the local variable from a variable connector device attribute. Hub Variable connectors are distinct objects from their underlying Hub Variables, and their attributes are set by an event generated from setting the Hub Variable. Such an event, like all other events, enters the event stream of the hub for processing. So a delay between setting the Hub Variable and retrieving an updated connector attribute is to be expected, and is not of a deterministic duration. This is why your rule behaves the way it does.

If you just set the local variable directly from the Hub Variable, instead of from a connector attribute, you wouldn't have this problem.

Ah, snarky comments always work well with us.... :sunglasses:

7 Likes

wow.... just....wow.....

Fail Dumb Ways To Die GIF

Yes, and where is this difference, and the delay when using a connector device attribute, documented?