I’m working on a presence system for HA and I have an input_number sensor that I use to show how ‘hot’ a zone is. That is the count is incremented when a presence detection sensor is ‘on’ and decremented when the sensor is ‘off’.
This works but sometimes I see warnings in the log when the code tries to set the input_number to less than zero. I suspect some sort of race conditions are going on. This is my code:
Now I can see what is happening (I think) - the state is getting updated by another callback after get_state but before set_value. In c# (that I’m most familiar with) I’d be looking into semaphores and other mutual exclusion patterns but i’m not sure that would be right here.
All I want to do is increment/decrement an input_number sensor based on sensor values within a zone. Is there a better way?
I don’t see that this would result in a value less than zero. You may not get the value you expected, but it will always be the number received by the thread for this app, and then adjusted by 1. AD then sets the value in HA via the API, which I assume has its own thread control, but in any case wouldn’t cause an error in AD.
It isn’t an error in AD - just a warning back from HA stating the input_number is being set out of range. It isn’t a problem as such but I’d prefer to do this the ‘right’ way. I don’t really understand how the count can end up less than zero since all sensors should only do +1 or -1.
sensor A goes from on to off > input_number -1
sensor B goes from off to on > input_number +1
i would go with:
sensor A goes from on to off > check state from all sensors > result to input_number
sensor B goes from off to on > check state from all sensors > result to input_number
I will add that based on the architecture of AD it is perfectly possible for 2 threads to be accessing your code at once, and also that the get_state() calls operate locally without going back to AD (although they correctly reflect any changes made by set_state() calls which do go back to HASS).
The state itself is protected by locking so 2 threads reading state info one after each other will take it in turns but looking at the code for set_state() it would be possible for a race condition to set AD’s state differently to HASS’s idea of the same state.
Moral of the story - use locks if you are trying to set state to the same sensor concurrently.
it is impossible to lock an HA service for the while that an app is running.
thats why i suspect its an achitectural failure.
in the case that its possible that sensor A presents a decrement before sensor B presents an increment, with the result that the input_number gets below zero for a short period there are 3 options in my eyes:
set the “normal” value from 0 to 10, so that the problem doesnt exist.
check the value before sending it and if its below zero, make it zero (so no decrerment when zero is reached)
no decrement and increment at all, but calc the value from sensor states. (which is probably the most reliable option)
I had tried 1. and 2. before. I’ve reworked things to check all sensors and set the value from that. The code is much clearer and its working far better so thanks for the prompt!
Still interesting on using get_state + set_value at the same time… will avoid using that pattern in future I think.
you need to remember that all you do is sending requests to HA.
so you cant really do it at the same time, they will be handled in the order they come in in HA.
and you work on a distance(even when you have both AD and HA on the same device). so anything can infuence the speed that the commands get send and answered.