-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Statistics sensor doesn't handle zero values correctly #67627
Comments
statistics documentation |
Hey there @fabaff, @ThomDietrich, mind taking a look at this issue as it has been labeled with an integration ( |
Hey @Flox-Muc,
Unrelated: I have other averaging characteristics on my todo list, so irrespective of the issue here, look out for those. |
Thank you for your quick response! And sorry that I didn't answer earlier. I probably have an idea what the problem could be. Take a look at my simplified example below: The blue line represents the sensor. The red dots are the stored values in the database. The green line represents the average of the last ten "hours" at "time" 10.5. Now look at the orange line at "time" 11.5: The error gets bigger the longer a sensor value is unchanged and the more consecutive stored values differ - so it's probably not a special problem with the zero. |
Probably none. The wind sensor gets its value via the Ecowitt integration every minute. But as the value is unchanged Home Assistant doesn't store any additional data point in the database, I think. Can you tell me how to extract the samples of the database? Then I could attach it.
The wind sensor from the Ecowitt integration is named "sensor.ws_windgeschwindigkeit". The two statistics sensors that show the error:
The sensor that I use to create the correct average:
The "input_number" is constantly changed by this automation that creates the mentioned jitter which forces Home Assistant to evenly store values:
I just created such a sensor - so I probably can tell you in a few days. |
I am having a similar issue, values are incorrect. Also when I do a avg over 24 hrs and 7 days, you would say that the averages should be different, however they are the same. Something's very off. |
There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. |
Still relevant. |
Hey guys, just a quick update from my side. Based on what was discussed here and in other places, these are the conclusions I drew:
Please let me know what you think. |
I just ran into this issue somewhat while trying to create a short window statistics sensor and it becoming The disadvantage of this approach is that the derivative trends to 0 but not always becomes 0, the advantage of the approach is that the sensor doesn't have to constantly check its state. I'm thinking of adding some logic to recalculate the state if it hasn't received an update for some time. Either based on the time window itself or via an optional parameter. With that I think we can get the best of both worlds (accuracy and speed) and add some customisation for the user if required. Since this sensor can also calculate more 'continuous' values such as standard deviation, I think the extra step of an optional For more info see: #31579 Most important implementation detail is that you have to keep the last value outside the window for your calculations. |
After spending too much time digging though many issues and the not so well conceived implementations of both the First of, the smoothing implemented in #65528 by @sophof in the Second, usage of the derivative function can be summarized to the following cases: I did a research on the history of commits changing behavior: As the author of the original derivative function (see commit 8a2bc99) in the For the competing The conclusion is that the At the last I am curious why there are two different integrations for the same purpose, why does the |
I'm in with @flo-wer's proposals however I want to point out that Maybe it fits for most cases (where at least one value is required) to do the following if no values were recorded: Use the current value of the sensor two times (one for the beginning & the other for the end of the time window). Then calculating the |
I must admit I was aware of the same (in my own way) as @flo-wer describes when I wrote my pull request, but I chose to be practical about it. For me this was simply the quickest way to achieve what I wanted and the old implementation was definitely incorrect in my opinion. With the limited time I have this was the best option for me. But yes, in essence I put a band-aid on something that probably shouldn't have existed in the first place. I'm not 100% sure, but I expect the same results could indeed be achieved by having the derivative sensor only calculate a naive derivative between two values and then handling the rest via the filter sensor. I'm personally not a big fan of intermediate sensors that you don't use, but that really is a different issue (and one can hide them I guess). This way it would be less redundant and in general you don't want each entity handling it's own 'filtering' probably. So I assume for statistics the same result could be achieved with the change per second characteristic? In that case for me at least it was just a case of not finding it (the last time I looked at the statistics sensor there was no derivative alternative afaik). I'm rambling a little, but I guess I'm saying I agree with this:
I do strongly think a good UI integration and an overall rethink of how to approach the subject is required in that case though. It seems we need to think about the scope of the integration in this case (where does this end?). |
I was pointed to this issue after struggling with both a Here's some example data and 4 different assumptions about what the data could represent: Assumption 1: Sensor sends new data at state change Assumption 2: Sensor sends stale data at state change Assumption 3: Sensor sends updates at unknown time-based intervals Assumption 4: Sensor sends updates at defined time-based intervals (and possibly also fresh data on state changes) Note that in the plots above I intentionally stopped the line at the point closest to 'now' (zero on the x-axis) where it is no longer possible to determine what the line will look like. In addition to picking which assumption is made about the data, there is also the issue about the oldest data point used in the
IMHO assumption 4 is probably the most-often-encountered representation of data where people are noticing issues with these sensors. (Meaning the data actually represents assumption 4 but the statistics/derivative sensors are assuming assumption 1 or 3). What I would love to see would be some configuration options in the statistics sensors (and derivative sensor) where we can choose what assumptions it should make about the source data. |
Maybe I misunderstand your post, but there's only one valid assumption for both integrations. AFAIK right now they both only update when a new sensor value is posted, so on calculation the last value is always at 'now'. Put in another way: when there's no state update both assume a constant derivative, not a constant sensor value, which isn't any of your examples I think. Or is that your assumption 4? To be clear, that is almost guaranteed to be wrong (since with time the derivative should then trend to 0), it just only really shows if there's a long gap in the sensor updates and the last derivative value was far from zero. |
This is almost true; the statistics sensor will update upon a new sensor value as you mentioned but will also update when the oldest sensor value ages outside of the
There's still an issue, and that is when a value is repeated. When a sensor has an update but it's the same value as the previous value, it isn't stored in the recorder database is this is where weird things happen. Lots of sensors have enough noise and small enough resolution where they don't see this. But if the sensor has a hard min or max (zero being the common one), or if it has low resolution and/or low noise, this issue pops up. The sensor I'm having an issue with is a water meter reader, and when I don't use water overnight, even though the sensor reports the reading every 2 minutes, the recorder database has a single datapoint for the reading when water was last used. Then the database can have 6+ hours before another data point appears when we use water in the morning. The statistics and derivative sensors don't assume a constant derivative when there aren't updates; they simply don't update at all (except as mentioned before when data points fall outside of
The derivative does not trend to zero as one would expect, because the derivative never recalculates after the last data point (and there is no data point at 'now'). If a change is implemented to force the sensor to update on command or at some interval, you'd see some odd behavior at times. A constantly increasing sensor updated every 2 minutes would have a sawtooth derivative if the derivative sensor were updated every 1 minute. (That is assuming the derivative sensor still interpolates data on the left/old side of the age window and holds the last value on the right/new side of the window.) |
The main point of my first comment was that whatever changes are made to the statistics sensor, the new behavior should be logically consistent. Specifically, whatever assumptions are made about the source sensor data on the right side of a moving time window (i.e. 'now'), the same assumptions should be made on the left side of the window (in the past). So for example, if it is going to be allowed to have a statistics sensor update (recalculate) 10 minutes after the last sensor data point (by assuming the stale source sensor data is still valid), then it should also be assumed that the sensor data stayed flat for 10 minutes as it moves to the left in the time window. So if there was an update to the sensor 11 minutes after the data point in question, then the statistics sensor should always perform calculations assuming the data point was flat for 10 minutes and then jumped to a new value at 11 minutes. It should never interpolate between the first data point and the 11-minute data point, forgetting that at one point in time it assumed there was another data point. The only possible logically-consistent assumptions I can come up with are the 4 examples that I listed in my post above. Anything else just makes an assumption about the data now for convenience, and then makes a different assumption about the data when it becomes older. I can't come up with a scenario where that is a good idea. |
I love the direction all this is headed, it sounds very exciting to have sophisticated statistics capabilities.
Source: https://community.home-assistant.io/t/add-force-update-support-to-template-sensor/106901/31 |
#88655 is another solution that would avoid the statistics sensor from going into an It does not change the current timing of statistic sensor updates which is discussed above. |
I just want to chime in here since I see that a lot of discussion is about the averaging case for statistics. I want to be sure that whatever fix that is implemented for this issue also works for the 'state_characteristic: total' use case as well. My use case is using the statistics sensor to generate rain amount totals for N periods of time looking back from the present time, e.g. 1 hour, 6 hours, etc. As such utility meter is not suitable for my needs since its time boundaries are chronology based. What I have setup is working well with the oldest data aging out as I would expect, it is just this zero handling issue that is making things not work quite right. But like the averaging case, I too get Unknown states when there are long periods of no data updates to the statistics sensor before hitting the max_age timeout. The statistics sensor is getting 0.00 values once per minute the entire time. So it is being fed information from a ESP Home device continuously, but the values are zero for hours, days, and maybe even a week or more stretches. So the basic problem that I'm seeing is well captured by this issue. |
Chiming in because once again I've picked up a new part of Home Assistant and once again, it's sent me on an hours-long goosechase. It didn't take me long to figure out "oh, the temperature isn't changing much outdoors, is that why this 1m average sensor is 'unavailable'?", but even after making the jump to "I probably need I figured I could ditch the mess of JSONata and Node-RED flows I used to post weather data to PWS pre-Home Assistant. After all, I have all the sensors in here over MQTT, why can't I just slap an average on them and have it post every minute? So… what exactly are we doing here? I'm hearing "making fancy new additions to statistics", but… what can I do to work around this now, and what can I do to fix the codebase now? |
By the way, this is making mean sensors fail for a weather sensor which is sending data every fifteen seconds. It's just that the temperature often won't change by more than 0.1° every minute, and the humidity is measured in integer percent… it's been pouring rain all day and it's pegged at 91%, so Home Assistant simply doesn't see any data going back, oh, probably an hour. Why tie a moving window of values to a persistent storage backend? Shouldn't we be able to disentangle "I want a moving average of incoming data" from "I want to only store changes"? |
If you want to skip a whole bunch of learning just use the workaround I posted above. I've had it in place for two months now and it works great. |
In addition to seeing the repeated zero value manifestation of this bug, I'm now 98% convinced that I'm seeing the above comment issue too when there are back to back non zero values that are identical. In my case it is when tracking rainfall. The issue I'm seeing is described in this community post: https://community.home-assistant.io/t/statistics-sensor-becomes-intermittent/591213/4 In my implementation I'm am using the 'state_characteristic: total' for the statistics sensor. |
Hey all, Thanks for summarizing the problem in such detail!! I would certainly like to fix it, but can't promise any ETA. If anyone wants to help with a fix, I'd happily review a PR. |
@ThomDietrich The main issue is the missing data from the sensor due to repeated sensor values not being stored in the recorder. I'm guessing this was an optimization to reduce db usage, and anything that is not changed is assumed to be in the same state. This is good enough for most use-cases, but not so great when running statistics on the data. @juicejuice's workaround is a pretty good one. Essentially you're duplicating the sensor, and forcing an update to the db on a regular interval (every minute), rather than only updating when the source sensor is updated/polled. This may update the sensor much more or less frequently than the actual sensor though, so individuals will need to consider the chosen interval based on their use-case. This may cause issues with algorithms that interpolate between the data points though, as this sensor's data can be much more fine grained than the source sensor. I believe #88655 may also provide an easy way for others to work around the issue for most people using the Perhaps there's an argument that the new feature in this PR should be on by default, to avoid some of these issues from being filed. |
I invite people to vote on a feature request to enable a method to solve this problem. Or, if you don't agree with that feature request, it would be a good forum to suggest changes or to link to a different feature request which has your preferred solution. |
There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. |
Still relevant. |
still broken |
I haven't tested yet but I think this issue might be fixed in an upcoming release: https://developers.home-assistant.io/blog/2024/03/20/state_reported_timestamp/ |
I've read the comments somewhat quickly, but want to throw ideas for semantics. First, we need to define the meaning when there aren't data points. For that we need to define the meaning of a sensor at times other than when it is reported. For a sensor that is once a minute, it is understood that these are samples of a perhaps-more-complicated process and we don't know about the state in between. For a sensor that is updated when the value changes, we still are fuzzy on exactly when the real-world state changed, and the shape between updates when those updates are at the max rate it uses. But when there is no update for hours, it is pretty safe that the value is unchanged. As an example, consider an energy meter on a well pump. And consider "well energy last hour". (Really, energy is converted to gallons via calibration, so it's "well gallons last hour".) This leads to saying "if there is no data point in the hour, that means the value over that hour was equal to the previous report", and that lets us create synthetic points for beginning and end of hour, and then use those for subtraction, min, or whatever. And, if there is a single data point in the hour, then that's the value at the end, and we need to look at the most recent point before that (before the hour) to get the start value. I think this gets users what they expect, treating "most recent report at time t" as the value at t. The second thing is that the sensor's semantics are defined as being over some time interval. It would be far cleaner if the sensor always had that value, rather than only updating when the underlying sensor updated. Well gallons last hour in particular should go to zero 1 hour after a report of a new energy value, if no new reports are received. I think it should not be that hard to determine the time at which the values used in the computation will age out (or might age out) and schedule a wakeup/recompute for that time. Of course it needs recomputing on new values too. But this way, the sensor can be defined to be what it says, without any hard-to-understand and not-what-you-want semantics. Thanks for listening! |
My two cents, the last value counts, for sensors that don't change/update. I tried to configure a daily average for a methane sensor. That methane sensor spikes a few times over the week and is zero in between. |
I have created a pull request to fix this issue #124644 |
My pull request will solve most of the issues discussed here, let's hope they will integrate it soon. However, some level of weirdness will still remain. The linear average will be "jumpy" . If you look at a value that is constant for a long time and then suddenly changing to a different value, the linear average will show a sudden drastic change, Assuming you have an equally spaced measurement like this: 0 (0) (0) (0) (0) 10 (10) (10) The linear average would compute this: 0 0 0 0 0 5 5.83 6.42 The average step would compute this: 0 0 0 0 0 0 1.66 2.85 The linear average will "jump" to 5 because all (0) values will be ignored, and hence, the linear model assumes a linear increase from the first 0 to the first 10. The average step function will behave more like what you would expect from a moving average and will change slowly after a sudden change of the input values. In my opinion the linear average is pretty useless since it doesn't give you the smoothed curve you would expect from an average function. It will only behave nicely when you have values that are noisy, so that the values will always change, and hence no value will be ignored. In the case of noisy values both average functions compute very similar values though, and I don't see the need to have both options then. Another thing to consider is the loss of precision you get for longer intervals. As far as I understood, all states older than 15 minutes are replaced by a 15 minutes average that home assistant is computing elsewhere. This average computation is most likely not taking into account the time between changes, so the precision of the statistics will most likely not be super exact anyway. Here is a screenshot of the differences between the two functions: The values are generated by a test template:
and the averages are computed like this:
|
Since getting this into the core system seems to take quite some time, I have published a It would be great to receive feedback regarding the changes. |
There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. |
The problem
As you can see in the picture below the statistics sensor seems to ignore 0 values. Both "average linear" and "average step" types jump to higher values as soon as the source sensor (in the picture the graph at the bottom) has a value of "0". The dark blue line in the upper graph ("Windgeschwindigkeit mit Jitter") shows how the "average step"-sensor should behave correctly. (It is created using an automation that adds an artificial jitter to the original value every second.)
What version of Home Assistant Core has the issue?
core-2022.2.2
What was the last working version of Home Assistant Core?
No response
What type of installation are you running?
Home Assistant Core
Integration causing the issue
Statistics
Link to integration documentation on our website
https://www.home-assistant.io/integrations/statistics/
Diagnostics information
No response
Example YAML snippet
No response
Anything in the logs that might be useful for us?
No response
Additional information
No response
The text was updated successfully, but these errors were encountered: