mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add zwave_js light support for HSM-200 V1 (#67089)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
9906717e33
commit
9fe61f9e7f
@ -16,6 +16,7 @@ from zwave_js_server.const import (
|
||||
from zwave_js_server.const.command_class.barrier_operator import (
|
||||
SIGNALING_STATE_PROPERTY,
|
||||
)
|
||||
from zwave_js_server.const.command_class.color_switch import CURRENT_COLOR_PROPERTY
|
||||
from zwave_js_server.const.command_class.humidity_control import (
|
||||
HUMIDITY_CONTROL_MODE_PROPERTY,
|
||||
)
|
||||
@ -125,9 +126,9 @@ class ZWaveValueDiscoverySchema(DataclassMustHaveAtLeastOne):
|
||||
# [optional] the value's property name must match ANY of these values
|
||||
property_name: set[str] | None = None
|
||||
# [optional] the value's property key must match ANY of these values
|
||||
property_key: set[str | int] | None = None
|
||||
property_key: set[str | int | None] | None = None
|
||||
# [optional] the value's property key name must match ANY of these values
|
||||
property_key_name: set[str] | None = None
|
||||
property_key_name: set[str | None] | None = None
|
||||
# [optional] the value's metadata_type must match ANY of these values
|
||||
type: set[str] | None = None
|
||||
|
||||
@ -180,8 +181,8 @@ class ZWaveDiscoverySchema:
|
||||
def get_config_parameter_discovery_schema(
|
||||
property_: set[str | int] | None = None,
|
||||
property_name: set[str] | None = None,
|
||||
property_key: set[str | int] | None = None,
|
||||
property_key_name: set[str] | None = None,
|
||||
property_key: set[str | int | None] | None = None,
|
||||
property_key_name: set[str | None] | None = None,
|
||||
**kwargs: Any,
|
||||
) -> ZWaveDiscoverySchema:
|
||||
"""
|
||||
@ -462,6 +463,20 @@ DISCOVERY_SCHEMAS = [
|
||||
},
|
||||
),
|
||||
),
|
||||
# HomeSeer HSM-200 v1
|
||||
ZWaveDiscoverySchema(
|
||||
platform="light",
|
||||
hint="black_is_off",
|
||||
manufacturer_id={0x001E},
|
||||
product_id={0x0001},
|
||||
product_type={0x0004},
|
||||
primary_value=ZWaveValueDiscoverySchema(
|
||||
command_class={CommandClass.SWITCH_COLOR},
|
||||
property={CURRENT_COLOR_PROPERTY},
|
||||
property_key={None},
|
||||
),
|
||||
absent_values=[SWITCH_MULTILEVEL_CURRENT_VALUE_SCHEMA],
|
||||
),
|
||||
# ====== START OF CONFIG PARAMETER SPECIFIC MAPPING SCHEMAS =======
|
||||
# Door lock mode config parameter. Functionality equivalent to Notification CC
|
||||
# list sensors.
|
||||
|
@ -74,8 +74,10 @@ async def async_setup_entry(
|
||||
def async_add_light(info: ZwaveDiscoveryInfo) -> None:
|
||||
"""Add Z-Wave Light."""
|
||||
|
||||
light = ZwaveLight(config_entry, client, info)
|
||||
async_add_entities([light])
|
||||
if info.platform_hint == "black_is_off":
|
||||
async_add_entities([ZwaveBlackIsOffLight(config_entry, client, info)])
|
||||
else:
|
||||
async_add_entities([ZwaveLight(config_entry, client, info)])
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(
|
||||
@ -127,7 +129,9 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
||||
|
||||
# get additional (optional) values and set features
|
||||
self._target_brightness = self.get_zwave_value(
|
||||
TARGET_VALUE_PROPERTY, add_to_watched_value_ids=False
|
||||
TARGET_VALUE_PROPERTY,
|
||||
CommandClass.SWITCH_MULTILEVEL,
|
||||
add_to_watched_value_ids=False,
|
||||
)
|
||||
self._target_color = self.get_zwave_value(
|
||||
TARGET_COLOR_PROPERTY,
|
||||
@ -167,14 +171,14 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
||||
self._calculate_color_values()
|
||||
|
||||
@property
|
||||
def brightness(self) -> int:
|
||||
def brightness(self) -> int | None:
|
||||
"""Return the brightness of this light between 0..255.
|
||||
|
||||
Z-Wave multilevel switches use a range of [0, 99] to control brightness.
|
||||
"""
|
||||
if self.info.primary_value.value is not None:
|
||||
return round((self.info.primary_value.value / 99) * 255)
|
||||
return 0
|
||||
if self.info.primary_value.value is None:
|
||||
return None
|
||||
return round((self.info.primary_value.value / 99) * 255)
|
||||
|
||||
@property
|
||||
def color_mode(self) -> str | None:
|
||||
@ -182,9 +186,12 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
||||
return self._color_mode
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if device is on (brightness above 0)."""
|
||||
return self.brightness > 0
|
||||
brightness = self.brightness
|
||||
if brightness is None:
|
||||
return None
|
||||
return brightness > 0
|
||||
|
||||
@property
|
||||
def hs_color(self) -> tuple[float, float] | None:
|
||||
@ -318,6 +325,9 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
||||
self, brightness: int | None, transition: float | None = None
|
||||
) -> None:
|
||||
"""Set new brightness to light."""
|
||||
# If we have no target brightness value, there is nothing to do
|
||||
if not self._target_brightness:
|
||||
return
|
||||
if brightness is None:
|
||||
# Level 255 means to set it to previous value.
|
||||
zwave_brightness = 255
|
||||
@ -426,3 +436,77 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity):
|
||||
self._rgbw_color = (red, green, blue, white)
|
||||
# Light supports rgbw, set color mode to rgbw
|
||||
self._color_mode = COLOR_MODE_RGBW
|
||||
|
||||
|
||||
class ZwaveBlackIsOffLight(ZwaveLight):
|
||||
"""
|
||||
Representation of a Z-Wave light where setting the color to black turns it off.
|
||||
|
||||
Currently only supports lights with RGB, no color temperature, and no white channels.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, config_entry: ConfigEntry, client: ZwaveClient, info: ZwaveDiscoveryInfo
|
||||
) -> None:
|
||||
"""Initialize the light."""
|
||||
super().__init__(config_entry, client, info)
|
||||
|
||||
self._last_color: dict[str, int] | None = None
|
||||
self._supported_color_modes.discard(COLOR_MODE_BRIGHTNESS)
|
||||
|
||||
@property
|
||||
def brightness(self) -> int:
|
||||
"""Return the brightness of this light between 0..255."""
|
||||
return 255
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if device is on (brightness above 0)."""
|
||||
if self.info.primary_value.value is None:
|
||||
return None
|
||||
return any(value != 0 for value in self.info.primary_value.value.values())
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the device on."""
|
||||
await super().async_turn_on(**kwargs)
|
||||
|
||||
if (
|
||||
kwargs.get(ATTR_RGBW_COLOR) is not None
|
||||
or kwargs.get(ATTR_COLOR_TEMP) is not None
|
||||
or kwargs.get(ATTR_HS_COLOR) is not None
|
||||
):
|
||||
return
|
||||
|
||||
transition = kwargs.get(ATTR_TRANSITION)
|
||||
# turn on light to last color if known, otherwise set to white
|
||||
if self._last_color is not None:
|
||||
await self._async_set_colors(
|
||||
{
|
||||
ColorComponent.RED: self._last_color["red"],
|
||||
ColorComponent.GREEN: self._last_color["green"],
|
||||
ColorComponent.BLUE: self._last_color["blue"],
|
||||
},
|
||||
transition,
|
||||
)
|
||||
else:
|
||||
await self._async_set_colors(
|
||||
{
|
||||
ColorComponent.RED: 255,
|
||||
ColorComponent.GREEN: 255,
|
||||
ColorComponent.BLUE: 255,
|
||||
},
|
||||
transition,
|
||||
)
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the light off."""
|
||||
self._last_color = self.info.primary_value.value
|
||||
await self._async_set_colors(
|
||||
{
|
||||
ColorComponent.RED: 0,
|
||||
ColorComponent.GREEN: 0,
|
||||
ColorComponent.BLUE: 0,
|
||||
},
|
||||
kwargs.get(ATTR_TRANSITION),
|
||||
)
|
||||
await self._async_set_brightness(0, kwargs.get(ATTR_TRANSITION))
|
||||
|
@ -497,6 +497,12 @@ def zp3111_state_fixture():
|
||||
return json.loads(load_fixture("zwave_js/zp3111-5_state.json"))
|
||||
|
||||
|
||||
@pytest.fixture(name="express_controls_ezmultipli_state", scope="session")
|
||||
def light_express_controls_ezmultipli_state_fixture():
|
||||
"""Load the Express Controls EZMultiPli node state fixture data."""
|
||||
return json.loads(load_fixture("zwave_js/express_controls_ezmultipli_state.json"))
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def mock_client_fixture(controller_state, version_state, log_config_state):
|
||||
"""Mock a client."""
|
||||
@ -981,3 +987,11 @@ def zp3111_fixture(client, zp3111_state):
|
||||
node = Node(client, copy.deepcopy(zp3111_state))
|
||||
client.driver.controller.nodes[node.node_id] = node
|
||||
return node
|
||||
|
||||
|
||||
@pytest.fixture(name="express_controls_ezmultipli")
|
||||
def express_controls_ezmultipli_fixture(client, express_controls_ezmultipli_state):
|
||||
"""Mock a Express Controls EZMultiPli node."""
|
||||
node = Node(client, copy.deepcopy(express_controls_ezmultipli_state))
|
||||
client.driver.controller.nodes[node.node_id] = node
|
||||
return node
|
||||
|
@ -0,0 +1,673 @@
|
||||
{
|
||||
"nodeId": 96,
|
||||
"index": 0,
|
||||
"installerIcon": 3079,
|
||||
"userIcon": 3079,
|
||||
"status": 4,
|
||||
"ready": true,
|
||||
"isListening": true,
|
||||
"isRouting": true,
|
||||
"isSecure": false,
|
||||
"manufacturerId": 30,
|
||||
"productId": 1,
|
||||
"productType": 4,
|
||||
"firmwareVersion": "1.8",
|
||||
"zwavePlusVersion": 1,
|
||||
"name": "HSM200",
|
||||
"location": "Basement",
|
||||
"deviceConfig": {
|
||||
"filename": "/data/db/devices/0x001e/ezmultipli.json",
|
||||
"isEmbedded": true,
|
||||
"manufacturer": "Express Controls",
|
||||
"manufacturerId": 30,
|
||||
"label": "EZMultiPli",
|
||||
"description": "Multi Sensor",
|
||||
"devices": [
|
||||
{
|
||||
"productType": 4,
|
||||
"productId": 1
|
||||
}
|
||||
],
|
||||
"firmwareVersion": {
|
||||
"min": "0.0",
|
||||
"max": "255.255"
|
||||
},
|
||||
"associations": {},
|
||||
"paramInformation": {
|
||||
"_map": {}
|
||||
}
|
||||
},
|
||||
"label": "EZMultiPli",
|
||||
"interviewAttempts": 1,
|
||||
"endpoints": [
|
||||
{
|
||||
"nodeId": 96,
|
||||
"index": 0,
|
||||
"installerIcon": 3079,
|
||||
"userIcon": 3079,
|
||||
"deviceClass": {
|
||||
"basic": {
|
||||
"key": 4,
|
||||
"label": "Routing Slave"
|
||||
},
|
||||
"generic": {
|
||||
"key": 7,
|
||||
"label": "Notification Sensor"
|
||||
},
|
||||
"specific": {
|
||||
"key": 1,
|
||||
"label": "Notification Sensor"
|
||||
},
|
||||
"mandatorySupportedCCs": [],
|
||||
"mandatoryControlledCCs": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 113,
|
||||
"commandClassName": "Notification",
|
||||
"property": "Home Security",
|
||||
"propertyKey": "Motion sensor status",
|
||||
"propertyName": "Home Security",
|
||||
"propertyKeyName": "Motion sensor status",
|
||||
"ccVersion": 3,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Motion sensor status",
|
||||
"ccSpecific": {
|
||||
"notificationType": 7
|
||||
},
|
||||
"min": 0,
|
||||
"max": 255,
|
||||
"states": {
|
||||
"0": "idle",
|
||||
"7": "Motion detection (location provided)"
|
||||
}
|
||||
},
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 49,
|
||||
"commandClassName": "Multilevel Sensor",
|
||||
"property": "Air temperature",
|
||||
"propertyName": "Air temperature",
|
||||
"ccVersion": 6,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Air temperature",
|
||||
"ccSpecific": {
|
||||
"sensorType": 1,
|
||||
"scale": 0
|
||||
},
|
||||
"unit": "\u00b0C"
|
||||
},
|
||||
"value": 16.8
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 49,
|
||||
"commandClassName": "Multilevel Sensor",
|
||||
"property": "Illuminance",
|
||||
"propertyName": "Illuminance",
|
||||
"ccVersion": 6,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Illuminance",
|
||||
"ccSpecific": {
|
||||
"sensorType": 3,
|
||||
"scale": 0
|
||||
},
|
||||
"unit": "%"
|
||||
},
|
||||
"value": 61
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "duration",
|
||||
"propertyName": "duration",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "duration",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"label": "Remaining duration"
|
||||
}
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "currentColor",
|
||||
"propertyKey": 2,
|
||||
"propertyName": "currentColor",
|
||||
"propertyKeyName": "Red",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"description": "The current value of the Red color.",
|
||||
"label": "Current value (Red)",
|
||||
"min": 0,
|
||||
"max": 255
|
||||
},
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "currentColor",
|
||||
"propertyKey": 3,
|
||||
"propertyName": "currentColor",
|
||||
"propertyKeyName": "Green",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"description": "The current value of the Green color.",
|
||||
"label": "Current value (Green)",
|
||||
"min": 0,
|
||||
"max": 255
|
||||
},
|
||||
"value": 255
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "currentColor",
|
||||
"propertyKey": 4,
|
||||
"propertyName": "currentColor",
|
||||
"propertyKeyName": "Blue",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"description": "The current value of the Blue color.",
|
||||
"label": "Current value (Blue)",
|
||||
"min": 0,
|
||||
"max": 255
|
||||
},
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "currentColor",
|
||||
"propertyName": "currentColor",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "any",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Current Color"
|
||||
},
|
||||
"value": {
|
||||
"red": 0,
|
||||
"green": 255,
|
||||
"blue": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "hexColor",
|
||||
"propertyName": "hexColor",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "color",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"label": "RGB Color",
|
||||
"minLength": 6,
|
||||
"maxLength": 7
|
||||
},
|
||||
"value": "00ff00"
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "targetColor",
|
||||
"propertyKey": 2,
|
||||
"propertyName": "targetColor",
|
||||
"propertyKeyName": "Red",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"description": "The target value of the Red color.",
|
||||
"label": "Target value (Red)",
|
||||
"min": 0,
|
||||
"max": 255
|
||||
}
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "targetColor",
|
||||
"propertyKey": 3,
|
||||
"propertyName": "targetColor",
|
||||
"propertyKeyName": "Green",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"description": "The target value of the Green color.",
|
||||
"label": "Target value (Green)",
|
||||
"min": 0,
|
||||
"max": 255
|
||||
}
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "targetColor",
|
||||
"propertyKey": 4,
|
||||
"propertyName": "targetColor",
|
||||
"propertyKeyName": "Blue",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"description": "The target value of the Blue color.",
|
||||
"label": "Target value (Blue)",
|
||||
"min": 0,
|
||||
"max": 255
|
||||
}
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 51,
|
||||
"commandClassName": "Color Switch",
|
||||
"property": "targetColor",
|
||||
"propertyName": "targetColor",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"type": "any",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"label": "Target Color",
|
||||
"valueChangeOptions": ["transitionDuration"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 114,
|
||||
"commandClassName": "Manufacturer Specific",
|
||||
"property": "manufacturerId",
|
||||
"propertyName": "manufacturerId",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Manufacturer ID",
|
||||
"min": 0,
|
||||
"max": 65535
|
||||
},
|
||||
"value": 30
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 114,
|
||||
"commandClassName": "Manufacturer Specific",
|
||||
"property": "productType",
|
||||
"propertyName": "productType",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Product type",
|
||||
"min": 0,
|
||||
"max": 65535
|
||||
},
|
||||
"value": 4
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 114,
|
||||
"commandClassName": "Manufacturer Specific",
|
||||
"property": "productId",
|
||||
"propertyName": "productId",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Product ID",
|
||||
"min": 0,
|
||||
"max": 65535
|
||||
},
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 134,
|
||||
"commandClassName": "Version",
|
||||
"property": "libraryType",
|
||||
"propertyName": "libraryType",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Library type",
|
||||
"states": {
|
||||
"0": "Unknown",
|
||||
"1": "Static Controller",
|
||||
"2": "Controller",
|
||||
"3": "Enhanced Slave",
|
||||
"4": "Slave",
|
||||
"5": "Installer",
|
||||
"6": "Routing Slave",
|
||||
"7": "Bridge Controller",
|
||||
"8": "Device under Test",
|
||||
"9": "N/A",
|
||||
"10": "AV Remote",
|
||||
"11": "AV Device"
|
||||
}
|
||||
},
|
||||
"value": 3
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 134,
|
||||
"commandClassName": "Version",
|
||||
"property": "protocolVersion",
|
||||
"propertyName": "protocolVersion",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "string",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Z-Wave protocol version"
|
||||
},
|
||||
"value": "4.5"
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 134,
|
||||
"commandClassName": "Version",
|
||||
"property": "firmwareVersions",
|
||||
"propertyName": "firmwareVersions",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "string[]",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Z-Wave chip firmware versions"
|
||||
},
|
||||
"value": ["1.8"]
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 134,
|
||||
"commandClassName": "Version",
|
||||
"property": "hardwareVersion",
|
||||
"propertyName": "hardwareVersion",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": false,
|
||||
"label": "Z-Wave chip hardware version"
|
||||
},
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 112,
|
||||
"commandClassName": "Configuration",
|
||||
"property": 1,
|
||||
"propertyName": "OnTime",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"label": "OnTime",
|
||||
"default": 10,
|
||||
"min": 0,
|
||||
"max": 127,
|
||||
"unit": "Minutes",
|
||||
"valueSize": 1,
|
||||
"format": 0,
|
||||
"allowManualEntry": true,
|
||||
"isFromConfig": true
|
||||
},
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 112,
|
||||
"commandClassName": "Configuration",
|
||||
"property": 2,
|
||||
"propertyName": "OnLevel",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"description": "Allowable range: 0-99, 255",
|
||||
"label": "OnLevel",
|
||||
"default": 255,
|
||||
"min": 0,
|
||||
"max": 255,
|
||||
"valueSize": 1,
|
||||
"format": 1,
|
||||
"allowManualEntry": true,
|
||||
"isFromConfig": true
|
||||
},
|
||||
"value": 255
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 112,
|
||||
"commandClassName": "Configuration",
|
||||
"property": 3,
|
||||
"propertyName": "LiteMin",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"label": "LiteMin",
|
||||
"default": 60,
|
||||
"min": 0,
|
||||
"max": 127,
|
||||
"unit": "Minutes",
|
||||
"valueSize": 1,
|
||||
"format": 0,
|
||||
"allowManualEntry": true,
|
||||
"isFromConfig": true
|
||||
},
|
||||
"value": 60
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 112,
|
||||
"commandClassName": "Configuration",
|
||||
"property": 4,
|
||||
"propertyName": "TempMin",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"description": "A Temperature report is sent to the controller every TempMin minutes.",
|
||||
"label": "TempMin",
|
||||
"default": 60,
|
||||
"min": 0,
|
||||
"max": 127,
|
||||
"unit": "Minutes",
|
||||
"valueSize": 1,
|
||||
"format": 0,
|
||||
"allowManualEntry": true,
|
||||
"isFromConfig": true
|
||||
},
|
||||
"value": 60
|
||||
},
|
||||
{
|
||||
"endpoint": 0,
|
||||
"commandClass": 112,
|
||||
"commandClassName": "Configuration",
|
||||
"property": 5,
|
||||
"propertyName": "TempAdj",
|
||||
"ccVersion": 2,
|
||||
"metadata": {
|
||||
"type": "number",
|
||||
"readable": true,
|
||||
"writeable": true,
|
||||
"label": "TempAdj",
|
||||
"default": 0,
|
||||
"min": -128,
|
||||
"max": 127,
|
||||
"valueSize": 1,
|
||||
"format": 0,
|
||||
"allowManualEntry": true,
|
||||
"isFromConfig": true
|
||||
},
|
||||
"value": -40
|
||||
}
|
||||
],
|
||||
"isFrequentListening": false,
|
||||
"maxDataRate": 100000,
|
||||
"supportedDataRates": [40000, 100000],
|
||||
"protocolVersion": 3,
|
||||
"supportsBeaming": true,
|
||||
"supportsSecurity": false,
|
||||
"nodeType": 1,
|
||||
"zwavePlusNodeType": 0,
|
||||
"zwavePlusRoleType": 5,
|
||||
"deviceClass": {
|
||||
"basic": {
|
||||
"key": 4,
|
||||
"label": "Routing Slave"
|
||||
},
|
||||
"generic": {
|
||||
"key": 7,
|
||||
"label": "Notification Sensor"
|
||||
},
|
||||
"specific": {
|
||||
"key": 1,
|
||||
"label": "Notification Sensor"
|
||||
},
|
||||
"mandatorySupportedCCs": [],
|
||||
"mandatoryControlledCCs": []
|
||||
},
|
||||
"commandClasses": [
|
||||
{
|
||||
"id": 94,
|
||||
"name": "Z-Wave Plus Info",
|
||||
"version": 2,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 113,
|
||||
"name": "Notification",
|
||||
"version": 3,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "Multilevel Sensor",
|
||||
"version": 6,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"name": "Color Switch",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 114,
|
||||
"name": "Manufacturer Specific",
|
||||
"version": 2,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 134,
|
||||
"name": "Version",
|
||||
"version": 2,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 89,
|
||||
"name": "Association Group Information",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 133,
|
||||
"name": "Association",
|
||||
"version": 2,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 112,
|
||||
"name": "Configuration",
|
||||
"version": 2,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 119,
|
||||
"name": "Node Naming and Location",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 90,
|
||||
"name": "Device Reset Locally",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 122,
|
||||
"name": "Firmware Update Meta Data",
|
||||
"version": 2,
|
||||
"isSecure": false
|
||||
},
|
||||
{
|
||||
"id": 115,
|
||||
"name": "Powerlevel",
|
||||
"version": 1,
|
||||
"isSecure": false
|
||||
}
|
||||
],
|
||||
"interviewStage": "Complete",
|
||||
"deviceDatabaseUrl": "https://devices.zwave-js.io/?jumpTo=0x001e:0x0004:0x0001:1.8",
|
||||
"statistics": {
|
||||
"commandsTX": 147,
|
||||
"commandsRX": 322,
|
||||
"commandsDroppedRX": 0,
|
||||
"commandsDroppedTX": 3,
|
||||
"timeoutResponse": 0
|
||||
},
|
||||
"highestSecurityClass": -1,
|
||||
"isControllerNode": false,
|
||||
"keepAwake": false
|
||||
}
|
@ -13,9 +13,17 @@ from homeassistant.components.light import (
|
||||
ATTR_RGBW_COLOR,
|
||||
ATTR_SUPPORTED_COLOR_MODES,
|
||||
ATTR_TRANSITION,
|
||||
DOMAIN as LIGHT_DOMAIN,
|
||||
SUPPORT_TRANSITION,
|
||||
)
|
||||
from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_OFF, STATE_ON
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
|
||||
from .common import (
|
||||
AEON_SMART_SWITCH_LIGHT_ENTITY,
|
||||
@ -24,6 +32,8 @@ from .common import (
|
||||
ZEN_31_ENTITY,
|
||||
)
|
||||
|
||||
HSM200_V1_ENTITY = "light.hsm200"
|
||||
|
||||
|
||||
async def test_light(hass, client, bulb_6_multi_color, integration):
|
||||
"""Test the light entity."""
|
||||
@ -62,7 +72,6 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
||||
"type": "number",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"label": "Target value",
|
||||
"valueChangeOptions": ["transitionDuration"],
|
||||
},
|
||||
}
|
||||
@ -95,7 +104,6 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
||||
"type": "number",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"label": "Target value",
|
||||
"valueChangeOptions": ["transitionDuration"],
|
||||
},
|
||||
}
|
||||
@ -168,7 +176,6 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
||||
"type": "number",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"label": "Target value",
|
||||
"valueChangeOptions": ["transitionDuration"],
|
||||
},
|
||||
}
|
||||
@ -206,7 +213,6 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
||||
"type": "number",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"label": "Target value",
|
||||
"valueChangeOptions": ["transitionDuration"],
|
||||
},
|
||||
}
|
||||
@ -444,7 +450,6 @@ async def test_light(hass, client, bulb_6_multi_color, integration):
|
||||
"type": "number",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"label": "Target value",
|
||||
"valueChangeOptions": ["transitionDuration"],
|
||||
},
|
||||
}
|
||||
@ -469,7 +474,6 @@ async def test_optional_light(hass, client, aeon_smart_switch_6, integration):
|
||||
|
||||
async def test_rgbw_light(hass, client, zen_31, integration):
|
||||
"""Test the light entity."""
|
||||
zen_31
|
||||
state = hass.states.get(ZEN_31_ENTITY)
|
||||
|
||||
assert state
|
||||
@ -523,7 +527,6 @@ async def test_rgbw_light(hass, client, zen_31, integration):
|
||||
"type": "number",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"label": "Target value",
|
||||
"valueChangeOptions": ["transitionDuration"],
|
||||
},
|
||||
"value": 59,
|
||||
@ -542,3 +545,161 @@ async def test_light_none_color_value(hass, light_color_null_values, integration
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes[ATTR_SUPPORTED_FEATURES] == SUPPORT_TRANSITION
|
||||
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == ["hs"]
|
||||
|
||||
|
||||
async def test_black_is_off(hass, client, express_controls_ezmultipli, integration):
|
||||
"""Test the black is off light entity."""
|
||||
node = express_controls_ezmultipli
|
||||
state = hass.states.get(HSM200_V1_ENTITY)
|
||||
assert state.state == STATE_ON
|
||||
|
||||
# Attempt to turn on the light and ensure it defaults to white
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: HSM200_V1_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(client.async_send_command.call_args_list) == 1
|
||||
args = client.async_send_command.call_args_list[0][0][0]
|
||||
assert args["command"] == "node.set_value"
|
||||
assert args["nodeId"] == node.node_id
|
||||
assert args["valueId"] == {
|
||||
"commandClassName": "Color Switch",
|
||||
"commandClass": 51,
|
||||
"endpoint": 0,
|
||||
"property": "targetColor",
|
||||
"propertyName": "targetColor",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"label": "Target Color",
|
||||
"type": "any",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"valueChangeOptions": ["transitionDuration"],
|
||||
},
|
||||
}
|
||||
assert args["value"] == {"red": 255, "green": 255, "blue": 255}
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
|
||||
# Force the light to turn off
|
||||
event = Event(
|
||||
type="value updated",
|
||||
data={
|
||||
"source": "node",
|
||||
"event": "value updated",
|
||||
"nodeId": node.node_id,
|
||||
"args": {
|
||||
"commandClassName": "Color Switch",
|
||||
"commandClass": 51,
|
||||
"endpoint": 0,
|
||||
"property": "currentColor",
|
||||
"newValue": {
|
||||
"red": 0,
|
||||
"green": 0,
|
||||
"blue": 0,
|
||||
},
|
||||
"prevValue": {
|
||||
"red": 0,
|
||||
"green": 255,
|
||||
"blue": 0,
|
||||
},
|
||||
"propertyName": "currentColor",
|
||||
},
|
||||
},
|
||||
)
|
||||
node.receive_event(event)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(HSM200_V1_ENTITY)
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
# Force the light to turn on
|
||||
event = Event(
|
||||
type="value updated",
|
||||
data={
|
||||
"source": "node",
|
||||
"event": "value updated",
|
||||
"nodeId": node.node_id,
|
||||
"args": {
|
||||
"commandClassName": "Color Switch",
|
||||
"commandClass": 51,
|
||||
"endpoint": 0,
|
||||
"property": "currentColor",
|
||||
"newValue": {
|
||||
"red": 0,
|
||||
"green": 255,
|
||||
"blue": 0,
|
||||
},
|
||||
"prevValue": {
|
||||
"red": 0,
|
||||
"green": 0,
|
||||
"blue": 0,
|
||||
},
|
||||
"propertyName": "currentColor",
|
||||
},
|
||||
},
|
||||
)
|
||||
node.receive_event(event)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(HSM200_V1_ENTITY)
|
||||
assert state.state == STATE_ON
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: HSM200_V1_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(client.async_send_command.call_args_list) == 1
|
||||
args = client.async_send_command.call_args_list[0][0][0]
|
||||
assert args["command"] == "node.set_value"
|
||||
assert args["nodeId"] == node.node_id
|
||||
assert args["valueId"] == {
|
||||
"commandClassName": "Color Switch",
|
||||
"commandClass": 51,
|
||||
"endpoint": 0,
|
||||
"property": "targetColor",
|
||||
"propertyName": "targetColor",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"label": "Target Color",
|
||||
"type": "any",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"valueChangeOptions": ["transitionDuration"],
|
||||
},
|
||||
}
|
||||
assert args["value"] == {"red": 0, "green": 0, "blue": 0}
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
|
||||
# Assert that the last color is restored
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: HSM200_V1_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(client.async_send_command.call_args_list) == 1
|
||||
args = client.async_send_command.call_args_list[0][0][0]
|
||||
assert args["command"] == "node.set_value"
|
||||
assert args["nodeId"] == node.node_id
|
||||
assert args["valueId"] == {
|
||||
"commandClassName": "Color Switch",
|
||||
"commandClass": 51,
|
||||
"endpoint": 0,
|
||||
"property": "targetColor",
|
||||
"propertyName": "targetColor",
|
||||
"ccVersion": 1,
|
||||
"metadata": {
|
||||
"label": "Target Color",
|
||||
"type": "any",
|
||||
"readable": True,
|
||||
"writeable": True,
|
||||
"valueChangeOptions": ["transitionDuration"],
|
||||
},
|
||||
}
|
||||
assert args["value"] == {"red": 0, "green": 255, "blue": 0}
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
|
Loading…
x
Reference in New Issue
Block a user