Add barrier covers to zwave_js integration (#46379)

This commit is contained in:
kpine 2021-02-14 04:24:29 -08:00 committed by GitHub
parent accba85e35
commit dfa973f9ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1483 additions and 16 deletions

View File

@ -3,9 +3,11 @@ import logging
from typing import Any, Callable, List, Optional from typing import Any, Callable, List, Optional
from zwave_js_server.client import Client as ZwaveClient from zwave_js_server.client import Client as ZwaveClient
from zwave_js_server.model.value import Value as ZwaveValue
from homeassistant.components.cover import ( from homeassistant.components.cover import (
ATTR_POSITION, ATTR_POSITION,
DEVICE_CLASS_GARAGE,
DOMAIN as COVER_DOMAIN, DOMAIN as COVER_DOMAIN,
SUPPORT_CLOSE, SUPPORT_CLOSE,
SUPPORT_OPEN, SUPPORT_OPEN,
@ -20,7 +22,15 @@ from .discovery import ZwaveDiscoveryInfo
from .entity import ZWaveBaseEntity from .entity import ZWaveBaseEntity
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
SUPPORT_GARAGE = SUPPORT_OPEN | SUPPORT_CLOSE
BARRIER_TARGET_CLOSE = 0
BARRIER_TARGET_OPEN = 255
BARRIER_STATE_CLOSED = 0
BARRIER_STATE_CLOSING = 252
BARRIER_STATE_STOPPED = 253
BARRIER_STATE_OPENING = 254
BARRIER_STATE_OPEN = 255
async def async_setup_entry( async def async_setup_entry(
@ -33,7 +43,10 @@ async def async_setup_entry(
def async_add_cover(info: ZwaveDiscoveryInfo) -> None: def async_add_cover(info: ZwaveDiscoveryInfo) -> None:
"""Add Z-Wave cover.""" """Add Z-Wave cover."""
entities: List[ZWaveBaseEntity] = [] entities: List[ZWaveBaseEntity] = []
entities.append(ZWaveCover(config_entry, client, info)) if info.platform_hint == "motorized_barrier":
entities.append(ZwaveMotorizedBarrier(config_entry, client, info))
else:
entities.append(ZWaveCover(config_entry, client, info))
async_add_entities(entities) async_add_entities(entities)
hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append( hass.data[DOMAIN][config_entry.entry_id][DATA_UNSUBSCRIBE].append(
@ -99,3 +112,65 @@ class ZWaveCover(ZWaveBaseEntity, CoverEntity):
target_value = self.get_zwave_value("Close") or self.get_zwave_value("Down") target_value = self.get_zwave_value("Close") or self.get_zwave_value("Down")
if target_value: if target_value:
await self.info.node.async_set_value(target_value, False) await self.info.node.async_set_value(target_value, False)
class ZwaveMotorizedBarrier(ZWaveBaseEntity, CoverEntity):
"""Representation of a Z-Wave motorized barrier device."""
def __init__(
self,
config_entry: ConfigEntry,
client: ZwaveClient,
info: ZwaveDiscoveryInfo,
) -> None:
"""Initialize a ZwaveMotorizedBarrier entity."""
super().__init__(config_entry, client, info)
self._target_state: ZwaveValue = self.get_zwave_value(
"targetState", add_to_watched_value_ids=False
)
@property
def supported_features(self) -> Optional[int]:
"""Flag supported features."""
return SUPPORT_OPEN | SUPPORT_CLOSE
@property
def device_class(self) -> Optional[str]:
"""Return the class of this device, from component DEVICE_CLASSES."""
return DEVICE_CLASS_GARAGE
@property
def is_opening(self) -> Optional[bool]:
"""Return if the cover is opening or not."""
if self.info.primary_value.value is None:
return None
return bool(self.info.primary_value.value == BARRIER_STATE_OPENING)
@property
def is_closing(self) -> Optional[bool]:
"""Return if the cover is closing or not."""
if self.info.primary_value.value is None:
return None
return bool(self.info.primary_value.value == BARRIER_STATE_CLOSING)
@property
def is_closed(self) -> Optional[bool]:
"""Return if the cover is closed or not."""
if self.info.primary_value.value is None:
return None
# If a barrier is in the stopped state, the only way to proceed is by
# issuing an open cover command. Return None in this case which
# produces an unknown state and allows it to be resolved with an open
# command.
if self.info.primary_value.value == BARRIER_STATE_STOPPED:
return None
return bool(self.info.primary_value.value == BARRIER_STATE_CLOSED)
async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the garage door."""
await self.info.node.async_set_value(self._target_state, BARRIER_TARGET_OPEN)
async def async_close_cover(self, **kwargs: Any) -> None:
"""Close the garage door."""
await self.info.node.async_set_value(self._target_state, BARRIER_TARGET_CLOSE)

View File

@ -1,7 +1,7 @@
"""Map Z-Wave nodes and values to Home Assistant entities.""" """Map Z-Wave nodes and values to Home Assistant entities."""
from dataclasses import dataclass from dataclasses import dataclass
from typing import Generator, Optional, Set, Union from typing import Generator, List, Optional, Set, Union
from zwave_js_server.const import CommandClass from zwave_js_server.const import CommandClass
from zwave_js_server.model.node import Node as ZwaveNode from zwave_js_server.model.node import Node as ZwaveNode
@ -78,7 +78,7 @@ class ZWaveDiscoverySchema:
# [optional] the node's specific device class must match ANY of these values # [optional] the node's specific device class must match ANY of these values
device_class_specific: Optional[Set[str]] = None device_class_specific: Optional[Set[str]] = None
# [optional] additional values that ALL need to be present on the node for this scheme to pass # [optional] additional values that ALL need to be present on the node for this scheme to pass
required_values: Optional[Set[ZWaveValueDiscoverySchema]] = None required_values: Optional[List[ZWaveValueDiscoverySchema]] = None
# [optional] bool to specify if this primary value may be discovered by multiple platforms # [optional] bool to specify if this primary value may be discovered by multiple platforms
allow_multi: bool = False allow_multi: bool = False
@ -345,10 +345,22 @@ DISCOVERY_SCHEMAS = [
command_class={CommandClass.SWITCH_BINARY}, property={"currentValue"} command_class={CommandClass.SWITCH_BINARY}, property={"currentValue"}
), ),
), ),
# binary switch
# barrier operator signaling states
ZWaveDiscoverySchema(
platform="switch",
hint="barrier_event_signaling_state",
primary_value=ZWaveValueDiscoverySchema(
command_class={CommandClass.BARRIER_OPERATOR},
property={"signalingState"},
type={"number"},
),
),
# cover # cover
# window coverings
ZWaveDiscoverySchema( ZWaveDiscoverySchema(
platform="cover", platform="cover",
hint="cover", hint="window_cover",
device_class_generic={"Multilevel Switch"}, device_class_generic={"Multilevel Switch"},
device_class_specific={ device_class_specific={
"Motor Control Class A", "Motor Control Class A",
@ -362,6 +374,24 @@ DISCOVERY_SCHEMAS = [
type={"number"}, type={"number"},
), ),
), ),
# cover
# motorized barriers
ZWaveDiscoverySchema(
platform="cover",
hint="motorized_barrier",
primary_value=ZWaveValueDiscoverySchema(
command_class={CommandClass.BARRIER_OPERATOR},
property={"currentState"},
type={"number"},
),
required_values=[
ZWaveValueDiscoverySchema(
command_class={CommandClass.BARRIER_OPERATOR},
property={"targetState"},
type={"number"},
),
],
),
# fan # fan
ZWaveDiscoverySchema( ZWaveDiscoverySchema(
platform="fan", platform="fan",
@ -430,13 +460,10 @@ def async_discover_values(node: ZwaveNode) -> Generator[ZwaveDiscoveryInfo, None
continue continue
# check additional required values # check additional required values
if schema.required_values is not None: if schema.required_values is not None:
required_values_present = True if not all(
for val_scheme in schema.required_values: any(check_value(val, val_scheme) for val in node.values.values())
for val in node.values.values(): for val_scheme in schema.required_values
if not check_value(val, val_scheme): ):
required_values_present = False
break
if not required_values_present:
continue continue
# all checks passed, this value belongs to an entity # all checks passed, this value belongs to an entity
yield ZwaveDiscoveryInfo( yield ZwaveDiscoveryInfo(

View File

@ -17,6 +17,10 @@ from .entity import ZWaveBaseEntity
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
BARRIER_EVENT_SIGNALING_OFF = 0
BARRIER_EVENT_SIGNALING_ON = 255
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: Callable
) -> None: ) -> None:
@ -27,7 +31,12 @@ async def async_setup_entry(
def async_add_switch(info: ZwaveDiscoveryInfo) -> None: def async_add_switch(info: ZwaveDiscoveryInfo) -> None:
"""Add Z-Wave Switch.""" """Add Z-Wave Switch."""
entities: List[ZWaveBaseEntity] = [] entities: List[ZWaveBaseEntity] = []
entities.append(ZWaveSwitch(config_entry, client, info)) if info.platform_hint == "barrier_event_signaling_state":
entities.append(
ZWaveBarrierEventSignalingSwitch(config_entry, client, info)
)
else:
entities.append(ZWaveSwitch(config_entry, client, info))
async_add_entities(entities) async_add_entities(entities)
@ -62,3 +71,59 @@ class ZWaveSwitch(ZWaveBaseEntity, SwitchEntity):
target_value = self.get_zwave_value("targetValue") target_value = self.get_zwave_value("targetValue")
if target_value is not None: if target_value is not None:
await self.info.node.async_set_value(target_value, False) await self.info.node.async_set_value(target_value, False)
class ZWaveBarrierEventSignalingSwitch(ZWaveBaseEntity, SwitchEntity):
"""This switch is used to turn on or off a barrier device's event signaling subsystem."""
def __init__(
self,
config_entry: ConfigEntry,
client: ZwaveClient,
info: ZwaveDiscoveryInfo,
) -> None:
"""Initialize a ZWaveBarrierEventSignalingSwitch entity."""
super().__init__(config_entry, client, info)
self._name = self.generate_name(include_value_name=True)
self._state: Optional[bool] = None
self._update_state()
@callback
def on_value_update(self) -> None:
"""Call when a watched value is added or updated."""
self._update_state()
@property
def name(self) -> str:
"""Return default name from device name and value name combination."""
return self._name
@property
def is_on(self) -> Optional[bool]: # type: ignore
"""Return a boolean for the state of the switch."""
return self._state
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on."""
await self.info.node.async_set_value(
self.info.primary_value, BARRIER_EVENT_SIGNALING_ON
)
# this value is not refreshed, so assume success
self._state = True
self.async_write_ha_state()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the switch off."""
await self.info.node.async_set_value(
self.info.primary_value, BARRIER_EVENT_SIGNALING_OFF
)
# this value is not refreshed, so assume success
self._state = False
self.async_write_ha_state()
@callback
def _update_state(self) -> None:
self._state = None
if self.info.primary_value.value is not None:
self._state = self.info.primary_value.value == BARRIER_EVENT_SIGNALING_ON

View File

@ -158,6 +158,12 @@ def in_wall_smart_fan_control_state_fixture():
return json.loads(load_fixture("zwave_js/in_wall_smart_fan_control_state.json")) return json.loads(load_fixture("zwave_js/in_wall_smart_fan_control_state.json"))
@pytest.fixture(name="gdc_zw062_state", scope="session")
def motorized_barrier_cover_state_fixture():
"""Load the motorized barrier cover node state fixture data."""
return json.loads(load_fixture("zwave_js/cover_zw062_state.json"))
@pytest.fixture(name="client") @pytest.fixture(name="client")
def mock_client_fixture(controller_state, version_state): def mock_client_fixture(controller_state, version_state):
"""Mock a client.""" """Mock a client."""
@ -345,3 +351,11 @@ def multiple_devices_fixture(
node = Node(client, lock_schlage_be469_state) node = Node(client, lock_schlage_be469_state)
client.driver.controller.nodes[node.node_id] = node client.driver.controller.nodes[node.node_id] = node
return client.driver.controller.nodes return client.driver.controller.nodes
@pytest.fixture(name="gdc_zw062")
def motorized_barrier_cover_fixture(client, gdc_zw062_state):
"""Mock a motorized barrier node."""
node = Node(client, gdc_zw062_state)
client.driver.controller.nodes[node.node_id] = node
return node

View File

@ -1,13 +1,28 @@
"""Test the Z-Wave JS cover platform.""" """Test the Z-Wave JS cover platform."""
from zwave_js_server.event import Event from zwave_js_server.event import Event
from homeassistant.components.cover import ATTR_CURRENT_POSITION from homeassistant.components.cover import (
ATTR_CURRENT_POSITION,
DEVICE_CLASS_GARAGE,
DOMAIN,
SERVICE_CLOSE_COVER,
SERVICE_OPEN_COVER,
)
from homeassistant.const import (
ATTR_DEVICE_CLASS,
STATE_CLOSED,
STATE_CLOSING,
STATE_OPEN,
STATE_OPENING,
STATE_UNKNOWN,
)
WINDOW_COVER_ENTITY = "cover.zws_12" WINDOW_COVER_ENTITY = "cover.zws_12"
GDC_COVER_ENTITY = "cover.aeon_labs_garage_door_controller_gen5"
async def test_cover(hass, client, chain_actuator_zws12, integration): async def test_window_cover(hass, client, chain_actuator_zws12, integration):
"""Test the light entity.""" """Test the cover entity."""
node = chain_actuator_zws12 node = chain_actuator_zws12
state = hass.states.get(WINDOW_COVER_ENTITY) state = hass.states.get(WINDOW_COVER_ENTITY)
@ -282,3 +297,197 @@ async def test_cover(hass, client, chain_actuator_zws12, integration):
state = hass.states.get(WINDOW_COVER_ENTITY) state = hass.states.get(WINDOW_COVER_ENTITY)
assert state.state == "closed" assert state.state == "closed"
async def test_motor_barrier_cover(hass, client, gdc_zw062, integration):
"""Test the cover entity."""
node = gdc_zw062
state = hass.states.get(GDC_COVER_ENTITY)
assert state
assert state.attributes[ATTR_DEVICE_CLASS] == DEVICE_CLASS_GARAGE
assert state.state == STATE_CLOSED
# Test open
await hass.services.async_call(
DOMAIN, SERVICE_OPEN_COVER, {"entity_id": GDC_COVER_ENTITY}, blocking=True
)
assert len(client.async_send_command.call_args_list) == 1
args = client.async_send_command.call_args[0][0]
assert args["command"] == "node.set_value"
assert args["nodeId"] == 12
assert args["value"] == 255
assert args["valueId"] == {
"ccVersion": 0,
"commandClass": 102,
"commandClassName": "Barrier Operator",
"endpoint": 0,
"metadata": {
"label": "Target Barrier State",
"max": 255,
"min": 0,
"readable": True,
"states": {"0": "Closed", "255": "Open"},
"type": "number",
"writeable": True,
},
"property": "targetState",
"propertyName": "targetState",
}
# state doesn't change until currentState value update is received
state = hass.states.get(GDC_COVER_ENTITY)
assert state.state == STATE_CLOSED
client.async_send_command.reset_mock()
# Test close
await hass.services.async_call(
DOMAIN, SERVICE_CLOSE_COVER, {"entity_id": GDC_COVER_ENTITY}, blocking=True
)
assert len(client.async_send_command.call_args_list) == 1
args = client.async_send_command.call_args[0][0]
assert args["command"] == "node.set_value"
assert args["nodeId"] == 12
assert args["value"] == 0
assert args["valueId"] == {
"ccVersion": 0,
"commandClass": 102,
"commandClassName": "Barrier Operator",
"endpoint": 0,
"metadata": {
"label": "Target Barrier State",
"max": 255,
"min": 0,
"readable": True,
"states": {"0": "Closed", "255": "Open"},
"type": "number",
"writeable": True,
},
"property": "targetState",
"propertyName": "targetState",
}
# state doesn't change until currentState value update is received
state = hass.states.get(GDC_COVER_ENTITY)
assert state.state == STATE_CLOSED
client.async_send_command.reset_mock()
# Barrier sends an opening state
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": 12,
"args": {
"commandClassName": "Barrier Operator",
"commandClass": 102,
"endpoint": 0,
"property": "currentState",
"newValue": 254,
"prevValue": 0,
"propertyName": "currentState",
},
},
)
node.receive_event(event)
state = hass.states.get(GDC_COVER_ENTITY)
assert state.state == STATE_OPENING
# Barrier sends an opened state
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": 12,
"args": {
"commandClassName": "Barrier Operator",
"commandClass": 102,
"endpoint": 0,
"property": "currentState",
"newValue": 255,
"prevValue": 254,
"propertyName": "currentState",
},
},
)
node.receive_event(event)
state = hass.states.get(GDC_COVER_ENTITY)
assert state.state == STATE_OPEN
# Barrier sends a closing state
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": 12,
"args": {
"commandClassName": "Barrier Operator",
"commandClass": 102,
"endpoint": 0,
"property": "currentState",
"newValue": 252,
"prevValue": 255,
"propertyName": "currentState",
},
},
)
node.receive_event(event)
state = hass.states.get(GDC_COVER_ENTITY)
assert state.state == STATE_CLOSING
# Barrier sends a closed state
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": 12,
"args": {
"commandClassName": "Barrier Operator",
"commandClass": 102,
"endpoint": 0,
"property": "currentState",
"newValue": 0,
"prevValue": 252,
"propertyName": "currentState",
},
},
)
node.receive_event(event)
state = hass.states.get(GDC_COVER_ENTITY)
assert state.state == STATE_CLOSED
# Barrier sends a stopped state
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": 12,
"args": {
"commandClassName": "Barrier Operator",
"commandClass": 102,
"endpoint": 0,
"property": "currentState",
"newValue": 253,
"prevValue": 252,
"propertyName": "currentState",
},
},
)
node.receive_event(event)
state = hass.states.get(GDC_COVER_ENTITY)
assert state.state == STATE_UNKNOWN

View File

@ -2,6 +2,9 @@
from zwave_js_server.event import Event from zwave_js_server.event import Event
from homeassistant.components.switch import DOMAIN, SERVICE_TURN_OFF, SERVICE_TURN_ON
from homeassistant.const import STATE_OFF, STATE_ON
from .common import SWITCH_ENTITY from .common import SWITCH_ENTITY
@ -83,3 +86,141 @@ async def test_switch(hass, hank_binary_switch, integration, client):
"value": False, "value": False,
} }
assert args["value"] is False assert args["value"] is False
async def test_barrier_signaling_switch(hass, gdc_zw062, integration, client):
"""Test barrier signaling state switch."""
node = gdc_zw062
entity = "switch.aeon_labs_garage_door_controller_gen5_signaling_state_visual"
state = hass.states.get(entity)
assert state
assert state.state == "on"
# Test turning off
await hass.services.async_call(
DOMAIN, SERVICE_TURN_OFF, {"entity_id": entity}, blocking=True
)
assert len(client.async_send_command.call_args_list) == 1
args = client.async_send_command.call_args[0][0]
assert args["command"] == "node.set_value"
assert args["nodeId"] == 12
assert args["value"] == 0
assert args["valueId"] == {
"ccVersion": 0,
"commandClass": 102,
"commandClassName": "Barrier Operator",
"endpoint": 0,
"metadata": {
"label": "Signaling State (Visual)",
"max": 255,
"min": 0,
"readable": True,
"states": {"0": "Off", "255": "On"},
"type": "number",
"writeable": True,
},
"property": "signalingState",
"propertyKey": 2,
"propertyKeyName": "2",
"propertyName": "signalingState",
"value": 255,
}
# state change is optimistic and writes state
await hass.async_block_till_done()
state = hass.states.get(entity)
assert state.state == STATE_OFF
client.async_send_command.reset_mock()
# Test turning on
await hass.services.async_call(
DOMAIN, SERVICE_TURN_ON, {"entity_id": entity}, blocking=True
)
# Note: the valueId's value is still 255 because we never
# received an updated value
assert len(client.async_send_command.call_args_list) == 1
args = client.async_send_command.call_args[0][0]
assert args["command"] == "node.set_value"
assert args["nodeId"] == 12
assert args["value"] == 255
assert args["valueId"] == {
"ccVersion": 0,
"commandClass": 102,
"commandClassName": "Barrier Operator",
"endpoint": 0,
"metadata": {
"label": "Signaling State (Visual)",
"max": 255,
"min": 0,
"readable": True,
"states": {"0": "Off", "255": "On"},
"type": "number",
"writeable": True,
},
"property": "signalingState",
"propertyKey": 2,
"propertyKeyName": "2",
"propertyName": "signalingState",
"value": 255,
}
# state change is optimistic and writes state
await hass.async_block_till_done()
state = hass.states.get(entity)
assert state.state == STATE_ON
# Received a refresh off
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": 12,
"args": {
"commandClassName": "Barrier Operator",
"commandClass": 102,
"endpoint": 0,
"property": "signalingState",
"propertyKey": 2,
"newValue": 0,
"prevValue": 0,
"propertyName": "signalingState",
"propertyKeyName": "2",
},
},
)
node.receive_event(event)
state = hass.states.get(entity)
assert state.state == STATE_OFF
# Received a refresh off
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": 12,
"args": {
"commandClassName": "Barrier Operator",
"commandClass": 102,
"endpoint": 0,
"property": "signalingState",
"propertyKey": 2,
"newValue": 255,
"prevValue": 255,
"propertyName": "signalingState",
"propertyKeyName": "2",
},
},
)
node.receive_event(event)
state = hass.states.get(entity)
assert state.state == STATE_ON

View File

@ -0,0 +1,936 @@
{
"nodeId": 12,
"index": 0,
"installerIcon": 7680,
"userIcon": 7680,
"status": 4,
"ready": true,
"deviceClass": {
"basic": "Routing Slave",
"generic": "Entry Control",
"specific": "Secure Barrier Add-on",
"mandatorySupportedCCs": [
"Application Status",
"Association",
"Association Group Information",
"Barrier Operator",
"Battery",
"Device Reset Locally",
"Manufacturer Specific",
"Notification",
"Powerlevel",
"Security",
"Security 2",
"Supervision",
"Transport Service",
"Version",
"Z-Wave Plus Info"
],
"mandatoryControlCCs": []
},
"isListening": true,
"isFrequentListening": false,
"isRouting": true,
"maxBaudRate": 40000,
"isSecure": true,
"version": 4,
"isBeaming": true,
"manufacturerId": 134,
"productId": 62,
"productType": 259,
"firmwareVersion": "1.12",
"zwavePlusVersion": 1,
"nodeType": 0,
"roleType": 5,
"deviceConfig": {
"manufacturerId": 134,
"manufacturer": "AEON Labs",
"label": "ZW062",
"description": "Aeon Labs Garage Door Controller Gen5",
"devices": [
{
"productType": "0x0003",
"productId": "0x003e"
},
{
"productType": "0x0103",
"productId": "0x003e"
},
{
"productType": "0x0203",
"productId": "0x003e"
}
],
"firmwareVersion": {
"min": "0.0",
"max": "255.255"
},
"associations": {},
"paramInformation": {
"_map": {}
}
},
"label": "ZW062",
"neighbors": [
1,
8,
11,
15,
19,
21,
22,
24,
25,
26,
27,
29
],
"interviewAttempts": 1,
"endpoints": [
{
"nodeId": 12,
"index": 0,
"installerIcon": 7680,
"userIcon": 7680
}
],
"values": [
{
"endpoint": 0,
"commandClass": 37,
"commandClassName": "Binary Switch",
"property": "currentValue",
"propertyName": "currentValue",
"ccVersion": 1,
"metadata": {
"type": "boolean",
"readable": true,
"writeable": false,
"label": "Current value"
},
"value": false
},
{
"endpoint": 0,
"commandClass": 37,
"commandClassName": "Binary Switch",
"property": "targetValue",
"propertyName": "targetValue",
"ccVersion": 1,
"metadata": {
"type": "boolean",
"readable": true,
"writeable": true,
"label": "Target value"
}
},
{
"endpoint": 0,
"commandClass": 102,
"commandClassName": "Barrier Operator",
"property": "currentState",
"propertyName": "currentState",
"ccVersion": 0,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"min": 0,
"max": 255,
"label": "Current Barrier State",
"states": {
"0": "Closed",
"252": "Closing",
"253": "Stopped",
"254": "Opening",
"255": "Open"
}
},
"value": 0
},
{
"endpoint": 0,
"commandClass": 102,
"commandClassName": "Barrier Operator",
"property": "position",
"propertyName": "position",
"ccVersion": 0,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"min": 0,
"max": 100,
"label": "Barrier Position",
"unit": "%"
},
"value": 0
},
{
"endpoint": 0,
"commandClass": 102,
"commandClassName": "Barrier Operator",
"property": "signalingState",
"propertyKey": 1,
"propertyName": "signalingState",
"propertyKeyName": "1",
"ccVersion": 0,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"min": 0,
"max": 255,
"label": "Signaling State (Audible)",
"states": {
"0": "Off",
"255": "On"
}
},
"value": 255
},
{
"endpoint": 0,
"commandClass": 102,
"commandClassName": "Barrier Operator",
"property": "signalingState",
"propertyKey": 2,
"propertyName": "signalingState",
"propertyKeyName": "2",
"ccVersion": 0,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"min": 0,
"max": 255,
"label": "Signaling State (Visual)",
"states": {
"0": "Off",
"255": "On"
}
},
"value": 255
},
{
"endpoint": 0,
"commandClass": 102,
"commandClassName": "Barrier Operator",
"property": "targetState",
"propertyName": "targetState",
"ccVersion": 0,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"min": 0,
"max": 255,
"label": "Target Barrier State",
"states": {
"0": "Closed",
"255": "Open"
}
}
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 32,
"propertyName": "Startup ringtone",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 1,
"min": 1,
"max": 100,
"default": 1,
"format": 0,
"allowManualEntry": true,
"label": "Startup ringtone",
"description": "Configure the default startup ringtone",
"isFromConfig": true
},
"value": 1
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 35,
"propertyName": "Calibration timout",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 2,
"min": 1,
"max": 255,
"default": 60,
"format": 0,
"allowManualEntry": true,
"label": "Calibration timout",
"description": "Set the timeout of all calibration steps for the Sensor.",
"isFromConfig": true
},
"value": 13
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 36,
"propertyName": "Number of alarm musics",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"valueSize": 1,
"min": 1,
"max": 100,
"default": 1,
"format": 0,
"allowManualEntry": true,
"label": "Number of alarm musics",
"description": "Get the number of alarm musics",
"isFromConfig": true
},
"value": 5
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 39,
"propertyName": "Unknown state alarm mode",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 0,
"max": 0,
"default": 0,
"format": 0,
"allowManualEntry": true,
"label": "Unknown state alarm mode",
"description": "Configuration alarm mode when the garage door is in \"unknown\" state",
"isFromConfig": true
},
"value": 100927488
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 40,
"propertyName": "Closed alarm mode",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 0,
"max": 0,
"default": 0,
"format": 0,
"allowManualEntry": true,
"label": "Closed alarm mode",
"description": "Configure the alarm mode when the garage door is in closed position.",
"isFromConfig": true
},
"value": 33883392
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 41,
"propertyName": "Tamper switch configuration",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 1,
"min": 0,
"max": 255,
"default": 0,
"format": 1,
"allowManualEntry": true,
"label": "Tamper switch configuration",
"description": "Configuration report for the tamper switch State",
"isFromConfig": true
},
"value": 15
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 42,
"propertyName": "Battery state",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"valueSize": 1,
"min": 0,
"max": 16,
"default": 0,
"format": 0,
"allowManualEntry": true,
"label": "Battery state",
"description": "Configuration report for the battery state of Sensor",
"isFromConfig": true
},
"value": 0
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 45,
"propertyName": "Temperature",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"valueSize": 2,
"min": 0,
"max": 500,
"default": 0,
"format": 0,
"allowManualEntry": true,
"label": "Temperature",
"description": "Get the environment temperature",
"isFromConfig": true
},
"value": 550
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 47,
"propertyName": "Button definition",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 1,
"min": 0,
"max": 1,
"default": 0,
"format": 0,
"allowManualEntry": false,
"states": {
"0": "Mode 0",
"1": "Mode 1"
},
"label": "Button definition",
"description": "Define the function of Button- or Button+.",
"isFromConfig": true
},
"value": 0
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 80,
"propertyName": "Door state change report type",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 1,
"min": 1,
"max": 2,
"default": 2,
"format": 0,
"allowManualEntry": false,
"states": {
"1": "Send hail CC",
"2": "Send barrier operator report CC"
},
"label": "Door state change report type",
"description": "Configure the door state change report type",
"isFromConfig": true
},
"value": 2
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 241,
"propertyName": "Pair the Sensor",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 0,
"max": 1431655681,
"default": 0,
"format": 0,
"allowManualEntry": false,
"states": {
"0": "Stop sensor pairing",
"1431655681": "Start sensor pairing"
},
"label": "Pair the Sensor",
"description": "Pair the Sensor with Garage Door Controller",
"isFromConfig": true
},
"value": 33554943
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 252,
"propertyName": "Lock Configuration",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 1,
"min": 0,
"max": 1,
"default": 0,
"format": 0,
"allowManualEntry": false,
"states": {
"0": "Configuration enabled",
"1": "Configuration disabled (locked)"
},
"label": "Lock Configuration",
"description": "Enable/disable configuration",
"isFromConfig": true
},
"value": 0
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 37,
"propertyKey": 255,
"propertyName": "Disable opening alarm",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 0,
"max": 1,
"default": 1,
"format": 0,
"allowManualEntry": false,
"states": {
"0": "Disable alarm prompt",
"1": "Enable alarm prompt"
},
"label": "Disable opening alarm",
"isFromConfig": true
},
"value": 1
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 37,
"propertyKey": 65280,
"propertyName": "Opening alarm volume",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 1,
"max": 10,
"default": 8,
"format": 0,
"allowManualEntry": true,
"label": "Opening alarm volume",
"isFromConfig": true
},
"value": 1
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 37,
"propertyKey": 16711680,
"propertyName": "Opening alarm choice",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 1,
"max": 4,
"default": 1,
"format": 0,
"allowManualEntry": true,
"label": "Opening alarm choice",
"description": "Alarm mode when the garage door is opening",
"isFromConfig": true
},
"value": 2
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 37,
"propertyKey": 251658240,
"propertyName": "Opening alarm LED mode",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 1,
"max": 10,
"default": 10,
"format": 0,
"allowManualEntry": true,
"label": "Opening alarm LED mode",
"isFromConfig": true
},
"value": 5
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 38,
"propertyKey": 255,
"propertyName": "Disable closing alarm",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 0,
"max": 1,
"default": 1,
"format": 0,
"allowManualEntry": false,
"states": {
"0": "Disable alarm prompt",
"1": "Enable alarm prompt"
},
"label": "Disable closing alarm",
"isFromConfig": true
},
"value": 0
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 38,
"propertyKey": 65280,
"propertyName": "Closing alarm volume",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 1,
"max": 10,
"default": 8,
"format": 0,
"allowManualEntry": true,
"label": "Closing alarm volume",
"isFromConfig": true
},
"value": 8
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 38,
"propertyKey": 16711680,
"propertyName": "Closing alarm choice",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 1,
"max": 4,
"default": 2,
"format": 0,
"allowManualEntry": true,
"label": "Closing alarm choice",
"description": "Alarm mode when the garage door is closing",
"isFromConfig": true
},
"value": 3
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 38,
"propertyKey": 251658240,
"propertyName": "Closing alarm LED mode",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": true,
"writeable": true,
"valueSize": 4,
"min": 1,
"max": 10,
"default": 6,
"format": 0,
"allowManualEntry": true,
"label": "Closing alarm LED mode",
"isFromConfig": true
},
"value": 8
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 34,
"propertyName": "Sensor Calibration",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": false,
"writeable": true,
"valueSize": 1,
"min": 0,
"max": 1,
"default": 0,
"format": 0,
"allowManualEntry": false,
"states": {
"0": "Calibration not active",
"1": "Begin calibration"
},
"label": "Sensor Calibration",
"description": "Perform Sensor Calibration",
"isFromConfig": true
}
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 43,
"propertyName": "Play or Pause ringtone",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": false,
"writeable": true,
"valueSize": 1,
"min": 1,
"max": 255,
"default": 1,
"format": 1,
"allowManualEntry": true,
"label": "Play or Pause ringtone",
"description": "Start playing or Stop playing the ringtone",
"isFromConfig": true
}
},
{
"endpoint": 0,
"commandClass": 112,
"commandClassName": "Configuration",
"property": 44,
"propertyName": "Ringtone test volume",
"ccVersion": 1,
"metadata": {
"type": "number",
"readable": false,
"writeable": true,
"valueSize": 1,
"min": 1,
"max": 10,
"default": 1,
"format": 0,
"allowManualEntry": true,
"label": "Ringtone test volume",
"description": "Set volume for test of ringtone",
"isFromConfig": true
}
},
{
"endpoint": 0,
"commandClass": 113,
"commandClassName": "Notification",
"property": "alarmType",
"propertyName": "alarmType",
"ccVersion": 4,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"min": 0,
"max": 255,
"label": "Alarm Type"
}
},
{
"endpoint": 0,
"commandClass": 113,
"commandClassName": "Notification",
"property": "alarmLevel",
"propertyName": "alarmLevel",
"ccVersion": 4,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"min": 0,
"max": 255,
"label": "Alarm Level"
}
},
{
"endpoint": 0,
"commandClass": 114,
"commandClassName": "Manufacturer Specific",
"property": "manufacturerId",
"propertyName": "manufacturerId",
"ccVersion": 2,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"min": 0,
"max": 65535,
"label": "Manufacturer ID"
},
"value": 134
},
{
"endpoint": 0,
"commandClass": 114,
"commandClassName": "Manufacturer Specific",
"property": "productType",
"propertyName": "productType",
"ccVersion": 2,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"min": 0,
"max": 65535,
"label": "Product type"
},
"value": 259
},
{
"endpoint": 0,
"commandClass": 114,
"commandClassName": "Manufacturer Specific",
"property": "productId",
"propertyName": "productId",
"ccVersion": 2,
"metadata": {
"type": "number",
"readable": true,
"writeable": false,
"min": 0,
"max": 65535,
"label": "Product ID"
},
"value": 62
},
{
"endpoint": 0,
"commandClass": 134,
"commandClassName": "Version",
"property": "libraryType",
"propertyName": "libraryType",
"ccVersion": 2,
"metadata": {
"type": "any",
"readable": true,
"writeable": false,
"label": "Library type"
},
"value": 3
},
{
"endpoint": 0,
"commandClass": 134,
"commandClassName": "Version",
"property": "protocolVersion",
"propertyName": "protocolVersion",
"ccVersion": 2,
"metadata": {
"type": "any",
"readable": true,
"writeable": false,
"label": "Z-Wave protocol version"
},
"value": "3.99"
},
{
"endpoint": 0,
"commandClass": 134,
"commandClassName": "Version",
"property": "firmwareVersions",
"propertyName": "firmwareVersions",
"ccVersion": 2,
"metadata": {
"type": "any",
"readable": true,
"writeable": false,
"label": "Z-Wave chip firmware versions"
},
"value": [
"1.12"
]
},
{
"endpoint": 0,
"commandClass": 134,
"commandClassName": "Version",
"property": "hardwareVersion",
"propertyName": "hardwareVersion",
"ccVersion": 2,
"metadata": {
"type": "any",
"readable": true,
"writeable": false,
"label": "Z-Wave chip hardware version"
}
}
]
}