2017-02-13 16:54:11 +00:00
|
|
|
"""Tests for the Z-Wave init."""
|
|
|
|
import asyncio
|
2017-04-07 05:39:35 +00:00
|
|
|
from collections import OrderedDict
|
2017-05-13 03:27:44 +00:00
|
|
|
from datetime import datetime
|
2018-10-09 14:30:55 +00:00
|
|
|
from pytz import utc
|
2019-04-08 13:18:52 +00:00
|
|
|
import voluptuous as vol
|
2017-02-13 16:54:11 +00:00
|
|
|
|
2017-08-14 01:15:59 +00:00
|
|
|
import unittest
|
|
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
|
2017-02-13 16:54:11 +00:00
|
|
|
from homeassistant.bootstrap import async_setup_component
|
2017-04-07 13:17:23 +00:00
|
|
|
from homeassistant.const import ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_START
|
|
|
|
from homeassistant.components import zwave
|
2019-02-07 21:50:59 +00:00
|
|
|
from homeassistant.components.zwave.binary_sensor import get_device
|
2017-04-07 05:39:35 +00:00
|
|
|
from homeassistant.components.zwave import (
|
2017-05-26 04:11:02 +00:00
|
|
|
const, CONFIG_SCHEMA, CONF_DEVICE_CONFIG_GLOB, DATA_NETWORK)
|
2017-04-07 13:17:23 +00:00
|
|
|
from homeassistant.setup import setup_component
|
2018-05-12 21:45:36 +00:00
|
|
|
from tests.common import mock_registry
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
2017-05-13 03:27:44 +00:00
|
|
|
from tests.common import (
|
2018-03-17 03:27:05 +00:00
|
|
|
get_test_home_assistant, async_fire_time_changed, mock_coro)
|
2017-04-07 13:17:23 +00:00
|
|
|
from tests.mock.zwave import MockNetwork, MockNode, MockValue, MockEntityValues
|
2017-02-13 16:54:11 +00:00
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_valid_device_config(hass, mock_openzwave):
|
2017-02-23 21:06:28 +00:00
|
|
|
"""Test valid device config."""
|
2017-02-13 16:54:11 +00:00
|
|
|
device_config = {
|
|
|
|
'light.kitchen': {
|
|
|
|
'ignored': 'true'
|
|
|
|
}
|
|
|
|
}
|
2018-11-20 19:58:03 +00:00
|
|
|
result = await async_setup_component(hass, 'zwave', {
|
2017-02-13 16:54:11 +00:00
|
|
|
'zwave': {
|
|
|
|
'device_config': device_config
|
|
|
|
}})
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-02-13 16:54:11 +00:00
|
|
|
|
2017-02-23 21:06:28 +00:00
|
|
|
assert result
|
2017-02-13 16:54:11 +00:00
|
|
|
|
2017-02-23 21:06:28 +00:00
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_invalid_device_config(hass, mock_openzwave):
|
2017-02-23 21:06:28 +00:00
|
|
|
"""Test invalid device config."""
|
|
|
|
device_config = {
|
|
|
|
'light.kitchen': {
|
|
|
|
'some_ignored': 'true'
|
|
|
|
}
|
2017-02-13 16:54:11 +00:00
|
|
|
}
|
2018-11-20 19:58:03 +00:00
|
|
|
result = await async_setup_component(hass, 'zwave', {
|
2017-02-23 21:06:28 +00:00
|
|
|
'zwave': {
|
|
|
|
'device_config': device_config
|
|
|
|
}})
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-02-13 16:54:11 +00:00
|
|
|
|
2017-02-23 21:06:28 +00:00
|
|
|
assert not result
|
2017-04-07 05:39:35 +00:00
|
|
|
|
|
|
|
|
2017-04-10 20:11:39 +00:00
|
|
|
def test_config_access_error():
|
|
|
|
"""Test threading error accessing config values."""
|
|
|
|
node = MagicMock()
|
|
|
|
|
|
|
|
def side_effect():
|
|
|
|
raise RuntimeError
|
|
|
|
|
|
|
|
node.values.values.side_effect = side_effect
|
|
|
|
result = zwave.get_config_value(node, 1)
|
|
|
|
assert result is None
|
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_network_options(hass, mock_openzwave):
|
2017-05-13 03:27:44 +00:00
|
|
|
"""Test network options."""
|
2018-11-20 19:58:03 +00:00
|
|
|
result = await async_setup_component(hass, 'zwave', {
|
2017-05-13 03:27:44 +00:00
|
|
|
'zwave': {
|
|
|
|
'usb_path': 'mock_usb_path',
|
|
|
|
'config_path': 'mock_config_path',
|
|
|
|
}})
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:27:44 +00:00
|
|
|
|
|
|
|
assert result
|
|
|
|
|
2017-05-26 04:11:02 +00:00
|
|
|
network = hass.data[zwave.DATA_NETWORK]
|
2017-05-13 03:27:44 +00:00
|
|
|
assert network.options.device == 'mock_usb_path'
|
|
|
|
assert network.options.config_path == 'mock_config_path'
|
|
|
|
|
|
|
|
|
2019-04-08 13:18:52 +00:00
|
|
|
async def test_network_key_validation(hass, mock_openzwave):
|
|
|
|
"""Test network key validation."""
|
|
|
|
test_values = [
|
|
|
|
('0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, '
|
|
|
|
'0x0C, 0x0D, 0x0E, 0x0F, 0x10'),
|
|
|
|
('0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,'
|
|
|
|
'0x0E,0x0F,0x10'),
|
|
|
|
]
|
|
|
|
for value in test_values:
|
|
|
|
result = zwave.CONFIG_SCHEMA({'zwave': {'network_key': value}})
|
|
|
|
assert result['zwave']['network_key'] == value
|
|
|
|
|
|
|
|
|
|
|
|
async def test_erronous_network_key_fails_validation(hass, mock_openzwave):
|
|
|
|
"""Test failing erronous network key validation."""
|
|
|
|
test_values = [
|
|
|
|
('0x 01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, '
|
|
|
|
'0x0C, 0x0D, 0x0E, 0x0F, 0x10'),
|
|
|
|
('0X01,0X02,0X03,0X04,0X05,0X06,0X07,0X08,0X09,0X0A,0X0B,0X0C,0X0D,'
|
|
|
|
'0X0E,0X0F,0X10'),
|
|
|
|
'invalid',
|
|
|
|
'1234567',
|
|
|
|
1234567
|
|
|
|
]
|
|
|
|
for value in test_values:
|
|
|
|
with pytest.raises(vol.Invalid):
|
|
|
|
zwave.CONFIG_SCHEMA({'zwave': {'network_key': value}})
|
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_auto_heal_midnight(hass, mock_openzwave):
|
2017-05-13 03:27:44 +00:00
|
|
|
"""Test network auto-heal at midnight."""
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {
|
2017-05-13 03:27:44 +00:00
|
|
|
'zwave': {
|
|
|
|
'autoheal': True,
|
2018-10-09 14:30:55 +00:00
|
|
|
}})
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-10-09 14:30:55 +00:00
|
|
|
|
2017-05-26 04:11:02 +00:00
|
|
|
network = hass.data[zwave.DATA_NETWORK]
|
2017-05-13 03:27:44 +00:00
|
|
|
assert not network.heal.called
|
|
|
|
|
2018-10-09 14:30:55 +00:00
|
|
|
time = utc.localize(datetime(2017, 5, 6, 0, 0, 0))
|
2017-05-13 03:27:44 +00:00
|
|
|
async_fire_time_changed(hass, time)
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:27:44 +00:00
|
|
|
assert network.heal.called
|
|
|
|
assert len(network.heal.mock_calls) == 1
|
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_auto_heal_disabled(hass, mock_openzwave):
|
2017-05-13 03:27:44 +00:00
|
|
|
"""Test network auto-heal disabled."""
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {
|
2017-05-13 03:27:44 +00:00
|
|
|
'zwave': {
|
|
|
|
'autoheal': False,
|
2018-10-09 14:30:55 +00:00
|
|
|
}})
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-10-09 14:30:55 +00:00
|
|
|
|
2017-05-26 04:11:02 +00:00
|
|
|
network = hass.data[zwave.DATA_NETWORK]
|
2017-05-13 03:27:44 +00:00
|
|
|
assert not network.heal.called
|
|
|
|
|
2018-10-09 14:30:55 +00:00
|
|
|
time = utc.localize(datetime(2017, 5, 6, 0, 0, 0))
|
2017-05-13 03:27:44 +00:00
|
|
|
async_fire_time_changed(hass, time)
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:27:44 +00:00
|
|
|
assert not network.heal.called
|
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_setup_platform(hass, mock_openzwave):
|
2017-04-10 20:11:39 +00:00
|
|
|
"""Test invalid device config."""
|
|
|
|
mock_device = MagicMock()
|
2017-05-26 04:11:02 +00:00
|
|
|
hass.data[DATA_NETWORK] = MagicMock()
|
|
|
|
hass.data[zwave.DATA_DEVICES] = {456: mock_device}
|
2018-08-24 14:37:30 +00:00
|
|
|
async_add_entities = MagicMock()
|
2017-04-10 20:11:39 +00:00
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
result = await zwave.async_setup_platform(
|
2018-08-24 14:37:30 +00:00
|
|
|
hass, None, async_add_entities, None)
|
2017-04-10 20:11:39 +00:00
|
|
|
assert not result
|
2018-08-24 14:37:30 +00:00
|
|
|
assert not async_add_entities.called
|
2017-04-10 20:11:39 +00:00
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
result = await zwave.async_setup_platform(
|
2018-08-24 14:37:30 +00:00
|
|
|
hass, None, async_add_entities, {const.DISCOVERY_DEVICE: 123})
|
2017-04-10 20:11:39 +00:00
|
|
|
assert not result
|
2018-08-24 14:37:30 +00:00
|
|
|
assert not async_add_entities.called
|
2017-04-10 20:11:39 +00:00
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
result = await zwave.async_setup_platform(
|
2018-08-24 14:37:30 +00:00
|
|
|
hass, None, async_add_entities, {const.DISCOVERY_DEVICE: 456})
|
2017-04-10 20:11:39 +00:00
|
|
|
assert result
|
2018-08-24 14:37:30 +00:00
|
|
|
assert async_add_entities.called
|
|
|
|
assert len(async_add_entities.mock_calls) == 1
|
|
|
|
assert async_add_entities.mock_calls[0][1][0] == [mock_device]
|
2017-04-10 20:11:39 +00:00
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_zwave_ready_wait(hass, mock_openzwave):
|
2017-04-10 20:11:39 +00:00
|
|
|
"""Test that zwave continues after waiting for network ready."""
|
|
|
|
# Initialize zwave
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {}})
|
|
|
|
await hass.async_block_till_done()
|
2017-04-10 20:11:39 +00:00
|
|
|
|
2018-01-24 08:27:58 +00:00
|
|
|
sleeps = []
|
|
|
|
|
|
|
|
def utcnow():
|
|
|
|
return datetime.fromtimestamp(len(sleeps))
|
|
|
|
|
|
|
|
asyncio_sleep = asyncio.sleep
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def sleep(duration, loop=None):
|
2018-01-24 08:27:58 +00:00
|
|
|
if duration > 0:
|
|
|
|
sleeps.append(duration)
|
2018-11-20 19:58:03 +00:00
|
|
|
await asyncio_sleep(0)
|
2018-01-24 08:27:58 +00:00
|
|
|
|
|
|
|
with patch('homeassistant.components.zwave.dt_util.utcnow', new=utcnow):
|
|
|
|
with patch('asyncio.sleep', new=sleep):
|
|
|
|
with patch.object(zwave, '_LOGGER') as mock_logger:
|
|
|
|
hass.data[DATA_NETWORK].state = MockNetwork.STATE_STARTED
|
|
|
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-01-24 08:27:58 +00:00
|
|
|
|
|
|
|
assert len(sleeps) == const.NETWORK_READY_WAIT_SECS
|
|
|
|
assert mock_logger.warning.called
|
|
|
|
assert len(mock_logger.warning.mock_calls) == 1
|
|
|
|
assert mock_logger.warning.mock_calls[0][1][1] == \
|
|
|
|
const.NETWORK_READY_WAIT_SECS
|
2017-04-10 20:11:39 +00:00
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_device_entity(hass, mock_openzwave):
|
2017-04-10 20:11:39 +00:00
|
|
|
"""Test device entity base class."""
|
|
|
|
node = MockNode(node_id='10', name='Mock Node')
|
|
|
|
value = MockValue(data=False, node=node, instance=2, object_id='11',
|
|
|
|
label='Sensor',
|
|
|
|
command_class=const.COMMAND_CLASS_SENSOR_BINARY)
|
|
|
|
power_value = MockValue(data=50.123456, node=node, precision=3,
|
|
|
|
command_class=const.COMMAND_CLASS_METER)
|
|
|
|
values = MockEntityValues(primary=value, power=power_value)
|
|
|
|
device = zwave.ZWaveDeviceEntity(values, 'zwave')
|
|
|
|
device.hass = hass
|
|
|
|
device.value_added()
|
|
|
|
device.update_properties()
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-04-10 20:11:39 +00:00
|
|
|
|
|
|
|
assert not device.should_poll
|
2018-01-30 09:39:39 +00:00
|
|
|
assert device.unique_id == "10-11"
|
2017-04-10 20:11:39 +00:00
|
|
|
assert device.name == 'Mock Node Sensor'
|
|
|
|
assert device.device_state_attributes[zwave.ATTR_POWER] == 50.123
|
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_node_discovery(hass, mock_openzwave):
|
2017-05-13 03:18:20 +00:00
|
|
|
"""Test discovery of a node."""
|
|
|
|
mock_receivers = []
|
|
|
|
|
|
|
|
def mock_connect(receiver, signal, *args, **kwargs):
|
|
|
|
if signal == MockNetwork.SIGNAL_NODE_ADDED:
|
|
|
|
mock_receivers.append(receiver)
|
|
|
|
|
|
|
|
with patch('pydispatch.dispatcher.connect', new=mock_connect):
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {}})
|
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:18:20 +00:00
|
|
|
|
|
|
|
assert len(mock_receivers) == 1
|
|
|
|
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
hass.async_add_job(mock_receivers[0], node)
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:18:20 +00:00
|
|
|
|
2019-02-05 10:12:09 +00:00
|
|
|
assert hass.states.get('zwave.mock_node').state == 'unknown'
|
2017-05-13 03:18:20 +00:00
|
|
|
|
|
|
|
|
2018-05-02 20:10:26 +00:00
|
|
|
async def test_unparsed_node_discovery(hass, mock_openzwave):
|
|
|
|
"""Test discovery of a node."""
|
|
|
|
mock_receivers = []
|
|
|
|
|
|
|
|
def mock_connect(receiver, signal, *args, **kwargs):
|
|
|
|
if signal == MockNetwork.SIGNAL_NODE_ADDED:
|
|
|
|
mock_receivers.append(receiver)
|
|
|
|
|
|
|
|
with patch('pydispatch.dispatcher.connect', new=mock_connect):
|
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {}})
|
2018-10-09 14:30:55 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-05-02 20:10:26 +00:00
|
|
|
|
|
|
|
assert len(mock_receivers) == 1
|
|
|
|
|
2018-05-29 01:49:38 +00:00
|
|
|
node = MockNode(
|
|
|
|
node_id=14, manufacturer_name=None, name=None, is_ready=False)
|
2018-05-02 20:10:26 +00:00
|
|
|
|
|
|
|
sleeps = []
|
|
|
|
|
|
|
|
def utcnow():
|
|
|
|
return datetime.fromtimestamp(len(sleeps))
|
|
|
|
|
|
|
|
asyncio_sleep = asyncio.sleep
|
|
|
|
|
2018-07-29 00:53:37 +00:00
|
|
|
async def sleep(duration, loop=None):
|
2018-05-02 20:10:26 +00:00
|
|
|
if duration > 0:
|
|
|
|
sleeps.append(duration)
|
2018-07-29 00:53:37 +00:00
|
|
|
await asyncio_sleep(0)
|
2018-05-02 20:10:26 +00:00
|
|
|
|
|
|
|
with patch('homeassistant.components.zwave.dt_util.utcnow', new=utcnow):
|
|
|
|
with patch('asyncio.sleep', new=sleep):
|
|
|
|
with patch.object(zwave, '_LOGGER') as mock_logger:
|
|
|
|
hass.async_add_job(mock_receivers[0], node)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
assert len(sleeps) == const.NODE_READY_WAIT_SECS
|
|
|
|
assert mock_logger.warning.called
|
|
|
|
assert len(mock_logger.warning.mock_calls) == 1
|
|
|
|
assert mock_logger.warning.mock_calls[0][1][1:] == \
|
|
|
|
(14, const.NODE_READY_WAIT_SECS)
|
2019-02-05 10:12:09 +00:00
|
|
|
assert hass.states.get('zwave.unknown_node_14').state == 'unknown'
|
2018-05-02 20:10:26 +00:00
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_node_ignored(hass, mock_openzwave):
|
2017-05-13 03:18:20 +00:00
|
|
|
"""Test discovery of a node."""
|
|
|
|
mock_receivers = []
|
|
|
|
|
|
|
|
def mock_connect(receiver, signal, *args, **kwargs):
|
|
|
|
if signal == MockNetwork.SIGNAL_NODE_ADDED:
|
|
|
|
mock_receivers.append(receiver)
|
|
|
|
|
|
|
|
with patch('pydispatch.dispatcher.connect', new=mock_connect):
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {
|
2017-05-13 03:18:20 +00:00
|
|
|
'device_config': {
|
2017-06-16 17:07:17 +00:00
|
|
|
'zwave.mock_node': {
|
2017-05-13 03:18:20 +00:00
|
|
|
'ignored': True,
|
|
|
|
}}}})
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:18:20 +00:00
|
|
|
|
|
|
|
assert len(mock_receivers) == 1
|
|
|
|
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
hass.async_add_job(mock_receivers[0], node)
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:18:20 +00:00
|
|
|
|
2017-06-16 17:07:17 +00:00
|
|
|
assert hass.states.get('zwave.mock_node') is None
|
2017-05-13 03:18:20 +00:00
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_value_discovery(hass, mock_openzwave):
|
2017-05-13 03:18:20 +00:00
|
|
|
"""Test discovery of a node."""
|
|
|
|
mock_receivers = []
|
|
|
|
|
|
|
|
def mock_connect(receiver, signal, *args, **kwargs):
|
|
|
|
if signal == MockNetwork.SIGNAL_VALUE_ADDED:
|
|
|
|
mock_receivers.append(receiver)
|
|
|
|
|
|
|
|
with patch('pydispatch.dispatcher.connect', new=mock_connect):
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {}})
|
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:18:20 +00:00
|
|
|
|
|
|
|
assert len(mock_receivers) == 1
|
|
|
|
|
|
|
|
node = MockNode(node_id=11, generic=const.GENERIC_TYPE_SENSOR_BINARY)
|
|
|
|
value = MockValue(data=False, node=node, index=12, instance=13,
|
|
|
|
command_class=const.COMMAND_CLASS_SENSOR_BINARY,
|
|
|
|
type=const.TYPE_BOOL, genre=const.GENRE_USER)
|
|
|
|
hass.async_add_job(mock_receivers[0], node, value)
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:18:20 +00:00
|
|
|
|
|
|
|
assert hass.states.get(
|
2019-02-05 10:12:09 +00:00
|
|
|
'binary_sensor.mock_node_mock_value').state == 'off'
|
2017-05-13 03:18:20 +00:00
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_value_discovery_existing_entity(hass, mock_openzwave):
|
2017-05-13 03:18:20 +00:00
|
|
|
"""Test discovery of a node."""
|
|
|
|
mock_receivers = []
|
|
|
|
|
|
|
|
def mock_connect(receiver, signal, *args, **kwargs):
|
|
|
|
if signal == MockNetwork.SIGNAL_VALUE_ADDED:
|
|
|
|
mock_receivers.append(receiver)
|
|
|
|
|
|
|
|
with patch('pydispatch.dispatcher.connect', new=mock_connect):
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {}})
|
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:18:20 +00:00
|
|
|
|
|
|
|
assert len(mock_receivers) == 1
|
|
|
|
|
|
|
|
node = MockNode(node_id=11, generic=const.GENERIC_TYPE_THERMOSTAT)
|
|
|
|
setpoint = MockValue(
|
|
|
|
data=22.0, node=node, index=12, instance=13,
|
|
|
|
command_class=const.COMMAND_CLASS_THERMOSTAT_SETPOINT,
|
|
|
|
genre=const.GENRE_USER, units='C')
|
|
|
|
hass.async_add_job(mock_receivers[0], node, setpoint)
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:18:20 +00:00
|
|
|
|
2017-06-16 17:07:17 +00:00
|
|
|
assert hass.states.get('climate.mock_node_mock_value').attributes[
|
2017-05-13 03:18:20 +00:00
|
|
|
'temperature'] == 22.0
|
2017-06-16 17:07:17 +00:00
|
|
|
assert hass.states.get('climate.mock_node_mock_value').attributes[
|
2017-05-13 03:18:20 +00:00
|
|
|
'current_temperature'] is None
|
|
|
|
|
|
|
|
def mock_update(self):
|
2018-03-11 19:32:12 +00:00
|
|
|
self.hass.add_job(self.async_update_ha_state)
|
2017-05-13 03:18:20 +00:00
|
|
|
|
|
|
|
with patch.object(zwave.node_entity.ZWaveBaseEntity,
|
|
|
|
'maybe_schedule_update', new=mock_update):
|
|
|
|
temperature = MockValue(
|
2017-06-14 12:41:20 +00:00
|
|
|
data=23.5, node=node, index=1, instance=13,
|
2017-05-13 03:18:20 +00:00
|
|
|
command_class=const.COMMAND_CLASS_SENSOR_MULTILEVEL,
|
2017-06-14 12:41:20 +00:00
|
|
|
genre=const.GENRE_USER, units='C')
|
2017-05-13 03:18:20 +00:00
|
|
|
hass.async_add_job(mock_receivers[0], node, temperature)
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 03:18:20 +00:00
|
|
|
|
2017-06-16 17:07:17 +00:00
|
|
|
assert hass.states.get('climate.mock_node_mock_value').attributes[
|
2017-05-13 03:18:20 +00:00
|
|
|
'temperature'] == 22.0
|
2017-06-16 17:07:17 +00:00
|
|
|
assert hass.states.get('climate.mock_node_mock_value').attributes[
|
2017-05-13 03:18:20 +00:00
|
|
|
'current_temperature'] == 23.5
|
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_power_schemes(hass, mock_openzwave):
|
2017-08-14 01:15:59 +00:00
|
|
|
"""Test power attribute."""
|
|
|
|
mock_receivers = []
|
|
|
|
|
|
|
|
def mock_connect(receiver, signal, *args, **kwargs):
|
|
|
|
if signal == MockNetwork.SIGNAL_VALUE_ADDED:
|
|
|
|
mock_receivers.append(receiver)
|
|
|
|
|
|
|
|
with patch('pydispatch.dispatcher.connect', new=mock_connect):
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {}})
|
|
|
|
await hass.async_block_till_done()
|
2017-08-14 01:15:59 +00:00
|
|
|
|
|
|
|
assert len(mock_receivers) == 1
|
|
|
|
|
|
|
|
node = MockNode(node_id=11, generic=const.GENERIC_TYPE_SWITCH_BINARY)
|
|
|
|
switch = MockValue(
|
|
|
|
data=True, node=node, index=12, instance=13,
|
|
|
|
command_class=const.COMMAND_CLASS_SWITCH_BINARY,
|
|
|
|
genre=const.GENRE_USER, type=const.TYPE_BOOL)
|
|
|
|
hass.async_add_job(mock_receivers[0], node, switch)
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-08-14 01:15:59 +00:00
|
|
|
|
|
|
|
assert hass.states.get('switch.mock_node_mock_value').state == 'on'
|
|
|
|
assert 'power_consumption' not in hass.states.get(
|
|
|
|
'switch.mock_node_mock_value').attributes
|
|
|
|
|
|
|
|
def mock_update(self):
|
2018-03-11 19:32:12 +00:00
|
|
|
self.hass.add_job(self.async_update_ha_state)
|
2017-08-14 01:15:59 +00:00
|
|
|
|
|
|
|
with patch.object(zwave.node_entity.ZWaveBaseEntity,
|
|
|
|
'maybe_schedule_update', new=mock_update):
|
|
|
|
power = MockValue(
|
|
|
|
data=23.5, node=node, index=const.INDEX_SENSOR_MULTILEVEL_POWER,
|
|
|
|
instance=13, command_class=const.COMMAND_CLASS_SENSOR_MULTILEVEL)
|
|
|
|
hass.async_add_job(mock_receivers[0], node, power)
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-08-14 01:15:59 +00:00
|
|
|
|
|
|
|
assert hass.states.get('switch.mock_node_mock_value').attributes[
|
|
|
|
'power_consumption'] == 23.5
|
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_network_ready(hass, mock_openzwave):
|
2017-05-13 06:06:32 +00:00
|
|
|
"""Test Node network ready event."""
|
|
|
|
mock_receivers = []
|
|
|
|
|
|
|
|
def mock_connect(receiver, signal, *args, **kwargs):
|
|
|
|
if signal == MockNetwork.SIGNAL_ALL_NODES_QUERIED:
|
|
|
|
mock_receivers.append(receiver)
|
|
|
|
|
|
|
|
with patch('pydispatch.dispatcher.connect', new=mock_connect):
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {}})
|
|
|
|
await hass.async_block_till_done()
|
2017-05-13 06:06:32 +00:00
|
|
|
|
|
|
|
assert len(mock_receivers) == 1
|
|
|
|
|
|
|
|
events = []
|
|
|
|
|
|
|
|
def listener(event):
|
|
|
|
events.append(event)
|
|
|
|
|
|
|
|
hass.bus.async_listen(const.EVENT_NETWORK_COMPLETE, listener)
|
|
|
|
|
|
|
|
hass.async_add_job(mock_receivers[0])
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 06:06:32 +00:00
|
|
|
|
|
|
|
assert len(events) == 1
|
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_network_complete(hass, mock_openzwave):
|
2017-05-13 06:06:32 +00:00
|
|
|
"""Test Node network complete event."""
|
|
|
|
mock_receivers = []
|
|
|
|
|
|
|
|
def mock_connect(receiver, signal, *args, **kwargs):
|
|
|
|
if signal == MockNetwork.SIGNAL_AWAKE_NODES_QUERIED:
|
|
|
|
mock_receivers.append(receiver)
|
|
|
|
|
|
|
|
with patch('pydispatch.dispatcher.connect', new=mock_connect):
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {}})
|
|
|
|
await hass.async_block_till_done()
|
2017-05-13 06:06:32 +00:00
|
|
|
|
|
|
|
assert len(mock_receivers) == 1
|
|
|
|
|
|
|
|
events = []
|
|
|
|
|
|
|
|
def listener(event):
|
|
|
|
events.append(event)
|
|
|
|
|
|
|
|
hass.bus.async_listen(const.EVENT_NETWORK_READY, listener)
|
|
|
|
|
|
|
|
hass.async_add_job(mock_receivers[0])
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2017-05-13 06:06:32 +00:00
|
|
|
|
|
|
|
assert len(events) == 1
|
|
|
|
|
|
|
|
|
2018-11-20 19:58:03 +00:00
|
|
|
async def test_network_complete_some_dead(hass, mock_openzwave):
|
2018-09-28 17:14:57 +00:00
|
|
|
"""Test Node network complete some dead event."""
|
|
|
|
mock_receivers = []
|
|
|
|
|
|
|
|
def mock_connect(receiver, signal, *args, **kwargs):
|
|
|
|
if signal == MockNetwork.SIGNAL_ALL_NODES_QUERIED_SOME_DEAD:
|
|
|
|
mock_receivers.append(receiver)
|
|
|
|
|
|
|
|
with patch('pydispatch.dispatcher.connect', new=mock_connect):
|
2018-11-20 19:58:03 +00:00
|
|
|
await async_setup_component(hass, 'zwave', {'zwave': {}})
|
|
|
|
await hass.async_block_till_done()
|
2018-09-28 17:14:57 +00:00
|
|
|
|
|
|
|
assert len(mock_receivers) == 1
|
|
|
|
|
|
|
|
events = []
|
|
|
|
|
|
|
|
def listener(event):
|
|
|
|
events.append(event)
|
|
|
|
|
|
|
|
hass.bus.async_listen(const.EVENT_NETWORK_COMPLETE_SOME_DEAD, listener)
|
|
|
|
|
|
|
|
hass.async_add_job(mock_receivers[0])
|
2018-11-20 19:58:03 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-09-28 17:14:57 +00:00
|
|
|
|
|
|
|
assert len(events) == 1
|
|
|
|
|
|
|
|
|
2017-04-08 13:34:59 +00:00
|
|
|
class TestZWaveDeviceEntityValues(unittest.TestCase):
|
|
|
|
"""Tests for the ZWaveDeviceEntityValues helper."""
|
|
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
def set_mock_openzwave(self, mock_openzwave):
|
|
|
|
"""Use the mock_openzwave fixture for this class."""
|
|
|
|
self.mock_openzwave = mock_openzwave
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
"""Initialize values for this testcase class."""
|
|
|
|
self.hass = get_test_home_assistant()
|
|
|
|
self.hass.start()
|
2018-05-12 21:45:36 +00:00
|
|
|
self.registry = mock_registry(self.hass)
|
2017-04-08 13:34:59 +00:00
|
|
|
|
2018-03-11 14:30:03 +00:00
|
|
|
setup_component(self.hass, 'zwave', {'zwave': {}})
|
2017-04-08 13:34:59 +00:00
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
self.node = MockNode()
|
|
|
|
self.mock_schema = {
|
|
|
|
const.DISC_COMPONENT: 'mock_component',
|
|
|
|
const.DISC_VALUES: {
|
|
|
|
const.DISC_PRIMARY: {
|
|
|
|
const.DISC_COMMAND_CLASS: ['mock_primary_class'],
|
|
|
|
},
|
|
|
|
'secondary': {
|
|
|
|
const.DISC_COMMAND_CLASS: ['mock_secondary_class'],
|
|
|
|
},
|
|
|
|
'optional': {
|
|
|
|
const.DISC_COMMAND_CLASS: ['mock_optional_class'],
|
|
|
|
const.DISC_OPTIONAL: True,
|
|
|
|
}}}
|
|
|
|
self.primary = MockValue(
|
2018-05-12 21:45:36 +00:00
|
|
|
command_class='mock_primary_class', node=self.node, value_id=1000)
|
2017-04-08 13:34:59 +00:00
|
|
|
self.secondary = MockValue(
|
|
|
|
command_class='mock_secondary_class', node=self.node)
|
|
|
|
self.duplicate_secondary = MockValue(
|
|
|
|
command_class='mock_secondary_class', node=self.node)
|
|
|
|
self.optional = MockValue(
|
|
|
|
command_class='mock_optional_class', node=self.node)
|
|
|
|
self.no_match_value = MockValue(
|
|
|
|
command_class='mock_bad_class', node=self.node)
|
|
|
|
|
2017-06-16 17:07:17 +00:00
|
|
|
self.entity_id = 'mock_component.mock_node_mock_value'
|
2018-03-11 14:30:03 +00:00
|
|
|
self.zwave_config = {'zwave': {}}
|
2017-04-08 13:34:59 +00:00
|
|
|
self.device_config = {self.entity_id: {}}
|
|
|
|
|
|
|
|
def tearDown(self): # pylint: disable=invalid-name
|
|
|
|
"""Stop everything that was started."""
|
|
|
|
self.hass.stop()
|
|
|
|
|
2019-04-12 16:22:56 +00:00
|
|
|
@patch.object(zwave, 'import_module')
|
2017-04-08 13:34:59 +00:00
|
|
|
@patch.object(zwave, 'discovery')
|
2019-04-12 16:22:56 +00:00
|
|
|
def test_entity_discovery(self, discovery, import_module):
|
2017-04-08 13:34:59 +00:00
|
|
|
"""Test the creation of a new entity."""
|
2018-03-17 03:27:05 +00:00
|
|
|
discovery.async_load_platform.return_value = mock_coro()
|
2017-06-16 17:07:17 +00:00
|
|
|
mock_platform = MagicMock()
|
2019-04-12 16:22:56 +00:00
|
|
|
import_module.return_value = mock_platform
|
2017-06-16 17:07:17 +00:00
|
|
|
mock_device = MagicMock()
|
|
|
|
mock_device.name = 'test_device'
|
|
|
|
mock_platform.get_device.return_value = mock_device
|
2017-04-08 13:34:59 +00:00
|
|
|
values = zwave.ZWaveDeviceEntityValues(
|
|
|
|
hass=self.hass,
|
|
|
|
schema=self.mock_schema,
|
|
|
|
primary_value=self.primary,
|
|
|
|
zwave_config=self.zwave_config,
|
|
|
|
device_config=self.device_config,
|
2018-05-12 21:45:36 +00:00
|
|
|
registry=self.registry
|
2017-04-08 13:34:59 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
assert values.primary is self.primary
|
|
|
|
assert len(list(values)) == 3
|
2018-10-24 10:10:05 +00:00
|
|
|
assert sorted(list(values), key=lambda a: id(a)) == \
|
|
|
|
sorted([self.primary, None, None], key=lambda a: id(a))
|
2017-04-08 13:34:59 +00:00
|
|
|
assert not discovery.async_load_platform.called
|
|
|
|
|
|
|
|
values.check_value(self.secondary)
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert values.secondary is self.secondary
|
|
|
|
assert len(list(values)) == 3
|
2018-10-24 10:10:05 +00:00
|
|
|
assert sorted(list(values), key=lambda a: id(a)) == \
|
|
|
|
sorted([self.primary, self.secondary, None], key=lambda a: id(a))
|
2017-04-08 13:34:59 +00:00
|
|
|
|
|
|
|
assert discovery.async_load_platform.called
|
2018-03-17 03:27:05 +00:00
|
|
|
assert len(discovery.async_load_platform.mock_calls) == 1
|
2017-04-08 13:34:59 +00:00
|
|
|
args = discovery.async_load_platform.mock_calls[0][1]
|
|
|
|
assert args[0] == self.hass
|
|
|
|
assert args[1] == 'mock_component'
|
|
|
|
assert args[2] == 'zwave'
|
2018-11-01 18:38:23 +00:00
|
|
|
assert args[3] == {const.DISCOVERY_DEVICE: mock_device.unique_id}
|
2017-04-08 13:34:59 +00:00
|
|
|
assert args[4] == self.zwave_config
|
|
|
|
|
|
|
|
discovery.async_load_platform.reset_mock()
|
|
|
|
values.check_value(self.optional)
|
|
|
|
values.check_value(self.duplicate_secondary)
|
|
|
|
values.check_value(self.no_match_value)
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert values.optional is self.optional
|
|
|
|
assert len(list(values)) == 3
|
2018-10-24 10:10:05 +00:00
|
|
|
assert sorted(list(values), key=lambda a: id(a)) == \
|
|
|
|
sorted([self.primary, self.secondary, self.optional],
|
|
|
|
key=lambda a: id(a))
|
2017-04-08 13:34:59 +00:00
|
|
|
assert not discovery.async_load_platform.called
|
|
|
|
|
|
|
|
assert values._entity.value_added.called
|
|
|
|
assert len(values._entity.value_added.mock_calls) == 1
|
|
|
|
assert values._entity.value_changed.called
|
|
|
|
assert len(values._entity.value_changed.mock_calls) == 1
|
|
|
|
|
2019-04-12 16:22:56 +00:00
|
|
|
@patch.object(zwave, 'import_module')
|
2017-04-08 13:34:59 +00:00
|
|
|
@patch.object(zwave, 'discovery')
|
2019-04-12 16:22:56 +00:00
|
|
|
def test_entity_existing_values(self, discovery, import_module):
|
2017-04-08 13:34:59 +00:00
|
|
|
"""Test the loading of already discovered values."""
|
2018-03-17 03:27:05 +00:00
|
|
|
discovery.async_load_platform.return_value = mock_coro()
|
2017-06-16 17:07:17 +00:00
|
|
|
mock_platform = MagicMock()
|
2019-04-12 16:22:56 +00:00
|
|
|
import_module.return_value = mock_platform
|
2017-06-16 17:07:17 +00:00
|
|
|
mock_device = MagicMock()
|
|
|
|
mock_device.name = 'test_device'
|
|
|
|
mock_platform.get_device.return_value = mock_device
|
2017-04-08 13:34:59 +00:00
|
|
|
self.node.values = {
|
|
|
|
self.primary.value_id: self.primary,
|
|
|
|
self.secondary.value_id: self.secondary,
|
|
|
|
self.optional.value_id: self.optional,
|
|
|
|
self.no_match_value.value_id: self.no_match_value,
|
|
|
|
}
|
|
|
|
|
|
|
|
values = zwave.ZWaveDeviceEntityValues(
|
|
|
|
hass=self.hass,
|
|
|
|
schema=self.mock_schema,
|
|
|
|
primary_value=self.primary,
|
|
|
|
zwave_config=self.zwave_config,
|
|
|
|
device_config=self.device_config,
|
2018-05-12 21:45:36 +00:00
|
|
|
registry=self.registry
|
2017-04-08 13:34:59 +00:00
|
|
|
)
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert values.primary is self.primary
|
|
|
|
assert values.secondary is self.secondary
|
|
|
|
assert values.optional is self.optional
|
|
|
|
assert len(list(values)) == 3
|
2018-10-24 10:10:05 +00:00
|
|
|
assert sorted(list(values), key=lambda a: id(a)) == \
|
|
|
|
sorted([self.primary, self.secondary, self.optional],
|
|
|
|
key=lambda a: id(a))
|
2017-04-08 13:34:59 +00:00
|
|
|
|
|
|
|
assert discovery.async_load_platform.called
|
2018-03-17 03:27:05 +00:00
|
|
|
assert len(discovery.async_load_platform.mock_calls) == 1
|
2017-04-08 13:34:59 +00:00
|
|
|
args = discovery.async_load_platform.mock_calls[0][1]
|
|
|
|
assert args[0] == self.hass
|
|
|
|
assert args[1] == 'mock_component'
|
|
|
|
assert args[2] == 'zwave'
|
2018-11-01 18:38:23 +00:00
|
|
|
assert args[3] == {const.DISCOVERY_DEVICE: mock_device.unique_id}
|
2017-04-08 13:34:59 +00:00
|
|
|
assert args[4] == self.zwave_config
|
|
|
|
assert not self.primary.enable_poll.called
|
|
|
|
|
2019-04-12 16:22:56 +00:00
|
|
|
@patch.object(zwave, 'import_module')
|
2017-04-08 13:34:59 +00:00
|
|
|
@patch.object(zwave, 'discovery')
|
2019-04-12 16:22:56 +00:00
|
|
|
def test_node_schema_mismatch(self, discovery, import_module):
|
2017-04-08 13:34:59 +00:00
|
|
|
"""Test node schema mismatch."""
|
|
|
|
self.node.generic = 'no_match'
|
|
|
|
self.node.values = {
|
|
|
|
self.primary.value_id: self.primary,
|
|
|
|
self.secondary.value_id: self.secondary,
|
|
|
|
}
|
|
|
|
self.mock_schema[const.DISC_GENERIC_DEVICE_CLASS] = ['generic_match']
|
|
|
|
values = zwave.ZWaveDeviceEntityValues(
|
|
|
|
hass=self.hass,
|
|
|
|
schema=self.mock_schema,
|
|
|
|
primary_value=self.primary,
|
|
|
|
zwave_config=self.zwave_config,
|
|
|
|
device_config=self.device_config,
|
2018-05-12 21:45:36 +00:00
|
|
|
registry=self.registry
|
2017-04-08 13:34:59 +00:00
|
|
|
)
|
|
|
|
values._check_entity_ready()
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert not discovery.async_load_platform.called
|
|
|
|
|
2019-04-12 16:22:56 +00:00
|
|
|
@patch.object(zwave, 'import_module')
|
2017-04-08 13:34:59 +00:00
|
|
|
@patch.object(zwave, 'discovery')
|
2019-04-12 16:22:56 +00:00
|
|
|
def test_entity_workaround_component(self, discovery, import_module):
|
2018-05-12 21:45:36 +00:00
|
|
|
"""Test component workaround."""
|
2018-03-17 03:27:05 +00:00
|
|
|
discovery.async_load_platform.return_value = mock_coro()
|
2017-06-16 17:07:17 +00:00
|
|
|
mock_platform = MagicMock()
|
2019-04-12 16:22:56 +00:00
|
|
|
import_module.return_value = mock_platform
|
2017-06-16 17:07:17 +00:00
|
|
|
mock_device = MagicMock()
|
|
|
|
mock_device.name = 'test_device'
|
|
|
|
mock_platform.get_device.return_value = mock_device
|
2017-04-08 13:34:59 +00:00
|
|
|
self.node.manufacturer_id = '010f'
|
|
|
|
self.node.product_type = '0b00'
|
|
|
|
self.primary.command_class = const.COMMAND_CLASS_SENSOR_ALARM
|
2017-06-16 17:07:17 +00:00
|
|
|
self.entity_id = 'binary_sensor.mock_node_mock_value'
|
2017-04-08 13:34:59 +00:00
|
|
|
self.device_config = {self.entity_id: {}}
|
|
|
|
|
|
|
|
self.mock_schema = {
|
|
|
|
const.DISC_COMPONENT: 'mock_component',
|
|
|
|
const.DISC_VALUES: {
|
|
|
|
const.DISC_PRIMARY: {
|
|
|
|
const.DISC_COMMAND_CLASS: [
|
|
|
|
const.COMMAND_CLASS_SWITCH_BINARY],
|
|
|
|
}}}
|
|
|
|
|
2018-10-16 12:58:25 +00:00
|
|
|
with patch.object(zwave, 'async_dispatcher_send') as \
|
|
|
|
mock_dispatch_send:
|
|
|
|
|
|
|
|
values = zwave.ZWaveDeviceEntityValues(
|
|
|
|
hass=self.hass,
|
|
|
|
schema=self.mock_schema,
|
|
|
|
primary_value=self.primary,
|
|
|
|
zwave_config=self.zwave_config,
|
|
|
|
device_config=self.device_config,
|
|
|
|
registry=self.registry
|
|
|
|
)
|
|
|
|
values._check_entity_ready()
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert mock_dispatch_send.called
|
|
|
|
assert len(mock_dispatch_send.mock_calls) == 1
|
|
|
|
args = mock_dispatch_send.mock_calls[0][1]
|
|
|
|
assert args[1] == 'zwave_new_binary_sensor'
|
2017-04-08 13:34:59 +00:00
|
|
|
|
2019-04-12 16:22:56 +00:00
|
|
|
@patch.object(zwave, 'import_module')
|
2017-04-08 13:34:59 +00:00
|
|
|
@patch.object(zwave, 'discovery')
|
2019-04-12 16:22:56 +00:00
|
|
|
def test_entity_workaround_ignore(self, discovery, import_module):
|
2017-04-08 13:34:59 +00:00
|
|
|
"""Test ignore workaround."""
|
|
|
|
self.node.manufacturer_id = '010f'
|
|
|
|
self.node.product_type = '0301'
|
|
|
|
self.primary.command_class = const.COMMAND_CLASS_SWITCH_BINARY
|
|
|
|
|
|
|
|
self.mock_schema = {
|
|
|
|
const.DISC_COMPONENT: 'mock_component',
|
|
|
|
const.DISC_VALUES: {
|
|
|
|
const.DISC_PRIMARY: {
|
|
|
|
const.DISC_COMMAND_CLASS: [
|
|
|
|
const.COMMAND_CLASS_SWITCH_BINARY],
|
|
|
|
}}}
|
|
|
|
|
|
|
|
values = zwave.ZWaveDeviceEntityValues(
|
|
|
|
hass=self.hass,
|
|
|
|
schema=self.mock_schema,
|
|
|
|
primary_value=self.primary,
|
|
|
|
zwave_config=self.zwave_config,
|
|
|
|
device_config=self.device_config,
|
2018-05-12 21:45:36 +00:00
|
|
|
registry=self.registry
|
2017-04-08 13:34:59 +00:00
|
|
|
)
|
|
|
|
values._check_entity_ready()
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert not discovery.async_load_platform.called
|
|
|
|
|
2019-04-12 16:22:56 +00:00
|
|
|
@patch.object(zwave, 'import_module')
|
2017-04-08 13:34:59 +00:00
|
|
|
@patch.object(zwave, 'discovery')
|
2019-04-12 16:22:56 +00:00
|
|
|
def test_entity_config_ignore(self, discovery, import_module):
|
2017-04-08 13:34:59 +00:00
|
|
|
"""Test ignore config."""
|
|
|
|
self.node.values = {
|
|
|
|
self.primary.value_id: self.primary,
|
|
|
|
self.secondary.value_id: self.secondary,
|
|
|
|
}
|
|
|
|
self.device_config = {self.entity_id: {
|
|
|
|
zwave.CONF_IGNORED: True
|
|
|
|
}}
|
|
|
|
values = zwave.ZWaveDeviceEntityValues(
|
|
|
|
hass=self.hass,
|
|
|
|
schema=self.mock_schema,
|
|
|
|
primary_value=self.primary,
|
|
|
|
zwave_config=self.zwave_config,
|
|
|
|
device_config=self.device_config,
|
2018-05-12 21:45:36 +00:00
|
|
|
registry=self.registry
|
2017-04-08 13:34:59 +00:00
|
|
|
)
|
|
|
|
values._check_entity_ready()
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert not discovery.async_load_platform.called
|
|
|
|
|
2019-04-12 16:22:56 +00:00
|
|
|
@patch.object(zwave, 'import_module')
|
2018-05-12 21:45:36 +00:00
|
|
|
@patch.object(zwave, 'discovery')
|
2019-04-12 16:22:56 +00:00
|
|
|
def test_entity_config_ignore_with_registry(self, discovery,
|
|
|
|
import_module):
|
2018-05-12 21:45:36 +00:00
|
|
|
"""Test ignore config.
|
|
|
|
|
|
|
|
The case when the device is in entity registry.
|
|
|
|
"""
|
|
|
|
self.node.values = {
|
|
|
|
self.primary.value_id: self.primary,
|
|
|
|
self.secondary.value_id: self.secondary,
|
|
|
|
}
|
|
|
|
self.device_config = {'mock_component.registry_id': {
|
|
|
|
zwave.CONF_IGNORED: True
|
|
|
|
}}
|
2018-09-25 08:16:30 +00:00
|
|
|
with patch.object(self.registry, 'async_schedule_save'):
|
|
|
|
self.registry.async_get_or_create(
|
|
|
|
'mock_component', zwave.DOMAIN, '567-1000',
|
|
|
|
suggested_object_id='registry_id')
|
|
|
|
|
2018-05-12 21:45:36 +00:00
|
|
|
zwave.ZWaveDeviceEntityValues(
|
|
|
|
hass=self.hass,
|
|
|
|
schema=self.mock_schema,
|
|
|
|
primary_value=self.primary,
|
|
|
|
zwave_config=self.zwave_config,
|
|
|
|
device_config=self.device_config,
|
|
|
|
registry=self.registry
|
|
|
|
)
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert not discovery.async_load_platform.called
|
|
|
|
|
2019-04-12 16:22:56 +00:00
|
|
|
@patch.object(zwave, 'import_module')
|
2017-04-08 13:34:59 +00:00
|
|
|
@patch.object(zwave, 'discovery')
|
2019-04-12 16:22:56 +00:00
|
|
|
def test_entity_platform_ignore(self, discovery, import_module):
|
2017-04-08 13:34:59 +00:00
|
|
|
"""Test platform ignore device."""
|
|
|
|
self.node.values = {
|
|
|
|
self.primary.value_id: self.primary,
|
|
|
|
self.secondary.value_id: self.secondary,
|
|
|
|
}
|
|
|
|
platform = MagicMock()
|
2019-04-12 16:22:56 +00:00
|
|
|
import_module.return_value = platform
|
2017-04-08 13:34:59 +00:00
|
|
|
platform.get_device.return_value = None
|
|
|
|
zwave.ZWaveDeviceEntityValues(
|
|
|
|
hass=self.hass,
|
|
|
|
schema=self.mock_schema,
|
|
|
|
primary_value=self.primary,
|
|
|
|
zwave_config=self.zwave_config,
|
|
|
|
device_config=self.device_config,
|
2018-05-12 21:45:36 +00:00
|
|
|
registry=self.registry
|
2017-04-08 13:34:59 +00:00
|
|
|
)
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert not discovery.async_load_platform.called
|
|
|
|
|
2019-04-12 16:22:56 +00:00
|
|
|
@patch.object(zwave, 'import_module')
|
2017-04-08 13:34:59 +00:00
|
|
|
@patch.object(zwave, 'discovery')
|
2019-04-12 16:22:56 +00:00
|
|
|
def test_config_polling_intensity(self, discovery, import_module):
|
2017-04-08 13:34:59 +00:00
|
|
|
"""Test polling intensity."""
|
2017-06-16 17:07:17 +00:00
|
|
|
mock_platform = MagicMock()
|
2019-04-12 16:22:56 +00:00
|
|
|
import_module.return_value = mock_platform
|
2017-06-16 17:07:17 +00:00
|
|
|
mock_device = MagicMock()
|
|
|
|
mock_device.name = 'test_device'
|
|
|
|
mock_platform.get_device.return_value = mock_device
|
2017-04-08 13:34:59 +00:00
|
|
|
self.node.values = {
|
|
|
|
self.primary.value_id: self.primary,
|
|
|
|
self.secondary.value_id: self.secondary,
|
|
|
|
}
|
|
|
|
self.device_config = {self.entity_id: {
|
|
|
|
zwave.CONF_POLLING_INTENSITY: 123,
|
|
|
|
}}
|
|
|
|
values = zwave.ZWaveDeviceEntityValues(
|
|
|
|
hass=self.hass,
|
|
|
|
schema=self.mock_schema,
|
|
|
|
primary_value=self.primary,
|
|
|
|
zwave_config=self.zwave_config,
|
|
|
|
device_config=self.device_config,
|
2018-05-12 21:45:36 +00:00
|
|
|
registry=self.registry
|
2017-04-08 13:34:59 +00:00
|
|
|
)
|
|
|
|
values._check_entity_ready()
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert discovery.async_load_platform.called
|
|
|
|
assert self.primary.enable_poll.called
|
|
|
|
assert len(self.primary.enable_poll.mock_calls) == 1
|
|
|
|
assert self.primary.enable_poll.mock_calls[0][1][0] == 123
|
|
|
|
|
|
|
|
|
2017-04-07 05:39:35 +00:00
|
|
|
class TestZwave(unittest.TestCase):
|
|
|
|
"""Test zwave init."""
|
|
|
|
|
|
|
|
def test_device_config_glob_is_ordered(self):
|
|
|
|
"""Test that device_config_glob preserves order."""
|
|
|
|
conf = CONFIG_SCHEMA(
|
|
|
|
{'zwave': {CONF_DEVICE_CONFIG_GLOB: OrderedDict()}})
|
2018-10-24 10:10:05 +00:00
|
|
|
assert isinstance(conf['zwave'][CONF_DEVICE_CONFIG_GLOB], OrderedDict)
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TestZWaveServices(unittest.TestCase):
|
|
|
|
"""Tests for zwave services."""
|
|
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
def set_mock_openzwave(self, mock_openzwave):
|
|
|
|
"""Use the mock_openzwave fixture for this class."""
|
|
|
|
self.mock_openzwave = mock_openzwave
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
"""Initialize values for this testcase class."""
|
|
|
|
self.hass = get_test_home_assistant()
|
|
|
|
self.hass.start()
|
|
|
|
|
|
|
|
# Initialize zwave
|
2018-03-11 14:30:03 +00:00
|
|
|
setup_component(self.hass, 'zwave', {'zwave': {}})
|
2017-04-07 13:17:23 +00:00
|
|
|
self.hass.block_till_done()
|
2017-05-26 04:11:02 +00:00
|
|
|
self.zwave_network = self.hass.data[DATA_NETWORK]
|
2017-04-12 17:09:29 +00:00
|
|
|
self.zwave_network.state = MockNetwork.STATE_READY
|
2017-04-07 13:17:23 +00:00
|
|
|
self.hass.bus.fire(EVENT_HOMEASSISTANT_START)
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
def tearDown(self): # pylint: disable=invalid-name
|
|
|
|
"""Stop everything that was started."""
|
2017-04-12 17:09:29 +00:00
|
|
|
self.hass.services.call('zwave', 'stop_network', {})
|
|
|
|
self.hass.block_till_done()
|
2017-04-07 13:17:23 +00:00
|
|
|
self.hass.stop()
|
|
|
|
|
|
|
|
def test_add_node(self):
|
|
|
|
"""Test zwave add_node service."""
|
|
|
|
self.hass.services.call('zwave', 'add_node', {})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
assert self.zwave_network.controller.add_node.called
|
|
|
|
assert len(self.zwave_network.controller
|
|
|
|
.add_node.mock_calls) == 1
|
|
|
|
assert len(self.zwave_network.controller
|
|
|
|
.add_node.mock_calls[0][1]) == 0
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_add_node_secure(self):
|
|
|
|
"""Test zwave add_node_secure service."""
|
|
|
|
self.hass.services.call('zwave', 'add_node_secure', {})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
assert self.zwave_network.controller.add_node.called
|
|
|
|
assert len(self.zwave_network.controller.add_node.mock_calls) == 1
|
|
|
|
assert (self.zwave_network.controller
|
|
|
|
.add_node.mock_calls[0][1][0] is True)
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_remove_node(self):
|
|
|
|
"""Test zwave remove_node service."""
|
|
|
|
self.hass.services.call('zwave', 'remove_node', {})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
assert self.zwave_network.controller.remove_node.called
|
|
|
|
assert len(self.zwave_network.controller.remove_node.mock_calls) == 1
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_cancel_command(self):
|
|
|
|
"""Test zwave cancel_command service."""
|
|
|
|
self.hass.services.call('zwave', 'cancel_command', {})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
assert self.zwave_network.controller.cancel_command.called
|
|
|
|
assert len(self.zwave_network.controller
|
|
|
|
.cancel_command.mock_calls) == 1
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_heal_network(self):
|
|
|
|
"""Test zwave heal_network service."""
|
|
|
|
self.hass.services.call('zwave', 'heal_network', {})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
assert self.zwave_network.heal.called
|
|
|
|
assert len(self.zwave_network.heal.mock_calls) == 1
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_soft_reset(self):
|
|
|
|
"""Test zwave soft_reset service."""
|
|
|
|
self.hass.services.call('zwave', 'soft_reset', {})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
assert self.zwave_network.controller.soft_reset.called
|
|
|
|
assert len(self.zwave_network.controller.soft_reset.mock_calls) == 1
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_test_network(self):
|
|
|
|
"""Test zwave test_network service."""
|
|
|
|
self.hass.services.call('zwave', 'test_network', {})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
assert self.zwave_network.test.called
|
|
|
|
assert len(self.zwave_network.test.mock_calls) == 1
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_stop_network(self):
|
|
|
|
"""Test zwave stop_network service."""
|
2017-04-10 20:11:39 +00:00
|
|
|
with patch.object(self.hass.bus, 'fire') as mock_fire:
|
|
|
|
self.hass.services.call('zwave', 'stop_network', {})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
assert self.zwave_network.stop.called
|
|
|
|
assert len(self.zwave_network.stop.mock_calls) == 1
|
2017-04-10 20:11:39 +00:00
|
|
|
assert mock_fire.called
|
2018-11-30 20:28:35 +00:00
|
|
|
assert len(mock_fire.mock_calls) == 1
|
2017-04-10 20:11:39 +00:00
|
|
|
assert mock_fire.mock_calls[0][1][0] == const.EVENT_NETWORK_STOP
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_rename_node(self):
|
|
|
|
"""Test zwave rename_node service."""
|
2017-04-12 17:09:29 +00:00
|
|
|
self.zwave_network.nodes = {11: MagicMock()}
|
2017-04-07 13:17:23 +00:00
|
|
|
self.hass.services.call('zwave', 'rename_node', {
|
|
|
|
const.ATTR_NODE_ID: 11,
|
|
|
|
const.ATTR_NAME: 'test_name',
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
assert self.zwave_network.nodes[11].name == 'test_name'
|
2017-04-07 13:17:23 +00:00
|
|
|
|
2017-06-03 06:03:00 +00:00
|
|
|
def test_rename_value(self):
|
|
|
|
"""Test zwave rename_value service."""
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
value = MockValue(index=12, value_id=123456, label="Old Label")
|
|
|
|
node.values = {123456: value}
|
|
|
|
self.zwave_network.nodes = {11: node}
|
|
|
|
|
|
|
|
assert value.label == "Old Label"
|
|
|
|
self.hass.services.call('zwave', 'rename_value', {
|
|
|
|
const.ATTR_NODE_ID: 11,
|
|
|
|
const.ATTR_VALUE_ID: 123456,
|
|
|
|
const.ATTR_NAME: "New Label",
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert value.label == "New Label"
|
|
|
|
|
2017-09-11 18:30:48 +00:00
|
|
|
def test_set_poll_intensity_enable(self):
|
2018-01-29 22:37:19 +00:00
|
|
|
"""Test zwave set_poll_intensity service, successful set."""
|
2017-09-11 18:30:48 +00:00
|
|
|
node = MockNode(node_id=14)
|
|
|
|
value = MockValue(index=12, value_id=123456, poll_intensity=0)
|
|
|
|
node.values = {123456: value}
|
|
|
|
self.zwave_network.nodes = {11: node}
|
|
|
|
|
|
|
|
assert value.poll_intensity == 0
|
|
|
|
self.hass.services.call('zwave', 'set_poll_intensity', {
|
|
|
|
const.ATTR_NODE_ID: 11,
|
|
|
|
const.ATTR_VALUE_ID: 123456,
|
|
|
|
const.ATTR_POLL_INTENSITY: 4,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
enable_poll = value.enable_poll
|
|
|
|
assert value.enable_poll.called
|
|
|
|
assert len(enable_poll.mock_calls) == 2
|
|
|
|
assert enable_poll.mock_calls[0][1][0] == 4
|
|
|
|
|
|
|
|
def test_set_poll_intensity_enable_failed(self):
|
|
|
|
"""Test zwave set_poll_intensity service, failed set."""
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
value = MockValue(index=12, value_id=123456, poll_intensity=0)
|
|
|
|
value.enable_poll.return_value = False
|
|
|
|
node.values = {123456: value}
|
|
|
|
self.zwave_network.nodes = {11: node}
|
|
|
|
|
|
|
|
assert value.poll_intensity == 0
|
|
|
|
self.hass.services.call('zwave', 'set_poll_intensity', {
|
|
|
|
const.ATTR_NODE_ID: 11,
|
|
|
|
const.ATTR_VALUE_ID: 123456,
|
|
|
|
const.ATTR_POLL_INTENSITY: 4,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
enable_poll = value.enable_poll
|
|
|
|
assert value.enable_poll.called
|
|
|
|
assert len(enable_poll.mock_calls) == 1
|
|
|
|
|
|
|
|
def test_set_poll_intensity_disable(self):
|
|
|
|
"""Test zwave set_poll_intensity service, successful disable."""
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
value = MockValue(index=12, value_id=123456, poll_intensity=4)
|
|
|
|
node.values = {123456: value}
|
|
|
|
self.zwave_network.nodes = {11: node}
|
|
|
|
|
|
|
|
assert value.poll_intensity == 4
|
|
|
|
self.hass.services.call('zwave', 'set_poll_intensity', {
|
|
|
|
const.ATTR_NODE_ID: 11,
|
|
|
|
const.ATTR_VALUE_ID: 123456,
|
|
|
|
const.ATTR_POLL_INTENSITY: 0,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
disable_poll = value.disable_poll
|
|
|
|
assert value.disable_poll.called
|
|
|
|
assert len(disable_poll.mock_calls) == 2
|
|
|
|
|
|
|
|
def test_set_poll_intensity_disable_failed(self):
|
|
|
|
"""Test zwave set_poll_intensity service, failed disable."""
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
value = MockValue(index=12, value_id=123456, poll_intensity=4)
|
|
|
|
value.disable_poll.return_value = False
|
|
|
|
node.values = {123456: value}
|
|
|
|
self.zwave_network.nodes = {11: node}
|
|
|
|
|
|
|
|
assert value.poll_intensity == 4
|
|
|
|
self.hass.services.call('zwave', 'set_poll_intensity', {
|
|
|
|
const.ATTR_NODE_ID: 11,
|
|
|
|
const.ATTR_VALUE_ID: 123456,
|
|
|
|
const.ATTR_POLL_INTENSITY: 0,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
disable_poll = value.disable_poll
|
|
|
|
assert value.disable_poll.called
|
|
|
|
assert len(disable_poll.mock_calls) == 1
|
|
|
|
|
2017-04-07 13:17:23 +00:00
|
|
|
def test_remove_failed_node(self):
|
|
|
|
"""Test zwave remove_failed_node service."""
|
|
|
|
self.hass.services.call('zwave', 'remove_failed_node', {
|
|
|
|
const.ATTR_NODE_ID: 12,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
remove_failed_node = self.zwave_network.controller.remove_failed_node
|
2017-04-07 13:17:23 +00:00
|
|
|
assert remove_failed_node.called
|
|
|
|
assert len(remove_failed_node.mock_calls) == 1
|
|
|
|
assert remove_failed_node.mock_calls[0][1][0] == 12
|
|
|
|
|
|
|
|
def test_replace_failed_node(self):
|
|
|
|
"""Test zwave replace_failed_node service."""
|
|
|
|
self.hass.services.call('zwave', 'replace_failed_node', {
|
|
|
|
const.ATTR_NODE_ID: 13,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-04-12 17:09:29 +00:00
|
|
|
replace_failed_node = self.zwave_network.controller.replace_failed_node
|
2017-04-07 13:17:23 +00:00
|
|
|
assert replace_failed_node.called
|
|
|
|
assert len(replace_failed_node.mock_calls) == 1
|
|
|
|
assert replace_failed_node.mock_calls[0][1][0] == 13
|
|
|
|
|
|
|
|
def test_set_config_parameter(self):
|
|
|
|
"""Test zwave set_config_parameter service."""
|
2019-04-15 21:24:20 +00:00
|
|
|
value_byte = MockValue(
|
2017-04-07 13:17:23 +00:00
|
|
|
index=12,
|
|
|
|
command_class=const.COMMAND_CLASS_CONFIGURATION,
|
2017-05-19 00:39:31 +00:00
|
|
|
type=const.TYPE_BYTE,
|
2017-04-07 13:17:23 +00:00
|
|
|
)
|
|
|
|
value_list = MockValue(
|
|
|
|
index=13,
|
|
|
|
command_class=const.COMMAND_CLASS_CONFIGURATION,
|
|
|
|
type=const.TYPE_LIST,
|
|
|
|
data_items=['item1', 'item2', 'item3'],
|
|
|
|
)
|
2019-04-15 21:24:20 +00:00
|
|
|
value_button = MockValue(
|
|
|
|
index=14,
|
|
|
|
command_class=const.COMMAND_CLASS_CONFIGURATION,
|
|
|
|
type=const.TYPE_BUTTON,
|
|
|
|
)
|
2018-03-20 13:04:24 +00:00
|
|
|
value_list_int = MockValue(
|
|
|
|
index=15,
|
|
|
|
command_class=const.COMMAND_CLASS_CONFIGURATION,
|
|
|
|
type=const.TYPE_LIST,
|
|
|
|
data_items=['1', '2', '3'],
|
|
|
|
)
|
2019-04-15 21:24:20 +00:00
|
|
|
value_bool = MockValue(
|
|
|
|
index=16,
|
2018-03-20 13:04:24 +00:00
|
|
|
command_class=const.COMMAND_CLASS_CONFIGURATION,
|
2019-04-15 21:24:20 +00:00
|
|
|
type=const.TYPE_BOOL,
|
2018-03-20 13:04:24 +00:00
|
|
|
)
|
2017-04-07 13:17:23 +00:00
|
|
|
node = MockNode(node_id=14)
|
2019-04-15 21:24:20 +00:00
|
|
|
node.get_values.return_value = {
|
|
|
|
12: value_byte,
|
|
|
|
13: value_list,
|
|
|
|
14: value_button,
|
|
|
|
15: value_list_int,
|
|
|
|
16: value_bool
|
|
|
|
}
|
2017-04-12 17:09:29 +00:00
|
|
|
self.zwave_network.nodes = {14: node}
|
2017-04-07 13:17:23 +00:00
|
|
|
|
2019-04-15 21:24:20 +00:00
|
|
|
# Byte
|
|
|
|
self.hass.services.call('zwave', 'set_config_parameter', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_CONFIG_PARAMETER: 12,
|
|
|
|
const.ATTR_CONFIG_VALUE: 7,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert value_byte.data == 7
|
|
|
|
|
|
|
|
# List
|
2017-04-07 13:17:23 +00:00
|
|
|
self.hass.services.call('zwave', 'set_config_parameter', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_CONFIG_PARAMETER: 13,
|
2017-05-19 00:39:31 +00:00
|
|
|
const.ATTR_CONFIG_VALUE: 'item3',
|
2017-04-07 13:17:23 +00:00
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2017-05-19 00:39:31 +00:00
|
|
|
assert value_list.data == 'item3'
|
2017-04-07 13:17:23 +00:00
|
|
|
|
2019-04-15 21:24:20 +00:00
|
|
|
# Button
|
|
|
|
self.hass.services.call('zwave', 'set_config_parameter', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_CONFIG_PARAMETER: 14,
|
|
|
|
const.ATTR_CONFIG_VALUE: True,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert self.zwave_network.manager.pressButton.called
|
|
|
|
assert self.zwave_network.manager.releaseButton.called
|
|
|
|
|
|
|
|
# List of Ints
|
2018-03-20 13:04:24 +00:00
|
|
|
self.hass.services.call('zwave', 'set_config_parameter', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_CONFIG_PARAMETER: 15,
|
|
|
|
const.ATTR_CONFIG_VALUE: 3,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert value_list_int.data == '3'
|
|
|
|
|
2019-04-15 21:24:20 +00:00
|
|
|
# Boolean Truthy
|
2017-04-07 13:17:23 +00:00
|
|
|
self.hass.services.call('zwave', 'set_config_parameter', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
2019-04-15 21:24:20 +00:00
|
|
|
const.ATTR_CONFIG_PARAMETER: 16,
|
|
|
|
const.ATTR_CONFIG_VALUE: 'True',
|
2017-04-07 13:17:23 +00:00
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2019-04-15 21:24:20 +00:00
|
|
|
assert value_bool.data == 1
|
2017-04-07 13:17:23 +00:00
|
|
|
|
2019-04-15 21:24:20 +00:00
|
|
|
# Boolean Falsy
|
2018-03-20 13:04:24 +00:00
|
|
|
self.hass.services.call('zwave', 'set_config_parameter', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
2019-04-15 21:24:20 +00:00
|
|
|
const.ATTR_CONFIG_PARAMETER: 16,
|
|
|
|
const.ATTR_CONFIG_VALUE: 'False',
|
2018-03-20 13:04:24 +00:00
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2019-04-15 21:24:20 +00:00
|
|
|
assert value_bool.data == 0
|
2018-03-20 13:04:24 +00:00
|
|
|
|
2019-04-15 21:24:20 +00:00
|
|
|
# Different Parameter Size
|
2017-04-07 13:17:23 +00:00
|
|
|
self.hass.services.call('zwave', 'set_config_parameter', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
2017-05-19 00:39:31 +00:00
|
|
|
const.ATTR_CONFIG_PARAMETER: 19,
|
2017-04-07 13:17:23 +00:00
|
|
|
const.ATTR_CONFIG_VALUE: 0x01020304,
|
2017-05-19 00:39:31 +00:00
|
|
|
const.ATTR_CONFIG_SIZE: 4
|
2017-04-07 13:17:23 +00:00
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert node.set_config_param.called
|
|
|
|
assert len(node.set_config_param.mock_calls) == 1
|
2017-05-19 00:39:31 +00:00
|
|
|
assert node.set_config_param.mock_calls[0][1][0] == 19
|
2017-04-07 13:17:23 +00:00
|
|
|
assert node.set_config_param.mock_calls[0][1][1] == 0x01020304
|
|
|
|
assert node.set_config_param.mock_calls[0][1][2] == 4
|
|
|
|
node.set_config_param.reset_mock()
|
|
|
|
|
|
|
|
def test_print_config_parameter(self):
|
|
|
|
"""Test zwave print_config_parameter service."""
|
|
|
|
value1 = MockValue(
|
|
|
|
index=12,
|
|
|
|
command_class=const.COMMAND_CLASS_CONFIGURATION,
|
|
|
|
data=1234,
|
|
|
|
)
|
|
|
|
value2 = MockValue(
|
|
|
|
index=13,
|
|
|
|
command_class=const.COMMAND_CLASS_CONFIGURATION,
|
|
|
|
data=2345,
|
|
|
|
)
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
node.values = {12: value1, 13: value2}
|
2017-04-12 17:09:29 +00:00
|
|
|
self.zwave_network.nodes = {14: node}
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
with patch.object(zwave, '_LOGGER') as mock_logger:
|
|
|
|
self.hass.services.call('zwave', 'print_config_parameter', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_CONFIG_PARAMETER: 13,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert mock_logger.info.called
|
|
|
|
assert len(mock_logger.info.mock_calls) == 1
|
|
|
|
assert mock_logger.info.mock_calls[0][1][1] == 13
|
|
|
|
assert mock_logger.info.mock_calls[0][1][2] == 14
|
|
|
|
assert mock_logger.info.mock_calls[0][1][3] == 2345
|
|
|
|
|
|
|
|
def test_print_node(self):
|
2018-04-05 09:14:15 +00:00
|
|
|
"""Test zwave print_node_parameter service."""
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
|
|
|
|
self.zwave_network.nodes = {14: node}
|
2017-04-07 13:17:23 +00:00
|
|
|
|
2018-09-18 13:06:52 +00:00
|
|
|
with self.assertLogs(level='DEBUG') as mock_logger:
|
2017-04-07 13:17:23 +00:00
|
|
|
self.hass.services.call('zwave', 'print_node', {
|
2018-04-05 09:14:15 +00:00
|
|
|
const.ATTR_NODE_ID: 14
|
2017-04-07 13:17:23 +00:00
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
2018-10-24 10:10:05 +00:00
|
|
|
assert "FOUND NODE " in mock_logger.output[1]
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_set_wakeup(self):
|
|
|
|
"""Test zwave set_wakeup service."""
|
|
|
|
value = MockValue(
|
|
|
|
index=12,
|
|
|
|
command_class=const.COMMAND_CLASS_WAKE_UP,
|
|
|
|
)
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
node.values = {12: value}
|
|
|
|
node.get_values.return_value = node.values
|
2017-04-12 17:09:29 +00:00
|
|
|
self.zwave_network.nodes = {14: node}
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
self.hass.services.call('zwave', 'set_wakeup', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_CONFIG_VALUE: 15,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert value.data == 15
|
|
|
|
|
|
|
|
node.can_wake_up_value = False
|
|
|
|
self.hass.services.call('zwave', 'set_wakeup', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_CONFIG_VALUE: 20,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert value.data == 15
|
|
|
|
|
2017-05-21 18:15:24 +00:00
|
|
|
def test_reset_node_meters(self):
|
|
|
|
"""Test zwave reset_node_meters service."""
|
|
|
|
value = MockValue(
|
|
|
|
instance=1,
|
|
|
|
index=8,
|
|
|
|
data=99.5,
|
|
|
|
command_class=const.COMMAND_CLASS_METER,
|
|
|
|
)
|
|
|
|
reset_value = MockValue(
|
|
|
|
instance=1,
|
|
|
|
index=33,
|
|
|
|
command_class=const.COMMAND_CLASS_METER,
|
|
|
|
)
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
node.values = {8: value, 33: reset_value}
|
|
|
|
node.get_values.return_value = node.values
|
|
|
|
self.zwave_network.nodes = {14: node}
|
|
|
|
|
|
|
|
self.hass.services.call('zwave', 'reset_node_meters', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_INSTANCE: 2,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert not self.zwave_network.manager.pressButton.called
|
|
|
|
assert not self.zwave_network.manager.releaseButton.called
|
|
|
|
|
|
|
|
self.hass.services.call('zwave', 'reset_node_meters', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert self.zwave_network.manager.pressButton.called
|
|
|
|
value_id, = self.zwave_network.manager.pressButton.mock_calls.pop(0)[1]
|
|
|
|
assert value_id == reset_value.value_id
|
|
|
|
assert self.zwave_network.manager.releaseButton.called
|
|
|
|
value_id, = (
|
|
|
|
self.zwave_network.manager.releaseButton.mock_calls.pop(0)[1])
|
|
|
|
assert value_id == reset_value.value_id
|
|
|
|
|
2017-04-07 13:17:23 +00:00
|
|
|
def test_add_association(self):
|
|
|
|
"""Test zwave change_association service."""
|
|
|
|
ZWaveGroup = self.mock_openzwave.group.ZWaveGroup
|
|
|
|
group = MagicMock()
|
|
|
|
ZWaveGroup.return_value = group
|
|
|
|
|
|
|
|
value = MockValue(
|
|
|
|
index=12,
|
|
|
|
command_class=const.COMMAND_CLASS_WAKE_UP,
|
|
|
|
)
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
node.values = {12: value}
|
|
|
|
node.get_values.return_value = node.values
|
2017-04-12 17:09:29 +00:00
|
|
|
self.zwave_network.nodes = {14: node}
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
self.hass.services.call('zwave', 'change_association', {
|
|
|
|
const.ATTR_ASSOCIATION: 'add',
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_TARGET_NODE_ID: 24,
|
|
|
|
const.ATTR_GROUP: 3,
|
|
|
|
const.ATTR_INSTANCE: 5,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert ZWaveGroup.called
|
|
|
|
assert len(ZWaveGroup.mock_calls) == 2
|
|
|
|
assert ZWaveGroup.mock_calls[0][1][0] == 3
|
|
|
|
assert ZWaveGroup.mock_calls[0][1][2] == 14
|
|
|
|
assert group.add_association.called
|
|
|
|
assert len(group.add_association.mock_calls) == 1
|
|
|
|
assert group.add_association.mock_calls[0][1][0] == 24
|
|
|
|
assert group.add_association.mock_calls[0][1][1] == 5
|
|
|
|
|
|
|
|
def test_remove_association(self):
|
|
|
|
"""Test zwave change_association service."""
|
|
|
|
ZWaveGroup = self.mock_openzwave.group.ZWaveGroup
|
|
|
|
group = MagicMock()
|
|
|
|
ZWaveGroup.return_value = group
|
|
|
|
|
|
|
|
value = MockValue(
|
|
|
|
index=12,
|
|
|
|
command_class=const.COMMAND_CLASS_WAKE_UP,
|
|
|
|
)
|
|
|
|
node = MockNode(node_id=14)
|
|
|
|
node.values = {12: value}
|
|
|
|
node.get_values.return_value = node.values
|
2017-04-12 17:09:29 +00:00
|
|
|
self.zwave_network.nodes = {14: node}
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
self.hass.services.call('zwave', 'change_association', {
|
|
|
|
const.ATTR_ASSOCIATION: 'remove',
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_TARGET_NODE_ID: 24,
|
|
|
|
const.ATTR_GROUP: 3,
|
|
|
|
const.ATTR_INSTANCE: 5,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert ZWaveGroup.called
|
|
|
|
assert len(ZWaveGroup.mock_calls) == 2
|
|
|
|
assert ZWaveGroup.mock_calls[0][1][0] == 3
|
|
|
|
assert ZWaveGroup.mock_calls[0][1][2] == 14
|
|
|
|
assert group.remove_association.called
|
|
|
|
assert len(group.remove_association.mock_calls) == 1
|
|
|
|
assert group.remove_association.mock_calls[0][1][0] == 24
|
|
|
|
assert group.remove_association.mock_calls[0][1][1] == 5
|
|
|
|
|
|
|
|
def test_refresh_entity(self):
|
|
|
|
"""Test zwave refresh_entity service."""
|
|
|
|
node = MockNode()
|
|
|
|
value = MockValue(data=False, node=node,
|
|
|
|
command_class=const.COMMAND_CLASS_SENSOR_BINARY)
|
|
|
|
power_value = MockValue(data=50, node=node,
|
|
|
|
command_class=const.COMMAND_CLASS_METER)
|
|
|
|
values = MockEntityValues(primary=value, power=power_value)
|
|
|
|
device = get_device(node=node, values=values, node_config={})
|
|
|
|
device.hass = self.hass
|
|
|
|
device.entity_id = 'binary_sensor.mock_entity_id'
|
|
|
|
self.hass.add_job(device.async_added_to_hass())
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
self.hass.services.call('zwave', 'refresh_entity', {
|
|
|
|
ATTR_ENTITY_ID: 'binary_sensor.mock_entity_id',
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert node.refresh_value.called
|
|
|
|
assert len(node.refresh_value.mock_calls) == 2
|
2018-10-24 10:10:05 +00:00
|
|
|
assert sorted([node.refresh_value.mock_calls[0][1][0],
|
|
|
|
node.refresh_value.mock_calls[1][1][0]]) == \
|
|
|
|
sorted([value.value_id, power_value.value_id])
|
2017-04-07 13:17:23 +00:00
|
|
|
|
|
|
|
def test_refresh_node(self):
|
|
|
|
"""Test zwave refresh_node service."""
|
|
|
|
node = MockNode(node_id=14)
|
2017-04-12 17:09:29 +00:00
|
|
|
self.zwave_network.nodes = {14: node}
|
2017-04-07 13:17:23 +00:00
|
|
|
self.hass.services.call('zwave', 'refresh_node', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert node.refresh_info.called
|
|
|
|
assert len(node.refresh_info.mock_calls) == 1
|
2017-11-05 17:19:19 +00:00
|
|
|
|
2018-09-27 10:34:42 +00:00
|
|
|
def test_set_node_value(self):
|
|
|
|
"""Test zwave set_node_value service."""
|
|
|
|
value = MockValue(
|
|
|
|
index=12,
|
|
|
|
command_class=const.COMMAND_CLASS_INDICATOR,
|
|
|
|
data=4
|
|
|
|
)
|
|
|
|
node = MockNode(node_id=14,
|
|
|
|
command_classes=[const.COMMAND_CLASS_INDICATOR])
|
|
|
|
node.values = {12: value}
|
|
|
|
node.get_values.return_value = node.values
|
|
|
|
self.zwave_network.nodes = {14: node}
|
|
|
|
|
|
|
|
self.hass.services.call('zwave', 'set_node_value', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_VALUE_ID: 12,
|
|
|
|
const.ATTR_CONFIG_VALUE: 2,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert self.zwave_network.nodes[14].values[12].data == 2
|
|
|
|
|
|
|
|
def test_refresh_node_value(self):
|
|
|
|
"""Test zwave refresh_node_value service."""
|
|
|
|
node = MockNode(node_id=14,
|
|
|
|
command_classes=[const.COMMAND_CLASS_INDICATOR],
|
|
|
|
network=self.zwave_network)
|
|
|
|
value = MockValue(
|
|
|
|
node=node,
|
|
|
|
index=12,
|
|
|
|
command_class=const.COMMAND_CLASS_INDICATOR,
|
|
|
|
data=2
|
|
|
|
)
|
|
|
|
value.refresh = MagicMock()
|
|
|
|
|
|
|
|
node.values = {12: value}
|
|
|
|
node.get_values.return_value = node.values
|
|
|
|
self.zwave_network.nodes = {14: node}
|
|
|
|
|
|
|
|
self.hass.services.call('zwave', 'refresh_node_value', {
|
|
|
|
const.ATTR_NODE_ID: 14,
|
|
|
|
const.ATTR_VALUE_ID: 12
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert value.refresh.called
|
|
|
|
|
2017-11-05 17:19:19 +00:00
|
|
|
def test_heal_node(self):
|
|
|
|
"""Test zwave heal_node service."""
|
|
|
|
node = MockNode(node_id=19)
|
|
|
|
self.zwave_network.nodes = {19: node}
|
|
|
|
self.hass.services.call('zwave', 'heal_node', {
|
|
|
|
const.ATTR_NODE_ID: 19,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert node.heal.called
|
|
|
|
assert len(node.heal.mock_calls) == 1
|
|
|
|
|
|
|
|
def test_test_node(self):
|
|
|
|
"""Test the zwave test_node service."""
|
|
|
|
node = MockNode(node_id=19)
|
|
|
|
self.zwave_network.nodes = {19: node}
|
|
|
|
self.hass.services.call('zwave', 'test_node', {
|
|
|
|
const.ATTR_NODE_ID: 19,
|
|
|
|
})
|
|
|
|
self.hass.block_till_done()
|
|
|
|
|
|
|
|
assert node.test.called
|
|
|
|
assert len(node.test.mock_calls) == 1
|