Working MQTT FAN yaml?

Does anyone have a working MQTT Fan yaml? I have a few examples in the community, along with the one in the docs, and nothing works. The percentage field always remains null. Here is the yaml, I am trying to get working on 2021.5.4

  - platform: mqtt
    name: "Office Fan"
    command_topic: "cmnd/office_fan/POWER1"
    state_topic: "stat/office_fan/POWER1"
    state_value_template: >
      {% if value_json.POWER1 is defined %}
        {% if value_json.POWER1 == OFF -%}off{%- elif value_json.POWER1 == ON -%}on{%- endif %}
      {% else %}
        {% if states.fan.office_fan.state == 'off' -%}off{%- elif states.fan.office_fan.state == 'on' -    %}on{%- endif %}
      {% endif %}
    availability_topic: tele/office_fan/LWT
    payload_off: 'OFF'
    payload_on: 'ON'
    payload_available: Online
    payload_not_available: Offline
    percentage_command_template: >
      {% if value == 33 %}
        '3,0'
      {% elif value == 66 %}
        '3,1'
      {% elif value == 100 %}
        '3,3'
      {% else %}
        0 
      {% endif %}
    percentage_command_topic: "cmnd/office_fan/TuyaSend4"
    percentage_state_topic: "stat/office_fan/speed"

This was one for a 4 speed fan with preset modes, not sure if it will help

fan:
  - platform: mqtt
    name: "Master Bedroom Fan"
    command_topic: "zigbee2mqtt/Bedroom Fan/set/fan_state"
    availability:
      - topic: "zigbee2mqtt/bridge/state"
    json_attributes_topic: "zigbee2mqtt/Bedroom Fan"
    state_topic: "zigbee2mqtt/Bedroom Fan"
    state_value_template: "{{ value_json.fan_state }}"
    unique_id: "mqtt_fan_master"
    speed_range_min: 1
    speed_range_max: 4
    percentage_state_topic: "zigbee2mqtt/Bedroom Fan"
    percentage_value_template: "{{ {'off': 0, 'low': 1, 'medium': 2, 'high': 3, 'on': 4, 'smart': 0}[value_json.fan_mode] | default('0') }}"
    percentage_command_topic: "zigbee2mqtt/Bedroom Fan/set/fan_mode"
    percentage_command_template: "{{ {0: 'off', 1: 'low', 2: 'medium', 3: 'high', 4: 'on'}[value] | default('0') }}"
    preset_mode_state_topic: "zigbee2mqtt/Bedroom Fan"
    preset_mode_value_template: "{{ {'smart': 'smart'}[value_json.fan_mode] | default('normal') }}"
    preset_mode_command_topic: "zigbee2mqtt/Bedroom Fan/set/fan_mode"
    preset_modes:
      - "smart"
      - "normal"

Take a look here too, although I believe you need to add code for “defaults” in the template now otherwise you get log warnings. Down the road in some future release these warnings will be errors per documentation I remember reading.

What weird is the percentage field doesn’t send an MQTT message. It just reports null. And that link you provided was actually what I based my yaml off of. Wondering if it’s the version I’m on, since I have a few other things that are acting wonky (reloading things from the UI doesn’t take hold. Like scripts, automations, etc.). Do you have any information on that default requirement you mentioned? I didn’t see anything in my logs given me errors

It was in these older release notes. It doesn’t specifically say you need a default but your not supposed to have undefined variables. Defining a default makes sure nothing is "undefined "

I dont believe any template changes happened between 4.2021 and now, so I don’t think it’s your version.

Okay, just restarted and now I’m getting the following error

Template variable error: 'value_json' is undefined when rendering '{% if value_json.POWER1 is defined %} {% if value_json.POWER1 == OFF -%}off{%- elif value_json.POWER1 == ON -%}on{%- endif %} {% else %} {% if states.fan.office_fan.state == 'off' -%}off{%- elif states.fan.office_fan.state == 'on' -%}on{%- endif %} {% endif %}'

So looks I just need to figure out why that isn’t rendering

Your template looks like its missing some info, I don’t see a percentage value template and I don’t see the speed range specified. There are definitely people better at these then me, and its tough for me to figure out without having access to the raw MQTT data from the fan but maybe try something like this. The below is my best guess, but if it doesn’t work can you listen to the “stat/office_fan/speed” mqtt topic and post the output for off, low, medium, and high speeds?

 - platform: mqtt
   name: "Office Fan"
   command_topic: "cmnd/office_fan/POWER1"
   state_topic: "stat/office_fan"
   json_attributes_topic: "stat/office_fan"
   state_value_template: "{{ value_json.POWER1 | default('')}}"
   payload_off: 'OFF'
   payload_on: 'ON'
   payload_available: Online
   payload_not_available: Offline
   speed_range_min: 1
   speed_range_max: 3
   percentage_command_template: "{{ {0: '0', 1: '3,0', 2: '3,1', 3: '3,3'}[value] | default('0') }}"
   percentage_command_topic: "cmnd/office_fan/TuyaSend4"
   percentage_value_template: "{{ {'0': 0, '3,0': 1, '3,1': 2, '3,3': 3}[value] | default('0') }}"
   percentage_state_topic: "stat/office_fan/speed"

Ok, I combined our two yamls and it seems to be working now. But whats weird is that the speed and percentage remains null.

That’s good it made progress. Must still be an issue with the percentage value template. Does setting a percentage actually change the fan to the right speed, but it just doesn’t reflect the right values? You can post the output from the mqtt topic stat/office_fan/speed for all the speeds to try and troubleshoot. Do you also have the updated combined yaml you’re using now?

Here is my updated yaml. It does change the speeds, which is all I need it for, doesn’t even really matter to me that it isn’t updating per the slider. I’m able to adjust the speed via automation when I come into my office and that’s what I was after.

  - platform: mqtt
    name: "Office Fan"
    command_topic: "cmnd/office_fan/POWER1"
    state_topic: "stat/office_fan/POWER1"
    availability_topic: tele/office_fan/LWT
    payload_off: 'OFF'
    payload_on: 'ON'
    payload_available: Online
    payload_not_available: Offline
    json_attributes_topic: "stat/office_fan"
    state_value_template: "{{ value_json.POWER1 | default('')}}"
    speed_range_min: 1
    speed_range_max: 3
    percentage_command_template: "{{ {0: '0', 1: '3,0', 2: '3,1', 3: '3,3'}[value] | default('0') }}"
    percentage_command_topic: "cmnd/office_fan/TuyaSend4"
    percentage_value_template: "{{ {'0': 0, '3,0': 1, '3,1': 2, '3,3': 3}[value] | default('0') }}"
    percentage_state_topic: "stat/office_fan/speed"

You can try this if you want, if not it at least does what you want it to do now



  - platform: mqtt
    name: "Office Fan"
    command_topic: "cmnd/office_fan/POWER1"
    state_topic: "stat/office_fan/POWER1"
    availability_topic: tele/office_fan/LWT
    payload_off: 'OFF'
    payload_on: 'ON'
    payload_available: Online
    payload_not_available: Offline
    json_attributes_topic: "stat/office_fan"
    state_value_template: "{{ value_json.POWER1 | default('')}}"
    speed_range_min: 1
    speed_range_max: 3
    percentage_command_template: "{{ {0: '0', 1: '3,0', 2: '3,1', 3: '3,3'}[value] | default('0') }}"
    percentage_command_topic: "cmnd/office_fan/TuyaSend4"
    percentage_value_template: "{{ {'0': 0, '3,0': 1, '3,1': 2, '3,3': 3}[value_json.speed] | default('0') }}"
    percentage_state_topic: "stat/office_fan"