Why isn't a statistics sensor of an "input_number" entity possible?

Is there a specific reason an input_number can’t be used as the entity for a statistics sensor?

I am using an input_number as a kind of “global variable” to exchange data between scripts (which feels like a hack to be honest, with no possibility to share anything else but a single number per entity; is that the only way? I didn’t find any other - that doesn’t feel even more like a bodge; anyways…).

The input_number won’t be changed by a person, just by scripts. One of the scripts needs to work with the minimum of the number of the last minute/3 samples. This is exactly what a statistics sensor can provide. But a statistics sensor only accepts a numeric sensor or binary_sensor. For all I can see an input_number behaves the same as a sensor does. It has a history, can trigger actions on state change aso.

The roundabout way to get it to work is a template sensor that tracks the input_number’s state and then apply the statistics sensor to that. Am I missing something? These extra steps shouldn’t be necessary.

Hi Lupin,

There is this:
Trigger based template sensor to store global variables.

You can also create MQTT entities to store most of the things.

These are exactly those things that feel even more like a hack, but it isn’t the question of my original post anyway (it’s just something I came about while wondering about the initial question, which is also why I put it in parenthesis).

So is there any reasoning why input_number can’t be a source for a statistics sensor?

Not really, other than that the person who implemented it would probably have thought it does not make sense for most use cases. Input numbers are normally not measurements.

But if I would pick the entity type that is the most hacky for your use case: using an input_number for something that is never input by a person is the most hacky. Sensors are what is used for data that is not input manually. And those can be used both for statistics and long term statistics.

How do you get the data - is it possible to have no scripts but just a (trigger based or other) sensor?

1 Like

Which is exactly what I’d prefer to do. I just haven’t found a way to create a sensor, the value of which is set by a script. There’s no helper for that.

Use a trigger-based template sensor and trigger it with a custom event… as Sir_Googenough posted earlier.

Where is the script getting the value from?

Yes, I edited in the same question in right after posting. If we know a bit more, we might be able to help you get the least hacky statistics :slight_smile:

It’s not that it isn’t working (well kind of, I just found the statistics value_min sensor is kind of useless on a sensor that doesn’t change at a constant rate), it just doesn’t feel right to use an input_number and on top of that “mirror” it with a template sensor.

The setup is quite involved (but surely not unique). It’s about using excess PV energy to heat water. To avoid confusion the scripts are python_scripts called as an action of an automation. YAML is so fiddly that there’s no way I would ever write the scripts in YAML, where something that takes two lines in Python becomes 10 lines :face_with_raised_eyebrow:.

One script (1) is triggered when there are new data from the solar inverter (every 10s).
Another script (2) is triggered by a new temperature reading from the water heater (essentially an ESPHome device that also does the relay switching to adjust the heater power level in several steps). That’s also about every 10 seconds but not synchronized with 1.

Script 1 takes into account the power from/to the grid, the current load on the three phases, the PV voltage, a heater power limit set by script 2, and the recent power setting (that’s what the statistics sensor should be for) and eventually sets the power level (a number, not input_number, in this case as it’s an entity created by ESPHome, but the thing about statistics sensors not being able to use them applies to both types), and respective phases for the ESPHome device.

Script 2 watches the heater temperature and calculates a power level limit depending on absolute temperature and temperature change (with a derivative sensor). The calculated limit is written into the infamous input_number, which is in turn read by script 1.

It is working (unless I mess up; after changes I always have to wait for the next day for the sun to come back to see if it’s still fine or pulls 6kW of expensive electricity from the grid to heat water :sweat_smile:), so I don’t want to refactor everything. If a different solution isn’t helpful here, it will be another time, because there’s always the next project, where I want to do things better.

Currently my main gripe switched to the statistics sensor not working the way I though it would, because if a value hasn’t changed it’s kind of ignored, making asking for the minimum of the last 30 seconds for example pointless. But that’s a topic for another hack :wink:.

I think the short description of a solution without (!) input helper might be possible: a trigger based template sensor uses the water heater temp as a trigger, calls the python script as an action, returns a value in the response variable, which is stored in the sensor. If you look at examples on how to get weather forecast data in a sensor, you’ll get the idea. Only the action is now your python script, and the trigger is a numerical state trigger.

Check the example for Example template sensor using get_forecasts in the link below for the concept (albeit a very different use case):

Thank you! One “problem” less. With that I could get rid of the input_number and the accompanying automation. And I learned how to return values from a python_script.

Now there’s still that “number mirroring sensor” for the statistical sensor, the latter of which doesn’t work as expected anyways :thinking:

1 Like

You should need nothing but the trigger based template sensor and the statistics sensor if the trigger based template sensor has state class measurement.

Now to get the statstics sensor working again (until they fix the underlying problem), once the hack level has lowered to make room for a new hack…

There is a dirty trick you could use to fix that too. Some people use a random, very small number that they add to the measurement to get it recorded. You could add an extra time based trigger to your template based sensor to determine how often you want values (or do away with the other trigger entirely). So. there. Hack level back to before, but working statistics :wink:

Yep, the random number “trick” is what I read about already as well. I just hoped things have changed in some way and there would be another way.

template:
  - trigger:
      - platform: state
        entity_id:
          - sensor.active_power_total_recent_statistical
    sensor:
      - name: heater_controller_power_level_mirror
        unique_id: 8b72e328-a083-4997-bb2f-9ea4dd5dc474
        state_class: measurement
        state: >-
          {{ states('number.heater_controller_power_level') | float + (range(100,1099) | random) / 10000}}

That’s the sensor that mirrors the original number sensor (because statistic sensors can’t work with number), and gets added a random number (because statistic sensors are blind to constant values). Never mind that this work around makes a float out of something that should be an int with discrete values between 0 and 7 (“fixed” by casting it back to an int in the following script 1).

Script 1 is triggered by the same trigger and in the process sets ‘number.heater_controller_power_level’. Is there a way to make this template sensor only triggers AFTER that script has finished? I can’t trigger on a number.heater_controller_power_level state change (because it might not change), but with a trigger like this it might apply the “randomness” to the previous value of number.heater_controller_power_level (because I have no idea which trigger runs/finishes first).

Btw. it was really hard to find which functions can be used in state templates. I came across the range() and random filter in some forum posts, but in no documentation. Is there any for that? (it’s not in Templating)