diff --git a/homeassistant/components/zwave/__init__.py b/homeassistant/components/zwave/__init__.py index 79067c0d2ef..4b86c191763 100755 --- a/homeassistant/components/zwave/__init__.py +++ b/homeassistant/components/zwave/__init__.py @@ -95,6 +95,11 @@ REFRESH_ENTITY_SCHEMA = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_id, }) +RESET_NODE_METERS_SCHEMA = vol.Schema({ + vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), + vol.Optional(const.ATTR_INSTANCE, default=1): vol.Coerce(int) +}) + CHANGE_ASSOCIATION_SCHEMA = vol.Schema({ vol.Required(const.ATTR_ASSOCIATION): cv.string, vol.Required(const.ATTR_NODE_ID): vol.Coerce(int), @@ -499,6 +504,26 @@ def setup(hass, config): node = network.nodes[node_id] node.refresh_info() + def reset_node_meters(service): + """Reset meter counters of a node.""" + node_id = service.data.get(const.ATTR_NODE_ID) + instance = service.data.get(const.ATTR_INSTANCE) + node = network.nodes[node_id] + for value in ( + node.get_values(class_id=const.COMMAND_CLASS_METER) + .values()): + if value.index != const.METER_RESET_INDEX: + continue + if value.instance != instance: + continue + network.manager.pressButton(value.value_id) + network.manager.releaseButton(value.value_id) + _LOGGER.info("Resetting meters on node %s instance %s....", + node_id, instance) + return + _LOGGER.info("Node %s on instance %s does not have resettable " + "meters.", node_id, instance) + def start_zwave(_service_or_event): """Startup Z-Wave network.""" _LOGGER.info("Starting Z-Wave network...") @@ -606,6 +631,11 @@ def setup(hass, config): descriptions[ const.SERVICE_REFRESH_NODE], schema=NODE_SERVICE_SCHEMA) + hass.services.register(DOMAIN, const.SERVICE_RESET_NODE_METERS, + reset_node_meters, + descriptions[ + const.SERVICE_RESET_NODE_METERS], + schema=RESET_NODE_METERS_SCHEMA) # Setup autoheal if autoheal: diff --git a/homeassistant/components/zwave/const.py b/homeassistant/components/zwave/const.py index 5b2eb08657d..b2fcf448db5 100644 --- a/homeassistant/components/zwave/const.py +++ b/homeassistant/components/zwave/const.py @@ -37,6 +37,7 @@ SERVICE_START_NETWORK = "start_network" SERVICE_RENAME_NODE = "rename_node" SERVICE_REFRESH_ENTITY = "refresh_entity" SERVICE_REFRESH_NODE = "refresh_node" +SERVICE_RESET_NODE_METERS = "reset_node_meters" EVENT_SCENE_ACTIVATED = "zwave.scene_activated" EVENT_NODE_EVENT = "zwave.node_event" @@ -329,3 +330,5 @@ DISC_SPECIFIC_DEVICE_CLASS = "specific_device_class" DISC_TYPE = "type" DISC_VALUES = "values" DISC_WRITEONLY = "writeonly" + +METER_RESET_INDEX = 33 diff --git a/homeassistant/components/zwave/services.yaml b/homeassistant/components/zwave/services.yaml index feacf8229aa..6f61dec5cc7 100644 --- a/homeassistant/components/zwave/services.yaml +++ b/homeassistant/components/zwave/services.yaml @@ -108,3 +108,11 @@ rename_node: name: description: New Name example: 'kitchen' + +reset_node_meters: + description: Resets the meter counters of a node. + fields: + node_id: + description: Node id of the device to reset meters for. (integer) + instance: + description: (Optional) Instance of association. Defaults to instance 1. diff --git a/tests/components/zwave/test_init.py b/tests/components/zwave/test_init.py index 17fac86c748..de500a81893 100644 --- a/tests/components/zwave/test_init.py +++ b/tests/components/zwave/test_init.py @@ -144,17 +144,17 @@ def test_setup_platform(hass, mock_openzwave): async_add_devices = MagicMock() result = yield from zwave.async_setup_platform( - hass, None, async_add_devices, None) + hass, None, async_add_devices, None) assert not result assert not async_add_devices.called result = yield from zwave.async_setup_platform( - hass, None, async_add_devices, {const.DISCOVERY_DEVICE: 123}) + hass, None, async_add_devices, {const.DISCOVERY_DEVICE: 123}) assert not result assert not async_add_devices.called result = yield from zwave.async_setup_platform( - hass, None, async_add_devices, {const.DISCOVERY_DEVICE: 456}) + hass, None, async_add_devices, {const.DISCOVERY_DEVICE: 456}) assert result assert async_add_devices.called assert len(async_add_devices.mock_calls) == 1 @@ -1015,6 +1015,46 @@ class TestZWaveServices(unittest.TestCase): assert value.data == 15 + 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 + def test_add_association(self): """Test zwave change_association service.""" ZWaveGroup = self.mock_openzwave.group.ZWaveGroup