How to make VZM30-SN report as a fan (or at least a switch) to Home Assistant from Zigbee2MQTT?

I just installed a VZM30-SN that is controlling a bathroom exhaust fan. It works, and it seems to fix my issue with using a VZM35-SN on that same fan. The issue is that this device is reporting itself as a light to Home Assistant via MQTT discovery. That’s not right, because it’s not controlling a light. As such, as bunch of configuration and behavior isn’t right for this device (there’s no brightness on the fan, for example).

If the VZM30-SN were reporting as a switch, I could use the Change device type of a switch helper to change it to a fan. I’ve done that with a handful of Lutron Casétas that report as switches and control fans. That would work fine, but apparently the Change device type of a switch helper only works with actual switches.

I saw the Blue Series On/Off - Change Device Type in Home Assistant article. And this works to add an additional fan into Home Assistant, but the original light entity has to still exist as long as I want this additional fan to work. That causes issues with other integrations that work off of the device type (like Magic Areas thinks a light is on because I turned the fan on and it templated the light on). If I disable the light entity, the fan entity stops working (because it’s templated off of the light). If I make the light entity not visible, it doesn’t show up in some places, but still causes issues with other integrations, like mentioned above.

I could probably keep going and puth more workarounds in place, but the root cause seems to be that the device is reporting itself as a light in Zigbee2MQTT. i saw this Exposing switch as a light section in Zigbee2MQTT, but I couldn’t figure out how to get it to expose the light as a fan/switch. Is there a way to change this device to reports as a fan (or at least a switch, so I can use the Change device type of a switch helper)? Or am I just stuck with this behavior and need to look into even more workarounds to make it work properly?

In Home Assistant:

  1. Settings>Devices & services
  2. Navigate to Helpers tab
  3. Click on +Create helper button
  4. Search for or scroll and select Template
  5. Choose to create a Fan Template
  6. Choose a name for how your new “fan” switch will appear
  7. In the “Actions on tun on”, choose the “Turn on light” action with the target of the VZM30-SN
  8. In the “Actions on tun off”, choose the “Turn off light” action with the target of the VZM30-SN
  9. Click the Submit button.
  10. Go into the properties of the VZM30-SN and disable the “Visible” property
  11. Optionally, choose the area for the switch and add a label if desired.

EDIT: I have my bathroom exhaust fan on a VZM30, set as a fan with a helper using the above steps, and I have then paired it with an external Humidity sensor and have them both connected in a Hygrostat helper, so the “fan” is controlled by the humidity sensor.

I appreciate you taking the time to write this out. But that’s effectively the Blue Series On/Off - Change Device Type in Home Assistant article. And that still has issues, since it’s adding an additional fan, not replacing the light with a fan:

That’s the only way to have it show up as a fan (that I know of)… set up the helper and hide the original switch.

Okay, I managed to kind of figure it out. The documentation for Zigbee2MQTT could really use some actual explanation about what the fields of these objects are, but near as I can tell, with the example as given:

devices:
  "0x12345678":
    friendly_name: my_switch
    homeassistant:
      switch:
        type: light
        object_id: light
      light:
        name: null
        value_template: null
        state_value_template: "{{ value_json.state }}"
  • The switch field is the one of the Zigbee Endpoints of the device.
  • The switch.type is the type of device you want to expose the Zigbee Endpoint as.
  • The switch.object_id is the field you want to define to override some configuration.
  • The light is referenced by the switch.object_id.
  • The light is what gets used as the MQTT path. In this example it’d be something like homeassistant/light/0x12345678/light/config.
  • The fields inside of the light object are used as the Home Assistant MQTT discovery payload.
  • No clue why they set the name to null or the value_template to null.

So it seems to be mapping from the switch Endpoint to a light Endpoint. It’s coincidence that they decided to call the light’s object_id they wanted to expose light. It’s not that the light field they defined has an actual meaning in the type of entity exposed over MQTT. So the way this works seems to be that you have to define an object that has the same name as one of the Zigbee Endpoints, and its type is what type you’re exposing that Endpoint to be in Home Assistant. So if you want a light to show up as a fan, you would have a light object with a type field that has the value fan. I assume if you wanted a switch to show up as a cover, you would have a switch object with a type field that has the value cover. It’s confusing without any documentation, but I can understand how that schema came about.

Regardless, after a lot of struggling, the configuration for the fan looks like:

devices:
  "0x12345678":
    friendly_name: Bathroom Exhaust Fan Switch
    homeassistant:
      fan:
        state_value_template: "{{ value_json.state }}"
      light:
        object_id: fan
        type: fan

This generates the correct Home Assistant MQTT discovery configuration of homeassistant/fan/0x12345678/fan/config, and it shows up in Home Assistant as a fan, not a light! So everything works like expected!

For anyone still a little confused, I’m doing a similar thing and using the object_id that happens to be the same as the type, but that’s not necessary. It would also work as:

devices:
  "0x12345678":
    friendly_name: Bathroom Exhaust Fan Switch
    homeassistant:
      this_is_a_fan:
        state_value_template: "{{ value_json.state }}"
      light:
        object_id: this_is_a_fan
        type: fan

The only difference is what the MQTT discovery path would look like. It would look like homeassistant/fan/0x12345678/this_is_a_fan/config,

Hopefully this helps someone else in the future!

@EricM_Inovelli Sorry for the ping, but I wasn’t sure who to ask this follow-up to. It looks like you authored the Blue Series On/Off - Change Device Type in Home Assistant article. Any thoughts on adding either another section or another article about how to change the device type via Zigbee2MQTT instead of via Home Assistant?

The motivation is explained in the first post, but it’s kind of long, so the tl;dr; is that things work better in both Home Assistant proper and arbitrary Home Assistant integrations if the entity is replaced with a different type rather than adding a new different type of entity.

@jones3.hardy we could add an additional help article. Just to clarify, this is configuration that you add to your zigbee2mqtt configuration.yaml file that makes it so that the device is presented as a fan (through the home assistant zigbee2mqtt discovery process)? Essentially, if I put this in my configuration file with my ieee and restart zigbee2mqtt it will come into HA as a fan?

devices:
  "0x12345678":
    friendly_name: Bathroom Exhaust Fan Switch
    homeassistant:
      fan:
        state_value_template: "{{ value_json.state }}"
      light:
        object_id: fan
        type: fan

Okay, cool!

Yes, to both questions. That’s how it’s working for me, and I believe the minimal change necessary for it to work.