Homeseer HSM200 Zwave LED On/Off and Color Control

There are a few threads on this subject over the years, which I’ll link below for reference. It looks to me like many of the hooks to control this device are available but they don’t seem to automatically appear when the device is added to the network. The (crude) documentation that comes with the device indicates that COMMAND_CLASS_COLOR must be implemented to control the LED.

It looks like there are tests in HA to test this feature of OpenZwave: https://github.com/home-assistant/core/search?q=COMMAND_CLASS_COLOR&unscoped_q=COMMAND_CLASS_COLOR

However, grepping for COMMAND_CLASS_COLOR in /config for both OZW 1.4 and 1.6 comes up empty – I’m not sure if this is meaningful or not. When I attach the device, there is this block in the zwave configuration xml:

			<CommandClass id="51" name="COMMAND_CLASS_COLOR" version="1" request_flags="2" innif="true" colorchannels="28">
				<Instance index="1" />
				<Value type="string" genre="user" instance="1" index="0" label="Color" units="#RRGGBB" read_only="false" write_only="false" verify_changes="false" poll_intensity="0" min="0" max="0" value="#000000" />
				<Value type="list" genre="user" instance="1" index="1" label="Color Index" units="" read_only="false" write_only="false" verify_changes="false" poll_intensity="0" min="0" max="0" vindex="0" size="18">
					<Item label="Off" value="0" />
					<Item label="Cool White" value="1" />
					<Item label="Warm White" value="2" />
					<Item label="Red" value="3" />
					<Item label="Lime" value="4" />
					<Item label="Blue" value="5" />
					<Item label="Yellow" value="6" />
					<Item label="Cyan" value="7" />
					<Item label="Magenta" value="8" />
					<Item label="Silver" value="9" />
					<Item label="Gray" value="10" />
					<Item label="Maroon" value="11" />
					<Item label="Olive" value="12" />
					<Item label="Green" value="13" />
					<Item label="Purple" value="14" />
					<Item label="Teal" value="15" />
					<Item label="Navy" value="16" />
					<Item label="Custom" value="17" />
				</Value>
				<Value type="int" genre="system" instance="1" index="2" label="Color Channels" units="" read_only="false" write_only="false" verify_changes="false" poll_intensity="0" min="-2147483648" max="2147483647" value="28" />
			</CommandClass>

It has the same command class ID as the HA tests but… where does this information come from? It seems like the color control information is there but nothing from HA sees this and creates an entity to set/control these features (like light.hms200_entity). Where does the information to populate the xml come from – is this extracted fromt he device itself upon attach? Also, is there any example from which I can create the necessary modifications to HA to cause a light (or switch, whatever) entity to be created when this device is attached?

Also, it appears something may not be complete in the way the device is pulled in: here are the first few lines from the zwave config xml:

	<Node id="28" name="EZM" location="" basic="4" generic="7" specific="1" roletype="5" devicetype="3079" nodetype="0" type="Notification Sensor" listening="true" frequentListening="false" beaming="true" routing="true" max_baud_rate="40000" version="4" secured="true" query_stage="Complete">
		<Manufacturer id="c" name="HomeSeer Technologies">
			<Product type="4" id="1" name="Unknown: type=0004, id=0001" />
		</Manufacturer>

It’s the Product type = 4, id=1, name=Unknown line that appears suspect. Thanks for any help. This is a pretty cool device that I figured I would experiment with, and having the LED work will be a big plus (somewhat justifying the price tag). Here are a few past posts that have been left hanging unresolved:

For more details on the solution see this post: Homeseer HSM200 Zwave LED On/Off and Color Control - #17 by inkblotadmirer

The following excerpt is from the get_device function in zwave/light.py. It looks like it’s handling “COMMAND_CLASS_SWITCH_COLOR” but doesn’t handle COMMAND_CLASS_COLOR – thus, a light entity will get created if the config xml includes COMMAND_CLASS_SWITCH_COLOR but not for one that contains COMMAND_CLASS_COLOR? Does anyone know if this is the spot at which handling should be added? If so, I can try to figure out how to have a light added with on/off state and a color attribute.

OZW’s COMMAND_CLASS_COLOR is the same thing as HA zwave’s const.COMMAND_CLASS_SWITCH_COLOR.

HA will only create light entities for devices that look like lights. The device classes need to match what HA thinks is a light, plus the node must support COMMAND_CLASS_SWITCH_MULTILEVEL. After that, COLOR is an optional value.

Since the device is reporting generic="7" specific="1", it doesn’t match the schema for a light. In HA those would be detected as GENERIC_TYPE_SENSOR_NOTIFICATION and SPECIFIC_TYPE_NOTIFICATION_SENSOR respectively. The node still needs to report MULTILEVEL_SWITCH command though, as HA doesn’t appear to support color binary switches.

The OpenZWave Beta would have the same problem, however you’d be able to control the device independently using MQTT, bypassing HA.

So it seems it may not be as simple as I initially thought to get HA to create a light entity for this device. It does support MULTILEVEL_SWITCH:

			<CommandClass id="38" name="COMMAND_CLASS_SWITCH_MULTILEVEL" version="2" innif="true">
				<Instance index="1" />
				<Value type="byte" genre="user" instance="1" index="0" label="Level" units="" read_only="false" write_only="false" verify_changes="false" poll_intensity="0" min="0" max="255" value="0" />
				<Value type="button" genre="user" instance="1" index="1" label="Bright" units="" read_only="false" write_only="true" verify_changes="false" poll_intensity="0" min="0" max="0" />
				<Value type="button" genre="user" instance="1" index="2" label="Dim" units="" read_only="false" write_only="true" verify_changes="false" poll_intensity="0" min="0" max="0" />
				<Value type="bool" genre="system" instance="1" index="3" label="Ignore Start Level" units="" read_only="false" write_only="false" verify_changes="false" poll_intensity="0" min="0" max="0" value="True" />
				<Value type="byte" genre="system" instance="1" index="4" label="Start Level" units="" read_only="false" write_only="false" verify_changes="false" poll_intensity="0" min="0" max="255" value="0" />
			</CommandClass>

I don’t want just a light, I want the other entities plus a light. Controlling from MQTT with the OZW beta is an acceptable option, however, if there’s not a reasonably simple path to get a light entity created for this device. Thanks for the info.

Well you have the best case scenario. All you should have to do is modify the discovery schema to allow “notification sensor” device types to have lights.

const.DISC_COMPONENT: "light",
        const.DISC_GENERIC_DEVICE_CLASS: [
            const.GENERIC_TYPE_SWITCH_MULTILEVEL,
            const.GENERIC_TYPE_SWITCH_REMOTE,
            const.GENERIC_TYPE_SENSOR_NOTIFICATION,
        ],
        const.DISC_SPECIFIC_DEVICE_CLASS: [
            const.SPECIFIC_TYPE_POWER_SWITCH_MULTILEVEL,
            const.SPECIFIC_TYPE_SCENE_SWITCH_MULTILEVEL,
            const.SPECIFIC_TYPE_NOT_USED,
            const.SPECIFIC_TYPE_NOTIFICATION_SENSOR,
        ],

You should then get a light entity with a color wheel to set the RGB values.

You can download the existing zwave component and install it as a custom component (copy all files to <config_dir>/custom_components/zwave.

Otherwise, you could submit an issue to HA. It’s unlikely anyone will update the zwave integration for you. Probably someone would update the ozw integration but you’d need to submit an MQTT dump.

That’s better than I expected. I have no issues with generating and maintaining a custom component for a deprecated (or at least, on its way out) feature. If it works, what are the odds of a pull request being accepted? I’d be willing to go through the hassle if ozw is far enough out that someone else might benefit.

I’ll update once I get a chance to test. I’m assuming I need to remove the node and reattach it, not just restart?

I think they might accept a PR, but I can’t say for sure.

You shouldn’t need to remove the node, just restart HA after the component is added.

I did this, restarted HA, and indeed a light entity is created. There may be more modifications required, no matter what I put into the light.turn_on service data it seems to send color “#ff00000000” when the device wants #ff0000 or “Red” for example. Here is what is sent (doesn’t actually turn the light on):

2020-09-01 11:35:17.102 Info, Node028, Value::Set - COMMAND_CLASS_COLOR - Color - 0 - 1 - #ff00000000
2020-09-01 11:35:17.103 Info, Node028, Color::SetValue - Setting Color value
2020-09-01 11:35:17.103 Detail, Node028, Queuing (Send) ColorCmd_Set (Node=28): 0x01, 0x14, 0x00, 0x13, 0x1c, 0x0d, 0x33, 0x05, 0x05, 0x02, 0xff, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0xf8, 0xfc
2020-09-01 11:35:17.103 Detail, Node028, Queuing (Send) ColorCmd_Get (Node=28): 0x01, 0x0a, 0x00, 0x13, 0x1c, 0x03, 0x33, 0x03, 0x02, 0x25, 0xf9, 0x17
2020-09-01 11:35:17.104 Detail, Node028, Queuing (Send) ColorCmd_Get (Node=28): 0x01, 0x0a, 0x00, 0x13, 0x1c, 0x03, 0x33, 0x03, 0x03, 0x25, 0xfa, 0x15
2020-09-01 11:35:17.104 Detail, Node028, Queuing (Send) ColorCmd_Get (Node=28): 0x01, 0x0a, 0x00, 0x13, 0x1c, 0x03, 0x33, 0x03, 0x04, 0x25, 0xfb, 0x13

which is followed with a series of Gets, one of which is:

2020-09-01 11:35:17.269 Info, Node028, Response RTT 41 Average Response RTT 40
2020-09-01 11:35:17.269 Info, Node028, Received a updated Color from Device: #000000
2020-09-01 11:35:17.269 Detail, Node028, Refreshed Value: old value=#000000, new value=#000000, type=string
2020-09-01 11:35:17.269 Detail, Node028, Changes to this value are not verified
2020-09-01 11:35:17.269 Detail, Node028, Refreshed Value: old value=0, new value=0, type=list
2020-09-01 11:35:17.269 Detail, Node028, Changes to this value are not verified
2020-09-01 11:35:17.269 Detail, Node028,   Expected reply and command class was received
2020-09-01 11:35:17.269 Detail, Node028,   Message transaction complete

From the first link in my original post, there is a sequence that works (that poster was using the OpenZwave Control Panel to test):

2018-05-30 21:59:16.681 Info, Node041, Value::Set - COMMAND_CLASS_COLOR -  - 1 - 1 - Red
2018-05-30 21:59:16.682 Info, Node041, Color::SetValue - Setting Color Index Value (Fake)
2018-05-30 21:59:16.682 Detail, Node041, Queuing (Send) ColorCmd_Set (Node=41): 0x01, 0x10, 0x00, 0x13, 0x29, 0x09, 0x33, 0x05, 0x03, 0x02, 0xff, 0x03, 0x00, 0x04, 0x00, 0x25, 0xaf, 0x99
2018-05-30 21:59:16.683 Detail, Node041, Queuing (Send) ColorCmd_Get (Node=41): 0x01, 0x0a, 0x00, 0x13, 0x29, 0x03, 0x33, 0x03, 0x02, 0x25, 0xb0, 0x6b
2018-05-30 21:59:16.683 Detail, Node041, Queuing (Send) ColorCmd_Get (Node=41): 0x01, 0x0a, 0x00, 0x13, 0x29, 0x03, 0x33, 0x03, 0x03, 0x25, 0xb1, 0x6b
2018-05-30 21:59:16.683 Detail, Node041, Queuing (Send) ColorCmd_Get (Node=41): 0x01, 0x0a, 0x00, 0x13, 0x29, 0x03, 0x33, 0x03, 0x04, 0x25, 0xb2, 0x6f

<snip>

2018-05-30 21:59:16.824 Info, Node041, Response RTT 37 Average Response RTT 36
2018-05-30 21:59:16.824 Info, Node041, Received a updated Color from Device: #FF0000
2018-05-30 21:59:16.824 Detail, Node041, Refreshed Value: old value=#008000, new value=#FF0000, type=string
2018-05-30 21:59:16.824 Detail, Node041, Changes to this value are not verified
2018-05-30 21:59:16.824 Detail, Node041, Refreshed Value: old value=13, new value=3, type=list
2018-05-30 21:59:16.824 Detail, Node041, Changes to this value are not verified
2018-05-30 21:59:16.824 Detail, Node041,   Expected reply and command class was received
2018-05-30 21:59:16.824 Detail, Node041,   Message transaction complete

I perused the light.py in the zwave component and it’s always (seemingly) sending a variable called ‘rgbw’ which must have information other than just the RGB light color. Maybe need to modify this file as well with a quirk for this device?

What is the value of the light entity’s supported_features attribute?

I think the zwave integration code is pretty broken. The ozw version of the code has been updated quite a bit to properly support RGB. I think your problem is related to this section of code:

It correctly sets the RGB values. It then checks if a white value is supported, which in your case is not true, but the last else is incorrectly appending the white values to the color string anyways.

OpenZWave doesn’t really care what values you set, it just passes them to the device. It’s looking like the device ignores the command if unexpected color values are set. I suspect if you delete the else block it will work properly, at least in your case.

Supported features is reported as 49, I think the following is the decoder ring:

SUPPORT_BRIGHTNESS = 1
SUPPORT_COLOR_TEMP = 2
SUPPORT_EFFECT = 4
SUPPORT_FLASH = 8
SUPPORT_COLOR = 16
SUPPORT_TRANSITION = 32
SUPPORT_WHITE_VALUE = 128

I played with that section including hardcoding rgbw to “#ff0000” and somewhere the additional 4 0s are still being appended before sent to the the device. I wonder if it has to do with “SUPPORT_WHITE_VALUE” being set – there is a comment in the light.py file that “openzwave appends white channels that are present”. I don’t see where these bits are set, it doesn’t look like in discovery.

It’s not set, you just said so yourself. 49 is BRIGHTNESS, COLOR and TRANSITION, which matches your xml cache file.

It looks like there is yet again another bug with this code. If you don’t specify a white value, self._white is set to 0 (line 381). So it’s actually line 390 where the extra values are set, because 0 is not None.

Also, don’t forget to restart HA if you change any of the component files.

Yeah, major brain slippage LOL. I have been restarting HA after making changes, I still think something else is modifying the result. I have the following as the last few lines in the file:

        rgbw = "$ff0000"
        self.values.color.data = rgbw

        super().turn_on(**kwargs)

I explicitly set the variable to what I want it to be and the additional zeroes still get sent. The entity also reports rgb_color of 255,255,255 so something is broken in the way the status is being read back as well.

I must have been pretty tired or distracted last night. I was making changes to light.py in the git repo, not in my custom_component folder. Commenting out the suspect if/else section (Homeseer HSM200 Zwave LED On/Off and Color Control) along with the discovery changes (Homeseer HSM200 Zwave LED On/Off and Color Control) allow the light to be controlled. I’m using the light.turn_on service call with this data:

entity_id: light.upstairs_motion_led
rgb_color: [255,0,0]
brightness: 255

Also working instead of rgb_color:

color_name: Red

The list of colors is in the zwave config xml (or in my original post in this thread).

For some reason the first command issued throws an error, the second works and this pattern continues so I still need to look into that. I also plan to come up with an acceptable pull request to fix this in general, and reference that with a feature request to the new ozw integration to have it fixed there as well.

Thanks @freshcoast for the help! I’m marking one of your posts as the solution and I’ll edit my original post to point to this one as a summary.

1 Like

@inkblotadmirer Did you have to do anything with the existing Home Assistant Zwave integration before or after you added the entire zwave files with the edits suggested into the custom component folder? Can I have a custom zwave component running simultaneously with the preloaded config options for zwave? I’m excited to give this solution a try as I just bought 3 of these sensors, but I’m nervous about messing up the rest of my zwave network of 25 devices.

I cloned the home assistant core repo, and created my own custom branch (as a separate user, in a non-HA location). Here is my git diff:

diff --git a/homeassistant/components/zwave/discovery_schemas.py b/homeassistant/components/zwave/discovery_schemas.py
index f8674a48a3..aa0874fd57 100644
--- a/homeassistant/components/zwave/discovery_schemas.py
+++ b/homeassistant/components/zwave/discovery_schemas.py
@@ -295,11 +295,13 @@ DISCOVERY_SCHEMAS = [
         const.DISC_GENERIC_DEVICE_CLASS: [
             const.GENERIC_TYPE_SWITCH_MULTILEVEL,
             const.GENERIC_TYPE_SWITCH_REMOTE,
+            const.GENERIC_TYPE_SENSOR_NOTIFICATION,
         ],
         const.DISC_SPECIFIC_DEVICE_CLASS: [
             const.SPECIFIC_TYPE_POWER_SWITCH_MULTILEVEL,
             const.SPECIFIC_TYPE_SCENE_SWITCH_MULTILEVEL,
             const.SPECIFIC_TYPE_NOT_USED,
+            const.SPECIFIC_TYPE_NOTIFICATION_SENSOR,
         ],
         const.DISC_VALUES: dict(
             DEFAULT_VALUES_SCHEMA,
diff --git a/homeassistant/components/zwave/light.py b/homeassistant/components/zwave/light.py
index 244b4a557e..d6e777d7a8 100644
--- a/homeassistant/components/zwave/light.py
+++ b/homeassistant/components/zwave/light.py
@@ -386,10 +394,11 @@ class ZwaveColorLight(ZwaveDimmer):
             rgbw = "#"
             for colorval in color_util.color_hs_to_RGB(*self._hs):
                 rgbw += format(colorval, "02x")
-            if self._white is not None:
-                rgbw += format(self._white, "02x") + "00"
-            else:
-                rgbw += "0000"
+            if self._supported_features & SUPPORT_WHITE_VALUE:
+                if self._white is not None:
+                    rgbw += format(self._white, "02x") + "00"
+                else:
+                    rgbw += "0000"

         if rgbw and self.values.color:
             self.values.color.data = rgbw

This entire zwave folder then gets copied to custom_components in your homeassistant/.homeassistant location. The changes are fairly small, it’s fine to just copy the zwave folder into the custom_components location and manually add/change the affected lines.

The changes made may affect other lights that fall into the “self._white is not None” categories or the added logic. This is the only light I have with a color LED, and I made no effort to truly understand the logic here. That, and the fact that this zwave implementation is on its way to being deprecated, is the reason for not submitting a pull request to get it fixed officially. Good luck!

EDIT: I inadvertantly clipped the top portion of the diff indicating the first file with changes. Fixed.

I should also add (since you asked) this shouldn’t affect any other zwave components (other than mentioned in my prior post, falling into the “self._white is not None” category.)

I took a look at my automations and it reminded me that I still did have some trouble getting these working correctly. I don’t recall the exact issue but my automations are calling the turn_on and turn_off routines twice. If I remember the light would only take one change at a time (like, not changing color and state with one command) but I don’t recall the specifics. In any case, here’s an example of the automation I’m using (I haven’t taken advantage of the variables and native types yet):

            sequence:
              repeat:
                count: 2
                sequence:
                  - service: light.turn_on
                    data_template:
                      entity_id: light.upstairs_motion_led
                      rgb_color: [255,0,255]
                      brightness: 255
                  - delay:
                      milliseconds: 250

Even though you can set arbitrary RGB values only one of the 16 supported colors will show. You can modify the automation to set these colors instead of the RGB value.

					<Item label="Off" value="0" />
					<Item label="Cool White" value="1" />
					<Item label="Warm White" value="2" />
					<Item label="Red" value="3" />
					<Item label="Lime" value="4" />
					<Item label="Blue" value="5" />
					<Item label="Yellow" value="6" />
					<Item label="Cyan" value="7" />
					<Item label="Magenta" value="8" />
					<Item label="Silver" value="9" />
					<Item label="Gray" value="10" />
					<Item label="Maroon" value="11" />
					<Item label="Olive" value="12" />
					<Item label="Green" value="13" />
					<Item label="Purple" value="14" />
					<Item label="Teal" value="15" />
					<Item label="Navy" value="16" />
					<Item label="Custom" value="17" />