Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
405 changes: 405 additions & 0 deletions homeassistant/components/zwave_mqtt/binary_sensor.py

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion homeassistant/components/zwave_mqtt/const.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"""Constants for the zwave_mqtt integration."""
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN

DOMAIN = "zwave_mqtt"
DATA_UNSUBSCRIBE = "unsubscribe"
PLATFORMS = [LIGHT_DOMAIN, SENSOR_DOMAIN, SWITCH_DOMAIN]
PLATFORMS = [BINARY_SENSOR_DOMAIN, LIGHT_DOMAIN, SENSOR_DOMAIN, SWITCH_DOMAIN]

# MQTT Topics
TOPIC_OPENZWAVE = "OpenZWave"
Expand Down
30 changes: 27 additions & 3 deletions homeassistant/components/zwave_mqtt/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@
from . import const

DISCOVERY_SCHEMAS = (
{ # Binary sensors
const.DISC_COMPONENT: "binary_sensor",
const.DISC_VALUES: {
const.DISC_PRIMARY: {
const.DISC_COMMAND_CLASS: CommandClass.SENSOR_BINARY,
const.DISC_TYPE: ValueType.BOOL,
const.DISC_GENRE: ValueGenre.USER,
},
"off_delay": {
const.DISC_COMMAND_CLASS: CommandClass.CONFIGURATION,
const.DISC_INDEX: 9,
const.DISC_OPTIONAL: True,
},
},
},
{ # Notification CommandClass translates to binary_sensor
const.DISC_COMPONENT: "binary_sensor",
const.DISC_VALUES: {
const.DISC_PRIMARY: {
const.DISC_COMMAND_CLASS: CommandClass.NOTIFICATION,
const.DISC_GENRE: ValueGenre.USER,
const.DISC_TYPE: (ValueType.BOOL, ValueType.LIST),
}
},
},
{ # Light
const.DISC_COMPONENT: "light",
const.DISC_GENERIC_DEVICE_CLASS: (
Expand Down Expand Up @@ -107,9 +132,8 @@ def check_node_schema(node, schema):

def check_value_schema(value, schema):
"""Check if the value matches the passed value schema."""
if (
const.DISC_COMMAND_CLASS in schema
and value.parent.command_class_id not in schema[const.DISC_COMMAND_CLASS]
if const.DISC_COMMAND_CLASS in schema and not eq_or_in(
value.parent.command_class_id, schema[const.DISC_COMMAND_CLASS]
):
return False
if const.DISC_TYPE in schema and not eq_or_in(value.type, schema[const.DISC_TYPE]):
Expand Down
24 changes: 24 additions & 0 deletions tests/components/zwave_mqtt/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,27 @@ async def sensor_msg_fixture(hass):
message = MQTTMessage(topic=sensor_json["topic"], payload=sensor_json["payload"])
message.encode()
return message


@pytest.fixture(name="binary_sensor_msg")
async def binary_sensor_msg_fixture(hass):
"""Return a mock MQTT msg with a binary_sensor change message."""
sensor_json = json.loads(
await hass.async_add_executor_job(load_fixture, "zwave_mqtt/binary_sensor.json")
)
message = MQTTMessage(topic=sensor_json["topic"], payload=sensor_json["payload"])
message.encode()
return message


@pytest.fixture(name="binary_sensor_alt_msg")
async def binary_sensor_alt_msg_fixture(hass):
"""Return a mock MQTT msg with a binary_sensor change message."""
sensor_json = json.loads(
await hass.async_add_executor_job(
load_fixture, "zwave_mqtt/binary_sensor_alt.json"
)
)
message = MQTTMessage(topic=sensor_json["topic"], payload=sensor_json["payload"])
message.encode()
return message
66 changes: 66 additions & 0 deletions tests/components/zwave_mqtt/test_binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Test Z-Wave Sensors."""
from homeassistant.components.binary_sensor import (
DEVICE_CLASS_MOTION,
DOMAIN as BINARY_SENSOR_DOMAIN,
)
from homeassistant.components.zwave_mqtt.const import DOMAIN
from homeassistant.const import ATTR_DEVICE_CLASS

from .common import setup_zwave


async def test_binary_sensor(hass, generic_data, binary_sensor_msg):
"""Test setting up config entry."""
receive_msg = await setup_zwave(hass, fixture=generic_data)

# Test Legacy sensor (disabled by default)
registry = await hass.helpers.entity_registry.async_get_registry()
entity_id = "binary_sensor.trisensor_sensor"
state = hass.states.get(entity_id)
assert state is None
entry = registry.async_get(entity_id)
assert entry
assert entry.disabled
assert entry.disabled_by == "integration"

# Test enabling legacy entity
updated_entry = registry.async_update_entity(
entry.entity_id, **{"disabled_by": None}
)
assert updated_entry != entry
assert updated_entry.disabled is False
Comment thread
marcelveldt marked this conversation as resolved.

# Test Sensor for Notification CC
state = hass.states.get("binary_sensor.trisensor_home_security_motion_detected")
assert state
assert state.state == "off"
assert state.attributes[ATTR_DEVICE_CLASS] == DEVICE_CLASS_MOTION

# Test incoming state change
receive_msg(binary_sensor_msg)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.trisensor_home_security_motion_detected")
assert state.state == "on"


async def test_sensor_enabled(hass, generic_data, binary_sensor_alt_msg):
"""Test enabling a legacy binary_sensor."""

registry = await hass.helpers.entity_registry.async_get_registry()

entry = registry.async_get_or_create(
BINARY_SENSOR_DOMAIN,
DOMAIN,
"1-37-625737744",
suggested_object_id="trisensor_sensor_instance_1_sensor",
disabled_by=None,
)
assert entry.disabled is False

receive_msg = await setup_zwave(hass, fixture=generic_data)
receive_msg(binary_sensor_alt_msg)
await hass.async_block_till_done()

state = hass.states.get(entry.entity_id)
assert state is not None
assert state.state == "on"
38 changes: 38 additions & 0 deletions tests/fixtures/zwave_mqtt/binary_sensor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"topic": "OpenZWave/1/node/37/instance/1/commandclass/113/value/1970325463777300/",
"payload": {
"Label": "Home Security",
"Value": {
"List": [
{
"Value": 0,
"Label": "Clear"
},
{
"Value": 8,
"Label": "Motion Detected at Unknown Location"
}
],
"Selected": "Motion Detected at Unknown Location",
"Selected_id": 8
},
"Units": "",
"Min": 0,
"Max": 0,
"Type": "List",
"Instance": 1,
"CommandClass": "COMMAND_CLASS_NOTIFICATION",
"Index": 7,
"Node": 37,
"Genre": "User",
"Help": "Home Security Alerts",
"ValueIDKey": 1970325463777300,
"ReadOnly": false,
"WriteOnly": false,
"ValueSet": false,
"ValuePolled": false,
"ChangeVerified": false,
"Event": "valueAdded",
"TimeStamp": 1579566891
}
}
25 changes: 25 additions & 0 deletions tests/fixtures/zwave_mqtt/binary_sensor_alt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"topic": "OpenZWave/1/node/37/instance/1/commandclass/48/value/625737744/",
"payload": {
"Label": "Sensor",
"Value": true,
"Units": "",
"Min": 0,
"Max": 0,
"Type": "Bool",
"Instance": 1,
"CommandClass": "COMMAND_CLASS_SENSOR_BINARY",
"Index": 0,
"Node": 37,
"Genre": "User",
"Help": "Binary Sensor State",
"ValueIDKey": 625737744,
"ReadOnly": false,
"WriteOnly": false,
"ValueSet": false,
"ValuePolled": false,
"ChangeVerified": false,
"Event": "valueAdded",
"TimeStamp": 1579566891
}
}
4 changes: 2 additions & 2 deletions tests/fixtures/zwave_mqtt/generic_network_dump.csv
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ OpenZWave/1/node/36/instance/1/commandclass/112/value/56576470933045270/,{ "L
OpenZWave/1/node/36/instance/1/commandclass/112/value/70931694745288724/,{ "Label": "Lock/Unlock Configuration", "Value": { "List": [ { "Value": 0, "Label": "Unlock" }, { "Value": 1, "Label": "Lock" } ], "Selected": "Unlock" }, "Units": "", "Min": 0, "Max": 1, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 252, "Node": 36, "Genre": "Config", "Help": "Lock/ unlock all configuration parameters", "ValueIDKey": 70931694745288724, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/1/commandclass/112/value/71776119675420692/,{ "Label": "Reset To Factory Defaults", "Value": { "List": [ { "Value": 0, "Label": "Normal" }, { "Value": 1, "Label": "Reset to factory default setting" }, { "Value": 1431655765, "Label": "Reset to factory default setting and removed from the z-wave network" } ], "Selected": "Reset to factory default setting" }, "Units": "", "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_CONFIGURATION", "Index": 255, "Node": 36, "Genre": "Config", "Help": "Reset to factory defaults", "ValueIDKey": 71776119675420692, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/1/commandclass/113/,{ "Instance": 1, "CommandClassId": 113, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/1/commandclass/113/value/1407375493578772/,{ "Label": "Instance 1: Water", "Value": { "List": [ { "Value": 0, "Label": "Clear" }, { "Value": 2, "Label": "Water Leak at Unknown Location" } ], "Selected": "Clear" }, "Units": "", "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "Index": 5, "Node": 36, "Genre": "User", "Help": "Water Alerts", "ValueIDKey": 1407375493578772, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/1/commandclass/113/value/1407375493578772/,{ "Label": "Instance 1: Water", "Value": { "List": [ { "Value": 0, "Label": "Clear" }, { "Value": 2, "Label": "Water Leak at Unknown Location" } ], "Selected": "Clear", "Selected_id": 0 }, "Units": "", "Min": 0, "Max": 0, "Type": "List", "Instance": 1, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "Index": 5, "Node": 36, "Genre": "User", "Help": "Water Alerts", "ValueIDKey": 1407375493578772, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/1/commandclass/113/value/72057594647953425/,{ "Label": "Instance 1: Previous Event Cleared", "Value": 0, "Units": "", "Min": 0, "Max": 255, "Type": "Byte", "Instance": 1, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "Index": 256, "Node": 36, "Genre": "User", "Help": "Previous Event that was sent", "ValueIDKey": 72057594647953425, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/1/commandclass/114/,{ "Instance": 1, "CommandClassId": 114, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/1/commandclass/114/value/618430483/,{ "Label": "Loaded Config Revision", "Value": 10, "Units": "", "Min": -2147483648, "Max": 2147483647, "Type": "Int", "Instance": 1, "CommandClass": "COMMAND_CLASS_MANUFACTURER_SPECIFIC", "Index": 0, "Node": 36, "Genre": "System", "Help": "Revision of the Config file currently loaded", "ValueIDKey": 618430483, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
Expand Down Expand Up @@ -142,7 +142,7 @@ OpenZWave/1/node/36/instance/2/commandclass/94/value/618102817/,{ "Label": "I
OpenZWave/1/node/36/instance/2/commandclass/94/value/281475594813478/,{ "Label": "Instance 2: InstallerIcon", "Value": 3079, "Units": "", "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 2, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "Index": 1, "Node": 36, "Genre": "System", "Help": "Icon File to use for the Installer Application", "ValueIDKey": 281475594813478, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/2/commandclass/94/value/562950571524134/,{ "Label": "Instance 2: UserIcon", "Value": 3079, "Units": "", "Min": -32768, "Max": 32767, "Type": "Short", "Instance": 2, "CommandClass": "COMMAND_CLASS_ZWAVEPLUS_INFO", "Index": 2, "Node": 36, "Genre": "System", "Help": "Icon File to use for the User Application", "ValueIDKey": 562950571524134, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/2/commandclass/113/,{ "Instance": 2, "CommandClassId": 113, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/2/commandclass/113/value/1407375493578788/,{ "Label": "Instance 2: Water", "Value": { "List": [ { "Value": 0, "Label": "Clear" }, { "Value": 2, "Label": "Water Leak at Unknown Location" } ], "Selected": "Clear" }, "Units": "", "Min": 0, "Max": 0, "Type": "List", "Instance": 2, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "Index": 5, "Node": 36, "Genre": "User", "Help": "Water Alerts", "ValueIDKey": 1407375493578788, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/2/commandclass/113/value/1407375493578788/,{ "Label": "Instance 2: Water", "Value": { "List": [ { "Value": 0, "Label": "Clear" }, { "Value": 2, "Label": "Water Leak at Unknown Location" } ], "Selected": "Clear", "Selected_id": 0 }, "Units": "", "Min": 0, "Max": 0, "Type": "List", "Instance": 2, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "Index": 5, "Node": 36, "Genre": "User", "Help": "Water Alerts", "ValueIDKey": 1407375493578788, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/instance/2/commandclass/113/value/72057594647953441/,{ "Label": "Instance 2: Previous Event Cleared", "Value": 0, "Units": "", "Min": 0, "Max": 255, "Type": "Byte", "Instance": 2, "CommandClass": "COMMAND_CLASS_NOTIFICATION", "Index": 256, "Node": 36, "Genre": "User", "Help": "Previous Event that was sent", "ValueIDKey": 72057594647953441, "ReadOnly": false, "WriteOnly": false, "ValueSet": false, "ValuePolled": false, "ChangeVerified": false, "Event": "valueAdded", "TimeStamp": 1579566891}
OpenZWave/1/node/36/association/1/,{ "Name": "Lifeline", "Help": "", "MaxAssociations": 5, "Members": [ "1.1" ], "TimeStamp": 1579566891}
OpenZWave/1/node/36/association/2/,{ "Name": "Send the configuration parameter 0x88", "Help": "", "MaxAssociations": 5, "Members": [], "TimeStamp": 1579566891}
Expand Down