Add zwave_js.reset_meter service (#53390)

* Add zwave_js.meter_reset service

* fix log statement

* Add endpoint attribute to service call and rename service

* Make service an entity service

* remove endpoint from service description
pull/53647/head
Raman Gupta 2021-07-28 17:15:27 -04:00 committed by GitHub
parent a8536e3ce5
commit e1c6ccb198
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 130 additions and 12 deletions

View File

@ -49,24 +49,24 @@ ATTR_NODE = "node"
ATTR_ZWAVE_VALUE = "zwave_value"
# service constants
ATTR_NODES = "nodes"
SERVICE_SET_VALUE = "set_value"
SERVICE_RESET_METER = "reset_meter"
SERVICE_MULTICAST_SET_VALUE = "multicast_set_value"
SERVICE_PING = "ping"
SERVICE_REFRESH_VALUE = "refresh_value"
SERVICE_SET_CONFIG_PARAMETER = "set_config_parameter"
SERVICE_BULK_SET_PARTIAL_CONFIG_PARAMETERS = "bulk_set_partial_config_parameters"
ATTR_NODES = "nodes"
# config parameter
ATTR_CONFIG_PARAMETER = "parameter"
ATTR_CONFIG_PARAMETER_BITMASK = "bitmask"
ATTR_CONFIG_VALUE = "value"
SERVICE_REFRESH_VALUE = "refresh_value"
# refresh value
ATTR_REFRESH_ALL_VALUES = "refresh_all_values"
SERVICE_SET_VALUE = "set_value"
SERVICE_MULTICAST_SET_VALUE = "multicast_set_value"
# multicast
ATTR_BROADCAST = "broadcast"
SERVICE_PING = "ping"
# meter reset
ATTR_METER_TYPE = "meter_type"
ADDON_SLUG = "core_zwave_js"

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import logging
from typing import cast
import voluptuous as vol
from zwave_js_server.client import Client as ZwaveClient
from zwave_js_server.const import CommandClass, ConfigurationValueType
from zwave_js_server.model.node import Node as ZwaveNode
@ -26,10 +27,11 @@ from homeassistant.const import (
TEMP_FAHRENHEIT,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_platform
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DATA_CLIENT, DOMAIN
from .const import ATTR_METER_TYPE, ATTR_VALUE, DATA_CLIENT, DOMAIN, SERVICE_RESET_METER
from .discovery import ZwaveDiscoveryInfo
from .entity import ZWaveBaseEntity
from .helpers import get_device_id
@ -89,6 +91,16 @@ async def async_setup_entry(
)
)
platform = entity_platform.async_get_current_platform()
platform.async_register_entity_service(
SERVICE_RESET_METER,
{
vol.Optional(ATTR_METER_TYPE): vol.Coerce(int),
vol.Optional(ATTR_VALUE): vol.Coerce(int),
},
"async_reset_meter",
)
class ZwaveSensorBase(ZWaveBaseEntity, SensorEntity):
"""Basic Representation of a Z-Wave sensor."""
@ -218,6 +230,30 @@ class ZWaveNumericSensor(ZwaveSensorBase):
return str(self.info.primary_value.metadata.unit)
async def async_reset_meter(
self, meter_type: int | None = None, value: int | None = None
) -> None:
"""Reset meter(s) on device."""
node = self.info.node
primary_value = self.info.primary_value
if primary_value.command_class != CommandClass.METER:
raise TypeError("Reset only available for Meter sensors")
options = {}
if meter_type is not None:
options["type"] = meter_type
if value is not None:
options["targetValue"] = value
args = [options] if options else []
await node.endpoints[primary_value.endpoint].async_invoke_cc_api(
CommandClass.METER, "reset", *args, wait_for_result=False
)
LOGGER.debug(
"Meters on node %s endpoint %s reset with the following options: %s",
node,
primary_value.endpoint,
options,
)
class ZWaveListSensor(ZwaveSensorBase):
"""Representation of a Z-Wave Numeric sensor with multiple states."""

View File

@ -229,3 +229,26 @@ ping:
target:
entity:
integration: zwave_js
reset_meter:
name: Reset meter(s) on a node
description: Resets the meter(s) on a node.
target:
entity:
domain: sensor
integration: zwave_js
fields:
meter_type:
name: Meter Type
description: The type of meter to reset. Not all meters support the ability to pick a meter type to reset.
example: 1
required: false
selector:
text:
value:
name: Target Value
description: The value that meter(s) should be reset to. Not all meters support the ability to be reset to a specific value.
example: 5
required: false
selector:
text:

View File

@ -1,7 +1,14 @@
"""Test the Z-Wave JS sensor platform."""
from zwave_js_server.event import Event
from homeassistant.components.zwave_js.const import (
ATTR_METER_TYPE,
ATTR_VALUE,
DOMAIN,
SERVICE_RESET_METER,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_POWER,
@ -131,3 +138,55 @@ async def test_node_status_sensor(hass, lock_id_lock_as_id150, integration):
)
node.receive_event(event)
assert hass.states.get(NODE_STATUS_ENTITY).state == "alive"
async def test_reset_meter(
hass,
client,
aeon_smart_switch_6,
integration,
):
"""Test reset_meter service."""
SENSOR = "sensor.smart_switch_6_electric_consumed_v"
client.async_send_command.return_value = {}
client.async_send_command_no_wait.return_value = {}
# Test successful meter reset call
await hass.services.async_call(
DOMAIN,
SERVICE_RESET_METER,
{
ATTR_ENTITY_ID: SENSOR,
},
blocking=True,
)
assert len(client.async_send_command_no_wait.call_args_list) == 1
args = client.async_send_command_no_wait.call_args[0][0]
assert args["command"] == "endpoint.invoke_cc_api"
assert args["nodeId"] == aeon_smart_switch_6.node_id
assert args["endpoint"] == 0
assert args["args"] == []
client.async_send_command_no_wait.reset_mock()
# Test successful meter reset call with options
await hass.services.async_call(
DOMAIN,
SERVICE_RESET_METER,
{
ATTR_ENTITY_ID: SENSOR,
ATTR_METER_TYPE: 1,
ATTR_VALUE: 2,
},
blocking=True,
)
assert len(client.async_send_command_no_wait.call_args_list) == 1
args = client.async_send_command_no_wait.call_args[0][0]
assert args["command"] == "endpoint.invoke_cc_api"
assert args["nodeId"] == aeon_smart_switch_6.node_id
assert args["endpoint"] == 0
assert args["args"] == [{"type": 1, "targetValue": 2}]
client.async_send_command_no_wait.reset_mock()