Zigbee Motion Switch • Project Linus • Bug & Enhancement Thread

@brassardv I did some testing in SmartThings to verify the values I entered in the settings section match what is sent to the switch. Also, I verified that I was able to reduce the reporting by changing the settings. I was able to confirm both in my environment with some caveats.

  • Min Reporting interval needs to be less than Max Reporting interval. Having them reversed causes the switch to indicate that “Reporting Configuration Failed”.
  • Also, setting them equal 36000 & 36000 is allowed by the firmware, but it causes unpredictable results. This caused many reports to be sent.

I did set them pretty high last night and observed that I did not get any reports for several hours even though I went in and out of the room. I’ll do some more digging, but can you try to change your settings to min interval = 1000, max interval =1800, min change = 100. I’ll check with the engineer to see what he things, but maybe setting them so high to 36000 caused some bug to appear that we haven’t seen before? Also, after changing the settings to my recommendation wait a bit for things to settle and if it still is misbehaving try to reboot the switch with the airgap.

@grady here are some comments in addition to what @Lance_Inovelli has mentioned. You have come across a difficult scenario to accurately detect. Smaller detection area, little to no movement, maybe covered by blankets. My recommendation would be to make sure the sensor sensitivity is set to high and fiddle with the Stay Life and Hold Time settings. You may actually want to setup an automation to change these settings during bedtime and return them during the day. Maybe start with:

(Stay Life):** 18000–36000 seconds (≈ 15–30 minutes)
(Detection Timeout / Hold Time):** 120–240 seconds

Stay Life helps when micro-movements (breathing for example) disappearing out of the detection area (instead of moving out). Hold Time helps more with regular movement.

1 Like

To begin, thank you for the follow-up. I hope you understand that my comments are not meant as criticism but rather as constructive feedback with the goal of improving the product, since this parameter does not prevent the system from functioning.

I tried your recommendations and restarted the device by shutting off the fuse, but I am still experiencing the same behavior. I have a new lead to investigate the bug: I noticed that every time the LUX value changes, it is logged in the history. It seems as though, regardless of the value I enter in the parameters, it is always treated as 0.

Most of the standard parameters work fine. However, when I tried modifying the mmWave parameters (103), no matter what value I entered, the radar zone stopped detecting anything except slightly on the far left side. To be clear, I changed the value from -600 to -500, then back to -600, and the radar no longer detected anything in the modified area. The only way I was able to correct the radar was by using parameter 117 to redefine the room size, which appears to reset parameter 103. Once that was done, the radar zone was restored.

My theory: could it be that any parameter I enter is being replaced by 0? And could this possibly be related to the fact that my iPhone is set to French?

@brassardv That theory does sound like a possibility and we can definitely look into it. I’d love to do some more digging to figure out what is going on. I’d like to confirm a couple of things and I will try to replicate what is going on for you. Can you post the parameters that you have set to non-default values? Screenshots might work as long as I can see the top of the list to the bottom since it will be in French.

Also, if you could record the logs while you are changing the settings in question and PM them to me. Here are some short instructions on how to do that:

SmartThings Edge Driver – Log Instructions

  1. Install the CLI (if you haven’t):
    GitHub - SmartThingsCommunity/smartthings-cli: Command-line Interface for the SmartThings APIs.
  2. Log in:
smartthings login
  1. Find your hub’s ID:
smartthings hubs
  1. Start live logging:
smartthings edge:drivers:logcat

(It will prompt you to choose the hub + driver.)

Lastly, there is an option in the driver to “reset mmwave module” which should return the module to its default settings. This can be a useful tool sometimes when having to start back from scratch. Keep in mind that SmartThings does not let us update what value is in the preference text box when you do this so it will still show the old values. Just keep that in mind and change them to what you would like them to be.

1 Like

Ok, I will proceed with the suggested test as soon as possible. In the meantime, if it helps, I noticed that when I add a decimal to the ‘Lux minimum change’ parameter, it alters the behavior. I have to proceed by trial and error, but the changes are not sent with every lux variation. For example, values like 1.05 or 1.01.

I did some more testing and believe I found an issue in the driver where the lux settings are getting overwritten by the defaults. I will fix that tomorrow.

I also verified all the distance parameters (101-106) just to make sure they were being sent correctly to the device and they looked good. I will still keep my eye out for anything that could be going wrong there.

2 Likes

This is excellent news — a very welcome fix for a device that I have considered perfect up until now.

I’ve updated the driver and your hub should get it in the next few hours. For reference, the date on it is 2025-12-12T21:53 if you want to verify. There was a function in the driver that was sending very low thresholds for illuminance configuration (the setting was every 10 seconds min interval and a change of .003460 lx min change). I am pretty confident that this is what was causing you problems. After you get the update, you will need to change at least one of the illuminance reporting configs in preferences. For example, change the 100 min change setting to 101. If you change more than one, keep in mind the 3 second “debounce” that might trigger if you try to change multiple settings quickly (mentioned above).

1 Like

I am on Hubitat and I have two sets of 301, 302, 303 parameters listed. See screenshot.

Thanks for reporting. I just fixed it and pushed the driver update to Github.

2 Likes

Should I be concerned with the WARN and the “Undefined Parameters” I get when I initialize the dimmer?

If i am not mistaken they are not defined in the driver and can be disregarded but @EricM_Inovelli will have to verify this for sure.

I got my Indiegogo switches in the mail yesterday! Congrats on getting there with this project, Erics and the Inovelli family/team! I know it’s been a HARD road, but you’ve made it and should be proud!

I just installed my first. I’m using Home Assistant. The default interface for the device is missing the majority of the configuration options (I can see them lurking in the direct zigbee params, but the UI is missing the ones my other Inovelli blues map automatically). Is there a way to get these to show up?

Screenshots attached.

Ah, saw this after I posted. Yeah, that’s frustrating. The quirks also don’t restore the extra entities, unfortunately, due to the changes they made in the quirkbuilder.

I fixed it (at least, for now). This quirk is needed, instead. If you want me to PR it somewhere, please let me know and I’d be happy to. Not exhaustively tested, but does seem to pass smoketests.

Edit: I should preface this with saying that it adds the right entities but not the ideal UI… each entity still needs you to view to update the setting instead of the proper adjustment UI directly on the device. Also, yup… this right here is just guided LLM code, but I don’t see anything fundamentally “wrong” with it and it functions as advertised; I’m an engineer too and I’m not thrilled with this being a way to solve problems either, but it lets me play with my new buttons on the wall until a proper quirk happens.

"""VZM32-SN MMwave Switch/Dimmer Module with explicit entity declarations."""
from zigpy.profiles import zha
from zigpy.quirks.v2 import QuirkBuilder
from zigpy.quirks.v2.homeassistant import EntityType

from zhacustomquirks import (
    INOVELLI_AUTOMATION_TRIGGERS,
    InovelliVZM32SNCluster,
    InovelliVZM32SNMMWaveCluster,
)

# Cluster IDs
VZM32SN_CLUSTER_ID = 0xFC31
MMWAVE_CLUSTER_ID = 0xFC32

(
    QuirkBuilder("Inovelli", "VZM32-SN")
    .replaces_endpoint(1, device_type=zha.DeviceType.DIMMABLE_LIGHT)
    .replace_cluster_occurrences(InovelliVZM32SNMMWaveCluster)
    .replace_cluster_occurrences(InovelliVZM32SNCluster)
    .device_automation_triggers(INOVELLI_AUTOMATION_TRIGGERS)
    # Number entities for VZM32SN cluster
    .number(
        "dimming_speed_up_local",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=126,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="dimming_speed_up_local",
        fallback_name="Local dimming up speed",
    )
    .number(
        "ramp_rate_off_to_on_local",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=127,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="ramp_rate_off_to_on_local",
        fallback_name="Local ramp rate off to on",
    )
    .number(
        "dimming_speed_down_local",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=127,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="dimming_speed_down_local",
        fallback_name="Local dimming down speed",
    )
    .number(
        "ramp_rate_on_to_off_local",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=127,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="ramp_rate_on_to_off_local",
        fallback_name="Local ramp rate on to off",
    )
    .number(
        "default_level_local",
        VZM32SN_CLUSTER_ID,
        min_value=1,
        max_value=254,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="default_level_local",
        fallback_name="Local default dimming level",
    )
    .number(
        "load_level_indicator_timeout",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=11,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="load_level_indicator_timeout",
        fallback_name="Load level indicator timeout",
    )
    .number(
        "button_delay",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=9,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="button_delay",
        fallback_name="Button delay",
    )
    .number(
        "double_tap_up_level",
        VZM32SN_CLUSTER_ID,
        min_value=2,
        max_value=254,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="double_tap_up_level",
        fallback_name="Double tap up level",
    )
    .number(
        "double_tap_down_level",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=254,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="double_tap_down_level",
        fallback_name="Double tap down level",
    )
    # LED color and intensity sliders
    .number(
        "led_color_when_on",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=255,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="led_color_when_on",
        fallback_name="Default all LED on color",
    )
    .number(
        "led_color_when_off",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=255,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="led_color_when_off",
        fallback_name="Default all LED off color",
    )
    .number(
        "led_intensity_when_on",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=100,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="led_intensity_when_on",
        fallback_name="Default all LED on intensity",
    )
    .number(
        "led_intensity_when_off",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=100,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="led_intensity_when_off",
        fallback_name="Default all LED off intensity",
    )
    # Auto-off timer
    .number(
        "auto_off_timer",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=32767,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="auto_off_timer",
        fallback_name="Automatic switch shutoff timer",
    )
    # Min/max levels
    .number(
        "minimum_level",
        VZM32SN_CLUSTER_ID,
        min_value=1,
        max_value=254,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="minimum_level",
        fallback_name="Minimum load dimming level",
    )
    .number(
        "maximum_level",
        VZM32SN_CLUSTER_ID,
        min_value=2,
        max_value=255,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="maximum_level",
        fallback_name="Maximum load dimming level",
    )
    # MMWave room size preset
    .number(
        "mmwave_room_size_preset",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=4,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_room_size_preset",
        fallback_name="MMWave room size preset",
    )
    .number(
        "light_on_presence_behavior",
        VZM32SN_CLUSTER_ID,
        min_value=0,
        max_value=2,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="light_on_presence_behavior",
        fallback_name="Light on presence behavior",
    )
    # Switch entities for VZM32SN cluster
    .switch(
        "invert_switch",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="invert_switch",
        fallback_name="Invert switch",
    )
    .switch(
        "smart_bulb_mode",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="smart_bulb_mode",
        fallback_name="Smart bulb mode",
    )
    .switch(
        "double_tap_up_enabled",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="double_tap_up_enabled",
        fallback_name="Double tap up enabled",
    )
    .switch(
        "double_tap_down_enabled",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="double_tap_down_enabled",
        fallback_name="Double tap down enabled",
    )
    .switch(
        "aux_switch_scenes",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="aux_switch_scenes",
        fallback_name="Aux switch scenes",
    )
    .switch(
        "binding_off_to_on_sync_level",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="binding_off_to_on_sync_level",
        fallback_name="Binding off to on sync level",
    )
    .switch(
        "local_protection",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="local_protection",
        fallback_name="Local protection",
    )
    .switch(
        "remote_protection",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="remote_protection",
        fallback_name="Remote protection",
    )
    .switch(
        "on_off_led_mode",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="on_off_led_mode",
        fallback_name="Only 1 LED mode",
    )
    .switch(
        "firmware_progress_led",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="firmware_progress_led",
        fallback_name="Firmware progress LED",
    )
    .switch(
        "relay_click_in_on_off_mode",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="relay_click_in_on_off_mode",
        fallback_name="Disable relay click in on off mode",
    )
    .switch(
        "disable_clear_notifications_double_tap",
        VZM32SN_CLUSTER_ID,
        off_value=0,
        on_value=1,
        entity_type=EntityType.CONFIG,
        translation_key="disable_clear_notifications_double_tap",
        fallback_name="Disable config 2x tap to clear notifications",
    )
    .switch(
        "output_mode",
        VZM32SN_CLUSTER_ID,
        off_value=0,  # Dimmer
        on_value=1,   # OnOff
        entity_type=EntityType.CONFIG,
        translation_key="output_mode",
        fallback_name="Output mode",
    )
    .switch(
        "increased_non_neutral_output",
        VZM32SN_CLUSTER_ID,
        off_value=0,  # Low
        on_value=1,   # High
        entity_type=EntityType.CONFIG,
        translation_key="increased_non_neutral_output",
        fallback_name="Non neutral output",
    )
    .switch(
        "led_scaling_mode",
        VZM32SN_CLUSTER_ID,
        off_value=0,  # VZM31SN
        on_value=1,   # LZW31SN
        entity_type=EntityType.CONFIG,
        translation_key="led_scaling_mode",
        fallback_name="Led scaling mode",
    )
    # MMWave cluster entities
    .number(
        "mmwave_z_min",
        MMWAVE_CLUSTER_ID,
        min_value=-32768,
        max_value=32767,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_z_min",
        fallback_name="MMWave Z min boundary",
    )
    .number(
        "mmwave_z_max",
        MMWAVE_CLUSTER_ID,
        min_value=-32768,
        max_value=32767,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_z_max",
        fallback_name="MMWave Z max boundary",
    )
    .number(
        "mmwave_x_min",
        MMWAVE_CLUSTER_ID,
        min_value=-32768,
        max_value=32767,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_x_min",
        fallback_name="MMWave X min boundary",
    )
    .number(
        "mmwave_x_max",
        MMWAVE_CLUSTER_ID,
        min_value=-32768,
        max_value=32767,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_x_max",
        fallback_name="MMWave X max boundary",
    )
    .number(
        "mmwave_y_min",
        MMWAVE_CLUSTER_ID,
        min_value=-32768,
        max_value=32767,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_y_min",
        fallback_name="MMWave Y min boundary",
    )
    .number(
        "mmwave_y_max",
        MMWAVE_CLUSTER_ID,
        min_value=-32768,
        max_value=32767,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_y_max",
        fallback_name="MMWave Y max boundary",
    )
    .number(
        "mmwave_detect_sensitivity",
        MMWAVE_CLUSTER_ID,
        min_value=0,
        max_value=100,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_detect_sensitivity",
        fallback_name="MMWave detect sensitivity",
    )
    .number(
        "mmwave_detect_trigger",
        MMWAVE_CLUSTER_ID,
        min_value=0,
        max_value=255,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_detect_trigger",
        fallback_name="MMWave detect trigger",
    )
    .number(
        "mmwave_hold_time",
        MMWAVE_CLUSTER_ID,
        min_value=0,
        max_value=4294967295,
        step=1,
        entity_type=EntityType.CONFIG,
        translation_key="mmwave_hold_time",
        fallback_name="MMWave hold time",
    )
    .add_to_registry()
)
```


1 Like

Preparing for Hubitat install. Manual (pg 46) recommends going to:

inov.li/vzm32snHEPrereqs

Resulting in “Short code does not appear to exist.”

I was able to navigate to the driver from the main page (inov.li/vzm32ns) but you may wish to edit your printed content.

I’m having issues with the detection area. I have not been able to test every detection parameter yet, but I do know that Parameter 106 (mmWave Depth Maximum (Far)) is not working as expected. I have it set for 550 cm, but it does not pick up until around 470 cm. If I set it to 600 cm, then it picks up around 550 cm.

Has anyone else seen this issue?

@fisheromega Have you set the near?

Looks like his Near is set to 0 (default).

@fisheromega These are just attributes that haven’t explicitly been assigned a name in the driver reporting function so it shouldn’t cause any issues. There is about a ±50cm variation possible on the settings due to noise, environmental effects, etc.

@justinlindh, I didn’t know you can set the entities in the quirk like that. I will try to test it out but thanks for doing that. I opened a PR with ZHA to get the entities added to the interface like the other Inovelli devices but just noticed there is an error on it that I need to look into: Changes to show entities for Inovelli VZM32-SN mmWave Presence Sensing Switch by InovelliUSA · Pull Request #597 · zigpy/zha

3 Likes

@hydro311 , thanks I did not catch that. I would try to reset the MMWave module, or clear the interference area, or reset the detection area on the commands tab. Give the module time to cool down and then without walking in front of it try setting the distances you want.

2 Likes