Sensor: Allow only positive values an zero but no negative values

I have set up the Shelly3EM module to measure my solar power.
For this purpose I have created a sensor that sums up all three phases as follows, which works perfectly:

template:
  - sensor:
    - name: "Shelly3EM02: Total power"
      unique_id: shelly3em02_power_total
      state: >-
          {{ 
            [ states('sensor.shelly3em02_channel_a_power'), 
              states('sensor.shelly3em02_channel_b_power'),
              states('sensor.shelly3em02_channel_c_power'),
            ] | map('float') | sum
          }}
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      availability: >-
          {{ 
            [ states('sensor.shelly3em02_channel_a_power'), 
              states('sensor.shelly3em02_channel_b_power'),
              states('sensor.shelly3em02_channel_c_power'),
            ] | map('is_number') | min
          }}

The problem is, that when the solar panels do not produce any energy, the sensor shows minimal negative values between 2 and 3 watts.
So I decided to create another sensor which should take the value from the sensor above but only allow values 0 (zero) and positive values as follows:

template:
  - sensor:
    - name: "Shelly3EM02: Total power positive only"
      unique_id: shelly3em02_power_total_positive_only
      unit_of_measurement: W
      state: >-
        {{ [ states('sensor.shelly3em02_power_total')|round(1), 0 ]|max }}

Unfortunately the reult is always “unavailable”.
Any suggestions what the problem could be?
Thanks a bunch in advance!

States are always strings, so you need to convert it to a float… EDIT (See Petro’s comment below)

You need to convert the availability of your other sensor as well or you may get weird results.

template:
  - sensor:
    - name: "Shelly3EM01: Total power"
      unique_id: shelly3em01_power_total
      state: >-
          {{ 
            [ states('sensor.shelly3em01_channel_a_power'), 
              states('sensor.shelly3em01_channel_b_power'),
              states('sensor.shelly3em01_channel_c_power'),
            ] | map('float') | sum
          }}
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      availability: >-
          {{ 
            [ states('sensor.shelly3em01_channel_a_power'), 
              states('sensor.shelly3em01_channel_b_power'),
              states('sensor.shelly3em01_channel_c_power'),
            ] | map('is_number') | map('float') | min
          }}

    - name: "Shelly3EM02: Total power positive only"
      unique_id: shelly3em02_power_total_positive_only
      unit_of_measurement: W
      state: >-
        {{ [ states('sensor.shelly3em02_power_total') | round(1), 0 ] | max }}

Unless you have each sensor in it’s own file, make sure you do not repeat the top-level template: configuration variable.

Round changes it to a number without needing float

3 Likes

Thanks guys.
I now changed to this but it still shows as “unavailable”:

template:
  - sensor:
    - name: "Shelly3EM02: Total power"
      unique_id: shelly3em02_power_total
      state: >-
          {{ 
            [ states('sensor.shelly3em02_channel_a_power'), 
              states('sensor.shelly3em02_channel_b_power'),
              states('sensor.shelly3em02_channel_c_power'),
            ] | sum
          }}
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      availability: >-
          {{ 
            [ states('sensor.shelly3em02_channel_a_power'), 
              states('sensor.shelly3em02_channel_b_power'),
              states('sensor.shelly3em02_channel_c_power'),
            ] | map('is_number') | min
          }}

    - name: "Shelly3EM02: Total power positive only"
      unique_id: shelly3em02_power_total_positive_only
      unit_of_measurement: W
      state: >-
        {{ [ states('sensor.shelly3em02_power_total') | round(1), 0 ] | max }}

For things like this, I’d take a two stage approach. With two different sets of templates.

The first step is to clean up the input data. So for each phase a, I’d create a new sensor that filters out the bad data. For you that is negative data.

{{ [ states('sensor.shelly3em02_channel_a_power')|float(0), 0.0 ] | max }}

Once this is in place, then doing the sums is easy since the data is cleansed.

For more complex cleansing you can use the filter integration. I use this on every temperature sensor to remove the random bad data points that occur occasionally.

Thanks!
I now made three different sensors for each phase and they work.
However the summarized entity still does not work, it still shows up as “unavailable”.
Any idea what I’m doing wrong?

template:
  - sensor:
    - name: "Shelly3EM02: Phase A: Positive power values only"
      unique_id: shelly3em02_phase_a_power_positive_only
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      state: >-
        {{ [ states('sensor.shelly3em02_channel_a_power')|float(0), 0.0 ] | max }}
    - name: "Shelly3EM02: Phase B: Positive power values only"
      unique_id: shelly3em02_phase_b__power_positive_only
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      state: >-
        {{ [ states('sensor.shelly3em02_channel_b_power')|float(0), 0.0 ] | max }}
    - name: "Shelly3EM02: Phase C: Positive power values only"
      unique_id: shelly3em02_phase_c_power_positive_only
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      state: >-
        {{ [ states('sensor.shelly3em02_channel_c_power')|float(0), 0.0 ] | max }}
    - name: "Shelly3EM02: Total power: Positive only"
      unique_id: shelly3em02_power_total_positive_only
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      state: '{{ states("shelly3em02_phase_a__power_positive_only") | float +
states("sensor.shelly3em02_phase_b__power_positive_only") | float + states("sensor.shelly3em02_phase_c__power_positive_only") | float }}'

You are missing a sensor. on the first element. Best way to make these is to go into developer tools / templates and work on the expression until it works, then paste it in the YAML and you are good to go.

1 Like

Thanks a bunch for the hint man, I didn’t know about the very useful developer tools feature, dumbe me was always rebooting after every try. Now I finally made it within a few minutes:

template:
  -sensor:
    - name: "Shelly3EM02: Phase A: Positive power values only"
      unique_id: shelly3em02_phase_a_power_positive_only
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      state: >-
        {{ [ states('sensor.shelly3em02_channel_a_power')|float(0), 0.0 ] | max }}
    - name: "Shelly3EM02: Phase B: Positive power values only"
      unique_id: shelly3em02_phase_b__power_positive_only
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      state: >-
        {{ [ states('sensor.shelly3em02_channel_b_power')|float(0), 0.0 ] | max }}
    - name: "Shelly3EM02: Phase C: Positive power values only"
      unique_id: shelly3em02_phase_c__power_positive_only
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      state: >-
        {{ [ states('sensor.shelly3em02_channel_c_power')|float(0), 0.0 ] | max }}        
    - name: "Shelly3EM02: Total power: Positive only"
      unique_id: shelly3em02_power_total_positive_only
      unit_of_measurement: W
      device_class: power
      state_class: measurement
      state: >- 
        {{
            [ states('sensor.shelly3em02_phase_a_positive_power_values_only'), 
              states('sensor.shelly3em02_phase_b_positive_power_values_only'),
              states('sensor.shelly3em02_phase_c_positive_power_values_only'),
            ] | map('float') | sum
          
        }}

Solved!

2 Likes