Display Fan Percentage

Hi !

Because it seems not possible to get the fanspeed directly in webserver I want to display the current percentage value of my fan component seperately.
But how I can get the current value and get a sensor with it’s value ?

Here is my created fan:

fan:
  - platform: speed
    id: the_fan
    output: fan_pwm
    name: $name Fan
    speed_count: 100
    on_turn_on:
      - switch.turn_on: fan_power
      - logger.log: "Fan Turned On"
      - fan.turn_on:
          id: the_fan
          speed: 1 #turn on the fan with initially 1% instead of 100%
    on_turn_off:
      - switch.turn_off: fan_power
      - logger.log: "Fan Turned Off"

And my created sensor:

sensor:
- platform: template
  id: fan_percent

In your template sensor lambda the docs say you can access speed like this.

id(my_fan).speed

This is working for me:

- platform: template
  id: fan_percent
  name: "Fan PWM"
  lambda: |-
    if (id(the_fan).state == true)
    {
      return id(the_fan).speed;
    }
    else
    {
      return 0;
    }
  update_interval: 10s
  icon: mdi:percent
  unit_of_measurement: "%"
  accuracy_decimals: 0

But it would be nicer if a new value would be reported on value change and not only every 10sec…

1 Like

I think if on a speed set trigger you publish the id(the_fan).speed (or x) to your fan_percent sensor then it will update instantly.

Thanks ! This is working for me:

fan:
  - platform: speed
    id: the_fan
    output: fan_pwm
    name: $name Fan
    speed_count: 100
    on_turn_on:
      - switch.turn_on: fan_power
      - logger.log: "Fan Turned On"
      - fan.turn_on:
          id: the_fan
          speed: 1 #turn on the fan with initially 1% instead of 100%
      #- output.set_level: # alternative approach for turning on with initially 1% instead of 100%
      #    id: fan_pwm
      #    level: 1
    on_turn_off:
      - switch.turn_off: fan_power
      - logger.log: "Fan Turned Off"
      - sensor.template.publish:
          id: fan_percent
          state: !lambda 'return 0;'
    on_speed_set:
      - sensor.template.publish:
          id: fan_percent
          state: !lambda 'return id(the_fan).speed;'

But is there a way to initialise “fan_percent” template sensor with 0 ? I can’t find an inital_value attribute or something else…

- platform: template
  id: fan_percent
  name: "Fan PWM"
#  lambda: |-
#    if (id(the_fan).state == true)
#    {
#      return id(the_fan).speed;
#    }
#    else
#    {
#      return 0;
#    }
#  update_interval: 10s
  icon: mdi:percent
  unit_of_measurement: "%"
  accuracy_decimals: 0

And if I try to use this:

- platform: template
  id: fan_percent
  name: "Fan PWM"
  lambda: |-
    if (id(the_fan).state == false)
    {
      return 0;
    }
#  update_interval: 10s
  icon: mdi:percent
  unit_of_measurement: "%"
  accuracy_decimals: 0

I get this error:

/config/esphome/wr-lufter-dallas-sensor.yaml: In lambda function:
/config/esphome/wr-lufter-dallas-sensor.yaml:182:3: error: control reaches end of non-void function [-Werror=return-type]

Not sure but try adding an else for the true condition that returns the current state (that value gets updated from elsewhere in your code).

return {}

1 Like

yep, saw this in the docu aswell:
return {}; if you don’t want to publish a new state (advanced).

And seems to work:

- platform: template
  id: fan_percent
  name: "Fan PWM"
  lambda: |-
    if (id(the_fan).state == false)
    {
      return 0;
    }
    else
    {
      return {}; //if you don’t want to publish a new state (advanced)
    }

But I thought this wouldn’t update the value and nothing else ?
And you mentioned:

Could you explain ?

Not sure I can explain well …

on_speed_set:
      - sensor.template.publish:
          id: fan_percent
          state: !lambda 'return id(the_fan).speed;'

^^^That part is pushing values into the sensor when the fan is on and speed changes, and the {} is just retaining the current value. It’s valid way to do it I think. Might be a cleaner way but I think it’s ok.

1 Like

That’s just what I want :slight_smile:

1 Like