Variables not being updated by multiple scheduled tasks


#1

1) Give a description of the problem
This piston is designed to notify a visitor to the porch when the sensor activates. To help prevent false notifications, this is suppressed for a few mins if we have arrived home, or walked up to the front door from inside (hall sensor)

2) What is the expected behavior?
The multiple scheduled tasks on the with sensor/presence increment a variable when there is activity. This prevents the notification if the porch sensor is activated. After a wait, the variable is decremented. The same variable is used (with 5 min wait) to prevent multiple notifications, and also if the porch senses movement when the counter is not 0 (i.e we’ve just arrived home or are leaving)

3) What is happening/not happening?
The piston is working well most of the time. However, occasionally, the notify variable has a value of -1. (hence condition =< 0 on line 23) I can’t see how notify can ever get to a value of -1, unless a multi scheduled task is not fully running, or there is a semaphore issue where two tasks try to set the variable at the same time?

Is this a bug, or am I doing something wrong/not understanding?

**4) Post a Green Snapshot of the piston![image|45x37]

5) Attach any logs (From ST IDE and by turning logging level to Full)
nothing in the logs


#2

Having given this issue some more thought, I’ve changed the title to better reflect the issue.

I suspect multiple tasks are trying to update a variable at the same time, leading to some updates being lost/overwritten. I wonder if webcore semaphores the updating of variables?

I’ve added some watchdog code which wakes up every 2 mins. If there have been no events fired for 6 mins and the notify variable is not zero, it sets it to zero. (as thats the value if should be after 6 mins of no activity)

This feels rather an inelegant solution, is there a better way of getting this to work?


#3

Well, you have 4 devices acting as triggers. This means that if any of the motions change to active, or if any of the presence changes to present, then there will be math done to the variable.

So, for example, if you and the missus come home in the same car, and walk past Motion Sensor 2, then you are effectively creating (notify + 1 + 1 + 1) in a short time period.

I suspect this is the root of your semaphore waits.


#4

That’s my suspicion too. The issue does seem to arise when there has been more activity. If you go in and out a few times there can be waits expiring too causing even more updates of the variable.

Is this a bug/issue in the way variables are updated in webcore? Is there any way to ensure the variables are updated correctly?

For interest this is the code with the watchdog (from line 73)
It also includes the updating of the last_event variable whenever a trigger event occurs (lines 26,53,67)
Although this works quite well, its not 100% and is rather inelegant. I don’t like waking every 2 mins to check everything is in the correct state.


#5

Well, with “Task Cancellation Policy” set to "Never…
You are forcing each block to finish in it’s entirety no matter what…

And with your “Task Scheduling Policy” set to “Allow multiple”…
then each time any of the 4 triggers fires you are creating an additional schedule for wakeup.

Using more than one trigger is not helping either…
For example, when line 62 becomes true, then you may find that the lines 49-60 are executed first.


The way I would do it is simply keep lines 23-38, and move the other logic into their respective pistons. (IE: lines 49-60 should go into your welcome home piston, and lines 61-72 should go into the piston that usually monitors that sensor)

The only other change I would do is to use a global variable instead of a local one. This way, there’s no need for loops, waits or repeats. Each event only triggers a single piston, and when that piston executes, the global is updated. (I’d probably use a boolean global (true/false) instead of plus/minus one)


#6

Thanks for your comments.

I’ve always tried to write my pistons to cover a particular automation, so this one covers the porch visitor. Is the recommendation to try to only have one piston subscribed to a particular trigger, and handle everything that then use that trigger from there, including global var setting?

In my code, the order of execution should not be an issue (line 49-60 running before line 62) as I use the variable to keep count of which trigger is cancelling the porch notification. I need to use the int rather than a bool here, as I want the notification suspended until 2 mins after the last sensor activation.

I’m not sure how using a global var & single piston would help as there would still be multiple wakups updating one variable?


#7

Personally, this is the way that I always try to code, whenever possible. The more pistons responding to an event, the more likely occasional commands will not make it thru to the device.


From what I see, all four triggers modify the same variable, potentially within a few seconds of each other. (due to your multiple triggers in one piston) This piston is going to run top to bottom at each event. (meaning there will be multiple blocks in limbo at the same time, but a new trigger event will still modify the variable)

I am not saying that it is impossible to do this in one piston, but it is definitely not the path I would take.


Yes. My global advice is only referring to pistons with a single trigger, since globals are not written until the last line of code has been executed.


If you are still determined to make this piston work, I would add at least eight “log to console” scattered about in your code, so you can easily see all the overlapping that you are creating. (I would make one before and after each wait)

temp