diff --git a/homeassistant/components/zwave_js/discovery.py b/homeassistant/components/zwave_js/discovery.py index 217a0493ce2..3a47706dcaf 100644 --- a/homeassistant/components/zwave_js/discovery.py +++ b/homeassistant/components/zwave_js/discovery.py @@ -2,9 +2,10 @@ from __future__ import annotations from collections.abc import Generator -from dataclasses import dataclass +from dataclasses import asdict, dataclass, field from typing import Any +from awesomeversion import AwesomeVersion from zwave_js_server.const import THERMOSTAT_CURRENT_TEMP_PROPERTY, CommandClass from zwave_js_server.model.device_class import DeviceClassItem from zwave_js_server.model.node import Node as ZwaveNode @@ -19,6 +20,33 @@ from .discovery_data_template import ( ) +class DataclassMustHaveAtLeastOne: + """A dataclass that must have at least one input parameter that is not None.""" + + def __post_init__(self) -> None: + """Post dataclass initialization.""" + if all(val is None for val in asdict(self).values()): + raise ValueError("At least one input parameter must not be None") + + +@dataclass +class FirmwareVersionRange(DataclassMustHaveAtLeastOne): + """Firmware version range dictionary.""" + + min: str | None = None + max: str | None = None + min_ver: AwesomeVersion | None = field(default=None, init=False) + max_ver: AwesomeVersion | None = field(default=None, init=False) + + def __post_init__(self) -> None: + """Post dataclass initialization.""" + super().__post_init__() + if self.min: + self.min_ver = AwesomeVersion(self.min) + if self.max: + self.max_ver = AwesomeVersion(self.max) + + @dataclass class ZwaveDiscoveryInfo: """Info discovered from (primary) ZWave Value to create entity.""" @@ -42,7 +70,7 @@ class ZwaveDiscoveryInfo: @dataclass -class ZWaveValueDiscoverySchema: +class ZWaveValueDiscoverySchema(DataclassMustHaveAtLeastOne): """Z-Wave Value discovery schema. The Z-Wave Value must match these conditions. @@ -89,6 +117,8 @@ class ZWaveDiscoverySchema: product_id: set[int] | None = None # [optional] the node's product_type must match ANY of these values product_type: set[int] | None = None + # [optional] the node's firmware_version must be within this range + firmware_version_range: FirmwareVersionRange | None = None # [optional] the node's firmware_version must match ANY of these values firmware_version: set[str] | None = None # [optional] the node's basic device class must match ANY of these values @@ -274,6 +304,42 @@ DISCOVERY_SCHEMAS = [ ZwaveValueID(2, CommandClass.CONFIGURATION, endpoint=0), ), ), + # Heatit Z-TRM2fx + ZWaveDiscoverySchema( + platform="climate", + hint="dynamic_current_temp", + manufacturer_id={0x019B}, + product_id={0x0202}, + product_type={0x0003}, + firmware_version_range=FirmwareVersionRange(min="3.0"), + primary_value=ZWaveValueDiscoverySchema( + command_class={CommandClass.THERMOSTAT_MODE}, + property={"mode"}, + type={"number"}, + ), + data_template=DynamicCurrentTempClimateDataTemplate( + { + # External Sensor + "A2": ZwaveValueID( + THERMOSTAT_CURRENT_TEMP_PROPERTY, + CommandClass.SENSOR_MULTILEVEL, + endpoint=2, + ), + "A2F": ZwaveValueID( + THERMOSTAT_CURRENT_TEMP_PROPERTY, + CommandClass.SENSOR_MULTILEVEL, + endpoint=2, + ), + # Floor sensor + "F": ZwaveValueID( + THERMOSTAT_CURRENT_TEMP_PROPERTY, + CommandClass.SENSOR_MULTILEVEL, + endpoint=3, + ), + }, + ZwaveValueID(2, CommandClass.CONFIGURATION, endpoint=0), + ), + ), # ====== START OF CONFIG PARAMETER SPECIFIC MAPPING SCHEMAS ======= # Door lock mode config parameter. Functionality equivalent to Notification CC # list sensors. @@ -541,6 +607,21 @@ def async_discover_values(node: ZwaveNode) -> Generator[ZwaveDiscoveryInfo, None ): continue + # check firmware_version_range + if schema.firmware_version_range is not None and ( + ( + schema.firmware_version_range.min is not None + and schema.firmware_version_range.min_ver + > AwesomeVersion(value.node.firmware_version) + ) + or ( + schema.firmware_version_range.max is not None + and schema.firmware_version_range.max_ver + < AwesomeVersion(value.node.firmware_version) + ) + ): + continue + # check firmware_version if ( schema.firmware_version is not None diff --git a/tests/components/zwave_js/conftest.py b/tests/components/zwave_js/conftest.py index e9078bcf467..14937b0ff2a 100644 --- a/tests/components/zwave_js/conftest.py +++ b/tests/components/zwave_js/conftest.py @@ -240,6 +240,12 @@ def climate_heatit_z_trm3_state_fixture(): return json.loads(load_fixture("zwave_js/climate_heatit_z_trm3_state.json")) +@pytest.fixture(name="climate_heatit_z_trm2fx_state", scope="session") +def climate_heatit_z_trm2fx_state_fixture(): + """Load the climate HEATIT Z-TRM2fx thermostat node state fixture data.""" + return json.loads(load_fixture("zwave_js/climate_heatit_z_trm2fx_state.json")) + + @pytest.fixture(name="nortek_thermostat_state", scope="session") def nortek_thermostat_state_fixture(): """Load the nortek thermostat node state fixture data.""" @@ -484,6 +490,14 @@ def climate_heatit_z_trm3_fixture(client, climate_heatit_z_trm3_state): return node +@pytest.fixture(name="climate_heatit_z_trm2fx") +def climate_heatit_z_trm2fx_fixture(client, climate_heatit_z_trm2fx_state): + """Mock a climate radio HEATIT Z-TRM2fx node.""" + node = Node(client, copy.deepcopy(climate_heatit_z_trm2fx_state)) + client.driver.controller.nodes[node.node_id] = node + return node + + @pytest.fixture(name="nortek_thermostat") def nortek_thermostat_fixture(client, nortek_thermostat_state): """Mock a nortek thermostat node.""" diff --git a/tests/components/zwave_js/test_climate.py b/tests/components/zwave_js/test_climate.py index cb84570158c..a1b86b14ebc 100644 --- a/tests/components/zwave_js/test_climate.py +++ b/tests/components/zwave_js/test_climate.py @@ -28,6 +28,7 @@ from homeassistant.components.climate.const import ( SERVICE_SET_PRESET_MODE, SERVICE_SET_TEMPERATURE, SUPPORT_FAN_MODE, + SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE_RANGE, ) @@ -436,8 +437,10 @@ async def test_setpoint_thermostat(hass, client, climate_danfoss_lc_13, integrat client.async_send_command_no_wait.reset_mock() -async def test_thermostat_heatit(hass, client, climate_heatit_z_trm3, integration): - """Test a thermostat v2 command class entity.""" +async def test_thermostat_heatit_z_trm3( + hass, client, climate_heatit_z_trm3, integration +): + """Test a heatit Z-TRM3 entity.""" node = climate_heatit_z_trm3 state = hass.states.get(CLIMATE_FLOOR_THERMOSTAT_ENTITY) @@ -501,6 +504,53 @@ async def test_thermostat_heatit(hass, client, climate_heatit_z_trm3, integratio assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 25.5 +async def test_thermostat_heatit_z_trm2fx( + hass, client, climate_heatit_z_trm2fx, integration +): + """Test a heatit Z-TRM2fx entity.""" + node = climate_heatit_z_trm2fx + state = hass.states.get(CLIMATE_FLOOR_THERMOSTAT_ENTITY) + + assert state + assert state.state == HVAC_MODE_HEAT + assert state.attributes[ATTR_HVAC_MODES] == [ + HVAC_MODE_OFF, + HVAC_MODE_HEAT, + HVAC_MODE_COOL, + ] + assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 28.8 + assert state.attributes[ATTR_TEMPERATURE] == 29 + assert ( + state.attributes[ATTR_SUPPORTED_FEATURES] + == SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE + ) + assert state.attributes[ATTR_MIN_TEMP] == 7 + assert state.attributes[ATTR_MAX_TEMP] == 35 + + # Try switching to external sensor + event = Event( + type="value updated", + data={ + "source": "node", + "event": "value updated", + "nodeId": 24, + "args": { + "commandClassName": "Configuration", + "commandClass": 112, + "endpoint": 0, + "property": 2, + "propertyName": "Sensor mode", + "newValue": 4, + "prevValue": 2, + }, + }, + ) + node.receive_event(event) + state = hass.states.get(CLIMATE_FLOOR_THERMOSTAT_ENTITY) + assert state + assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 0 + + async def test_thermostat_srt321_hrt4_zw(hass, client, srt321_hrt4_zw, integration): """Test a climate entity from a HRT4-ZW / SRT321 thermostat device. diff --git a/tests/components/zwave_js/test_discovery.py b/tests/components/zwave_js/test_discovery.py index cbc9d756292..8914019cd43 100644 --- a/tests/components/zwave_js/test_discovery.py +++ b/tests/components/zwave_js/test_discovery.py @@ -1,4 +1,11 @@ """Test discovery of entities for device-specific schemas for the Z-Wave JS integration.""" +import pytest + +from homeassistant.components.zwave_js.discovery import ( + FirmwareVersionRange, + ZWaveDiscoverySchema, + ZWaveValueDiscoverySchema, +) async def test_iblinds_v2(hass, client, iblinds_v2, integration): @@ -48,3 +55,13 @@ async def test_vision_security_zl7432( state = hass.states.get(entity_id) assert state assert state.attributes["assumed_state"] + + +async def test_firmware_version_range_exception(hass): + """Test FirmwareVersionRange exception.""" + with pytest.raises(ValueError): + ZWaveDiscoverySchema( + "test", + ZWaveValueDiscoverySchema(command_class=1), + firmware_version_range=FirmwareVersionRange(), + ) diff --git a/tests/fixtures/zwave_js/climate_heatit_z_trm2fx_state.json b/tests/fixtures/zwave_js/climate_heatit_z_trm2fx_state.json new file mode 100644 index 00000000000..2526e346a53 --- /dev/null +++ b/tests/fixtures/zwave_js/climate_heatit_z_trm2fx_state.json @@ -0,0 +1,1444 @@ +{ + "nodeId": 26, + "index": 0, + "installerIcon": 4608, + "userIcon": 4609, + "status": 4, + "ready": true, + "isListening": true, + "isRouting": true, + "isSecure": false, + "manufacturerId": 411, + "productId": 514, + "productType": 3, + "firmwareVersion": "3.6", + "zwavePlusVersion": 1, + "deviceConfig": { + "filename": "/usr/src/node_modules/@zwave-js/config/config/devices/0x019b/z-trm2fx_3.0.json", + "manufacturer": "ThermoFloor", + "manufacturerId": 411, + "label": "Z-TRM2fx", + "description": "Floor thermostat", + "devices": [ + { + "productType": 3, + "productId": 514 + } + ], + "firmwareVersion": { + "min": "3.0", + "max": "255.255" + }, + "paramInformation": { + "_map": {} + }, + "compat": { + "valueIdRegex": {}, + "skipConfigurationInfoQuery": true + }, + "isEmbedded": true + }, + "label": "Z-TRM2fx", + "neighbors": [6, 7, 8, 11, 12, 13, 14, 15, 16, 17, 19, 20, 24, 25], + "endpointCountIsDynamic": false, + "endpointsHaveIdenticalCapabilities": false, + "individualEndpointCount": 4, + "aggregatedEndpointCount": 0, + "interviewAttempts": 1, + "endpoints": [ + { + "nodeId": 26, + "index": 0, + "installerIcon": 4608, + "userIcon": 4609, + "deviceClass": { + "basic": { + "key": 4, + "label": "Routing Slave" + }, + "generic": { + "key": 8, + "label": "Thermostat" + }, + "specific": { + "key": 6, + "label": "General Thermostat V2" + }, + "mandatorySupportedCCs": [32, 114, 64, 67, 134], + "mandatoryControlledCCs": [] + } + }, + { + "nodeId": 26, + "index": 1, + "installerIcon": 4608, + "userIcon": 4609, + "deviceClass": { + "basic": { + "key": 4, + "label": "Routing Slave" + }, + "generic": { + "key": 8, + "label": "Thermostat" + }, + "specific": { + "key": 6, + "label": "General Thermostat V2" + }, + "mandatorySupportedCCs": [32, 114, 64, 67, 134], + "mandatoryControlledCCs": [] + } + }, + { + "nodeId": 26, + "index": 2, + "installerIcon": 3328, + "userIcon": 3329, + "deviceClass": { + "basic": { + "key": 4, + "label": "Routing Slave" + }, + "generic": { + "key": 33, + "label": "Multilevel Sensor" + }, + "specific": { + "key": 1, + "label": "Routing Multilevel Sensor" + }, + "mandatorySupportedCCs": [32, 49], + "mandatoryControlledCCs": [] + } + }, + { + "nodeId": 26, + "index": 3, + "installerIcon": 3328, + "userIcon": 3329, + "deviceClass": { + "basic": { + "key": 4, + "label": "Routing Slave" + }, + "generic": { + "key": 33, + "label": "Multilevel Sensor" + }, + "specific": { + "key": 1, + "label": "Routing Multilevel Sensor" + }, + "mandatorySupportedCCs": [32, 49], + "mandatoryControlledCCs": [] + } + }, + { + "nodeId": 26, + "index": 4, + "installerIcon": 1792, + "userIcon": 1793, + "deviceClass": { + "basic": { + "key": 4, + "label": "Routing Slave" + }, + "generic": { + "key": 16, + "label": "Binary Switch" + }, + "specific": { + "key": 1, + "label": "Binary Power Switch" + }, + "mandatorySupportedCCs": [32, 37, 39], + "mandatoryControlledCCs": [] + } + } + ], + "values": [ + { + "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": 411 + }, + { + "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": 3 + }, + { + "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": 514 + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "libraryType", + "propertyName": "libraryType", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": false, + "label": "Library type" + }, + "value": 3 + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "protocolVersion", + "propertyName": "protocolVersion", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": false, + "label": "Z-Wave protocol version" + }, + "value": "5.3" + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "firmwareVersions", + "propertyName": "firmwareVersions", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": false, + "label": "Z-Wave chip firmware versions" + }, + "value": ["3.6"] + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "hardwareVersion", + "propertyName": "hardwareVersion", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": false, + "label": "Z-Wave chip hardware version" + } + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "sdkVersion", + "propertyName": "sdkVersion", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": "6.71.3" + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "applicationFrameworkAPIVersion", + "propertyName": "applicationFrameworkAPIVersion", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": "3.1.1" + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "applicationFrameworkBuildNumber", + "propertyName": "applicationFrameworkBuildNumber", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": 52445 + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "hostInterfaceVersion", + "propertyName": "hostInterfaceVersion", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": "unused" + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "hostInterfaceBuildNumber", + "propertyName": "hostInterfaceBuildNumber", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": 0 + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "zWaveProtocolVersion", + "propertyName": "zWaveProtocolVersion", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": "5.3.0" + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "zWaveProtocolBuildNumber", + "propertyName": "zWaveProtocolBuildNumber", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": 43 + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "applicationVersion", + "propertyName": "applicationVersion", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": "unused" + }, + { + "endpoint": 0, + "commandClass": 134, + "commandClassName": "Version", + "property": "applicationBuildNumber", + "propertyName": "applicationBuildNumber", + "ccVersion": 3, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": 0 + }, + { + "endpoint": 0, + "commandClass": 96, + "commandClassName": "Multi Channel", + "property": "endpointIndizes", + "propertyName": "endpointIndizes", + "ccVersion": 4, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + }, + "value": [1, 2, 3, 4] + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 1, + "propertyName": "Operation mode", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Operation mode", + "default": 0, + "min": 0, + "max": 11, + "states": { + "0": "Off. (default)", + "1": "Heating mode", + "2": "Cooling mode (not implemented)", + "11": "Energy saving heating mode" + }, + "valueSize": 1, + "format": 0, + "allowManualEntry": false, + "isFromConfig": true + }, + "value": 1 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 2, + "propertyName": "Sensor mode", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Sensor mode", + "default": 0, + "min": 0, + "max": 4, + "states": { + "0": "F-mode, floor sensor mode", + "3": "A2-mode, external room sensor mode", + "4": "A2F-mode, external sensor with floor limitation" + }, + "valueSize": 1, + "format": 0, + "allowManualEntry": false, + "isFromConfig": true + }, + "value": 0 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 3, + "propertyName": "Floor sensor type", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Floor sensor type", + "default": 0, + "min": 0, + "max": 5, + "states": { + "0": "10K-NTC (default)", + "1": "12K-NTC", + "2": "15K-NTC", + "3": "22K-NTC", + "4": "33K-NTC", + "5": "47K-NTC" + }, + "valueSize": 1, + "format": 0, + "allowManualEntry": false, + "isFromConfig": true + }, + "value": 0 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 4, + "propertyName": "Temperature control hysteresis (DIFF I)", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Temperature control hysteresis (DIFF I)", + "default": 5, + "min": 3, + "max": 30, + "valueSize": 1, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 5 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 5, + "propertyName": "Floor minimum temperature limit (FLo)", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Floor minimum temperature limit (FLo)", + "default": 50, + "min": 50, + "max": 400, + "unit": "oC", + "valueSize": 2, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 50 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 6, + "propertyName": "Floor maximum temperature (FHi)", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Floor maximum temperature (FHi)", + "default": 400, + "min": 50, + "max": 400, + "unit": "oC", + "valueSize": 2, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 400 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 7, + "propertyName": "Air (A2) minimum temperature limit (ALo)", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Air (A2) minimum temperature limit (ALo)", + "default": 50, + "min": 50, + "max": 400, + "unit": "oC", + "valueSize": 2, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 50 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 8, + "propertyName": "Air (A2) maximum temperature limit (AHi)", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Air (A2) maximum temperature limit (AHi)", + "default": 400, + "min": 50, + "max": 400, + "unit": "oC", + "valueSize": 2, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 400 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 9, + "propertyName": "Heating mode setpoint (CO)", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Heating mode setpoint (CO)", + "default": 210, + "min": 50, + "max": 400, + "unit": "oC", + "valueSize": 2, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 290 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 10, + "propertyName": "Energy saving mode setpoint (ECO)", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Energy saving mode setpoint (ECO)", + "default": 180, + "min": 50, + "max": 400, + "unit": "oC", + "valueSize": 2, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 250 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 11, + "propertyName": "Cooling setpoint (COOL)", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Cooling setpoint (COOL)", + "default": 210, + "min": 50, + "max": 400, + "unit": "oC", + "valueSize": 2, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 200 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 12, + "propertyName": "Floor sensor calibration", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Floor sensor calibration", + "default": 0, + "min": -40, + "max": 40, + "unit": "oC", + "valueSize": 1, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 0 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 13, + "propertyName": "External sensor calibration", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "External sensor calibration", + "default": 0, + "min": -40, + "max": 40, + "unit": "oC", + "valueSize": 1, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 0 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 14, + "propertyName": "Temperature display", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Temperature display", + "default": 0, + "min": 0, + "max": 1, + "states": { + "0": "Display setpoint temperature (default)", + "1": "Display measured temperature" + }, + "valueSize": 1, + "format": 0, + "allowManualEntry": false, + "isFromConfig": true + }, + "value": 0 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 15, + "propertyName": "Button brightness - dimmed state", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Button brightness - dimmed state", + "default": 50, + "min": 0, + "max": 100, + "unit": "%", + "valueSize": 1, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 1 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 16, + "propertyName": "Button brightness - active state", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Button brightness - active state", + "default": 100, + "min": 0, + "max": 100, + "unit": "%", + "valueSize": 1, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 100 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 17, + "propertyName": "Display brightness - dimmed state", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Display brightness - dimmed state", + "default": 50, + "min": 0, + "max": 100, + "unit": "%", + "valueSize": 1, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 1 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 18, + "propertyName": "Display brightness - active state", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Display brightness - active state", + "default": 100, + "min": 0, + "max": 100, + "unit": "%", + "valueSize": 1, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 100 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 19, + "propertyName": "Temperature report interval", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Temperature report interval", + "default": 60, + "min": 0, + "max": 32767, + "unit": "seconds", + "valueSize": 2, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 60 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 20, + "propertyName": "Temperature report hysteresis", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Temperature report hysteresis", + "default": 10, + "min": 1, + "max": 100, + "unit": "oC", + "valueSize": 1, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 10 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 21, + "propertyName": "Meter report interval", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Meter report interval", + "default": 60, + "min": 0, + "max": 32767, + "unit": "seconds", + "valueSize": 2, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 60 + }, + { + "endpoint": 0, + "commandClass": 112, + "commandClassName": "Configuration", + "property": 22, + "propertyName": "Meter report delta value", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Meter report delta value", + "default": 10, + "min": 0, + "max": 127, + "unit": "kWh/10", + "valueSize": 1, + "format": 0, + "allowManualEntry": true, + "isFromConfig": true + }, + "value": 10 + }, + { + "endpoint": 1, + "commandClass": 114, + "commandClassName": "Manufacturer Specific", + "property": "manufacturerId", + "propertyName": "manufacturerId", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Manufacturer ID", + "min": 0, + "max": 65535 + } + }, + { + "endpoint": 1, + "commandClass": 114, + "commandClassName": "Manufacturer Specific", + "property": "productType", + "propertyName": "productType", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Product type", + "min": 0, + "max": 65535 + } + }, + { + "endpoint": 1, + "commandClass": 114, + "commandClassName": "Manufacturer Specific", + "property": "productId", + "propertyName": "productId", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Product ID", + "min": 0, + "max": 65535 + } + }, + { + "endpoint": 1, + "commandClass": 64, + "commandClassName": "Thermostat Mode", + "property": "mode", + "propertyName": "mode", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Thermostat mode", + "min": 0, + "max": 255, + "states": { + "0": "Off", + "1": "Heat", + "2": "Cool", + "11": "Energy heat" + } + }, + "value": 1 + }, + { + "endpoint": 1, + "commandClass": 64, + "commandClassName": "Thermostat Mode", + "property": "manufacturerData", + "propertyName": "manufacturerData", + "ccVersion": 0, + "metadata": { + "type": "any", + "readable": true, + "writeable": true + } + }, + { + "endpoint": 1, + "commandClass": 67, + "commandClassName": "Thermostat Setpoint", + "property": "setpoint", + "propertyKey": 1, + "propertyName": "setpoint", + "propertyKeyName": "Heating", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "ccSpecific": { + "setpointType": 1 + }, + "unit": "\u00b0C" + }, + "value": 29 + }, + { + "endpoint": 1, + "commandClass": 67, + "commandClassName": "Thermostat Setpoint", + "property": "setpoint", + "propertyKey": 2, + "propertyName": "setpoint", + "propertyKeyName": "Cooling", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "ccSpecific": { + "setpointType": 2 + }, + "unit": "\u00b0C" + }, + "value": 20 + }, + { + "endpoint": 1, + "commandClass": 67, + "commandClassName": "Thermostat Setpoint", + "property": "setpoint", + "propertyKey": 11, + "propertyName": "setpoint", + "propertyKeyName": "Energy Save Heating", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "ccSpecific": { + "setpointType": 11 + }, + "unit": "\u00b0C" + }, + "value": 25 + }, + { + "endpoint": 1, + "commandClass": 134, + "commandClassName": "Version", + "property": "libraryType", + "propertyName": "libraryType", + "ccVersion": 0, + "metadata": { + "type": "any", + "readable": true, + "writeable": false, + "label": "Library type" + } + }, + { + "endpoint": 1, + "commandClass": 134, + "commandClassName": "Version", + "property": "protocolVersion", + "propertyName": "protocolVersion", + "ccVersion": 0, + "metadata": { + "type": "any", + "readable": true, + "writeable": false, + "label": "Z-Wave protocol version" + } + }, + { + "endpoint": 1, + "commandClass": 134, + "commandClassName": "Version", + "property": "firmwareVersions", + "propertyName": "firmwareVersions", + "ccVersion": 0, + "metadata": { + "type": "any", + "readable": true, + "writeable": false, + "label": "Z-Wave chip firmware versions" + } + }, + { + "endpoint": 2, + "commandClass": 32, + "commandClassName": "Basic", + "property": "currentValue", + "propertyName": "currentValue", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Current value", + "min": 0, + "max": 99 + }, + "value": 0 + }, + { + "endpoint": 2, + "commandClass": 32, + "commandClassName": "Basic", + "property": "targetValue", + "propertyName": "targetValue", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Target value", + "min": 0, + "max": 99 + } + }, + { + "endpoint": 2, + "commandClass": 49, + "commandClassName": "Multilevel Sensor", + "property": "Air temperature", + "propertyName": "Air temperature", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Air temperature", + "ccSpecific": { + "sensorType": 1, + "scale": 0 + }, + "unit": "\u00b0C" + }, + "value": 0 + }, + { + "endpoint": 3, + "commandClass": 32, + "commandClassName": "Basic", + "property": "currentValue", + "propertyName": "currentValue", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Current value", + "min": 0, + "max": 99 + }, + "value": 0 + }, + { + "endpoint": 3, + "commandClass": 32, + "commandClassName": "Basic", + "property": "targetValue", + "propertyName": "targetValue", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": true, + "label": "Target value", + "min": 0, + "max": 99 + } + }, + { + "endpoint": 3, + "commandClass": 49, + "commandClassName": "Multilevel Sensor", + "property": "Air temperature", + "propertyName": "Air temperature", + "ccVersion": 0, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Air temperature", + "ccSpecific": { + "sensorType": 1, + "scale": 0 + }, + "unit": "\u00b0C" + }, + "value": 28.8 + }, + { + "endpoint": 4, + "commandClass": 37, + "commandClassName": "Binary Switch", + "property": "currentValue", + "propertyName": "currentValue", + "ccVersion": 0, + "metadata": { + "type": "boolean", + "readable": true, + "writeable": false, + "label": "Current value" + }, + "value": false + }, + { + "endpoint": 4, + "commandClass": 37, + "commandClassName": "Binary Switch", + "property": "targetValue", + "propertyName": "targetValue", + "ccVersion": 0, + "metadata": { + "type": "boolean", + "readable": true, + "writeable": true, + "label": "Target value" + } + }, + { + "endpoint": 4, + "commandClass": 50, + "commandClassName": "Meter", + "property": "value", + "propertyKey": 65537, + "propertyName": "value", + "propertyKeyName": "Electric_kWh_Consumed", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Electric Consumed [kWh]", + "ccSpecific": { + "meterType": 1, + "rateType": 1, + "scale": 0 + }, + "unit": "kWh" + }, + "value": 795.7 + }, + { + "endpoint": 4, + "commandClass": 50, + "commandClassName": "Meter", + "property": "value", + "propertyKey": 66049, + "propertyName": "value", + "propertyKeyName": "Electric_W_Consumed", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Electric Consumed [W]", + "ccSpecific": { + "meterType": 1, + "rateType": 1, + "scale": 2 + }, + "unit": "W" + }, + "value": 493.57 + }, + { + "endpoint": 4, + "commandClass": 50, + "commandClassName": "Meter", + "property": "value", + "propertyKey": 66561, + "propertyName": "value", + "propertyKeyName": "Electric_V_Consumed", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": true, + "writeable": false, + "label": "Electric Consumed [V]", + "ccSpecific": { + "meterType": 1, + "rateType": 1, + "scale": 4 + }, + "unit": "V" + }, + "value": 237.1 + } + ], + "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": 8, + "label": "Thermostat" + }, + "specific": { + "key": 6, + "label": "General Thermostat V2" + }, + "mandatorySupportedCCs": [32, 114, 64, 67, 134], + "mandatoryControlledCCs": [] + }, + "commandClasses": [ + { + "id": 114, + "name": "Manufacturer Specific", + "version": 2, + "isSecure": false + }, + { + "id": 64, + "name": "Thermostat Mode", + "version": 3, + "isSecure": false + }, + { + "id": 67, + "name": "Thermostat Setpoint", + "version": 3, + "isSecure": false + }, + { + "id": 134, + "name": "Version", + "version": 3, + "isSecure": false + }, + { + "id": 94, + "name": "Z-Wave Plus Info", + "version": 2, + "isSecure": false + }, + { + "id": 133, + "name": "Association", + "version": 2, + "isSecure": false + }, + { + "id": 89, + "name": "Association Group Information", + "version": 1, + "isSecure": false + }, + { + "id": 142, + "name": "Multi Channel Association", + "version": 3, + "isSecure": false + }, + { + "id": 96, + "name": "Multi Channel", + "version": 4, + "isSecure": false + }, + { + "id": 90, + "name": "Device Reset Locally", + "version": 1, + "isSecure": false + }, + { + "id": 152, + "name": "Security", + "version": 1, + "isSecure": true + }, + { + "id": 108, + "name": "Supervision", + "version": 1, + "isSecure": false + }, + { + "id": 112, + "name": "Configuration", + "version": 3, + "isSecure": false + }, + { + "id": 122, + "name": "Firmware Update Meta Data", + "version": 4, + "isSecure": false + }, + { + "id": 50, + "name": "Meter", + "version": 3, + "isSecure": false + } + ], + "interviewStage": "Complete" +}