diff --git a/homeassistant/components/shelly/sensor.py b/homeassistant/components/shelly/sensor.py index 8dde2d323f0..49c4befb2cf 100644 --- a/homeassistant/components/shelly/sensor.py +++ b/homeassistant/components/shelly/sensor.py @@ -963,6 +963,25 @@ RPC_SENSORS: Final = { sub_key="xpercent", name="Analog value", ), + "pulse_counter": RpcSensorDescription( + key="input", + sub_key="counts", + name="Pulse counter", + native_unit_of_measurement="pulse", + state_class=SensorStateClass.TOTAL, + value=lambda status, _: status["total"], + removal_condition=lambda config, _status, key: (config[key]["enable"] is False), + ), + "counter_value": RpcSensorDescription( + key="input", + sub_key="counts", + name="Counter value", + value=lambda status, _: status["xtotal"], + removal_condition=lambda config, status, key: ( + config[key]["enable"] is False + or status[key]["counts"].get("xtotal") is None + ), + ), } diff --git a/tests/components/shelly/conftest.py b/tests/components/shelly/conftest.py index 45e1e551b23..d8895e39657 100644 --- a/tests/components/shelly/conftest.py +++ b/tests/components/shelly/conftest.py @@ -167,6 +167,12 @@ MOCK_BLOCKS = [ MOCK_CONFIG = { "input:0": {"id": 0, "name": "Test name input 0", "type": "button"}, + "input:2": { + "id": 2, + "name": "Gas", + "type": "count", + "enable": True, + }, "light:0": {"name": "test light_0"}, "switch:0": {"name": "test switch_0"}, "cover:0": {"name": "test cover_0"}, @@ -220,6 +226,7 @@ MOCK_STATUS_COAP = { MOCK_STATUS_RPC = { "switch:0": {"output": True}, "input:0": {"id": 0, "state": None, "xpercent": 8.9}, + "input:2": {"id": 2, "counts": {"total": 56174, "xtotal": 561.74}}, "light:0": {"output": True, "brightness": 53.0}, "cloud": {"connected": False}, "cover:0": { diff --git a/tests/components/shelly/test_sensor.py b/tests/components/shelly/test_sensor.py index 4f93b298557..5c1d4bad267 100644 --- a/tests/components/shelly/test_sensor.py +++ b/tests/components/shelly/test_sensor.py @@ -1,4 +1,7 @@ """Tests for Shelly sensor platform.""" +from copy import deepcopy +from unittest.mock import Mock + from freezegun.api import FrozenDateTimeFactory import pytest @@ -23,7 +26,7 @@ from homeassistant.const import ( UnitOfEnergy, ) from homeassistant.core import HomeAssistant, State -from homeassistant.helpers.entity_registry import async_get +from homeassistant.helpers.entity_registry import EntityRegistry, async_get from homeassistant.setup import async_setup_component from . import ( @@ -608,3 +611,67 @@ async def test_rpc_analog_input_xpercent_sensor( entry = entity_registry.async_get(entity_id) assert entry assert entry.unique_id == "123456789ABC-input:0-analoginput_xpercent" + + +async def test_rpc_pulse_counter_sensors( + hass: HomeAssistant, + mock_rpc_device: Mock, + entity_registry: EntityRegistry, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test RPC counter sensor.""" + await init_integration(hass, 2) + + entity_id = f"{SENSOR_DOMAIN}.gas_pulse_counter" + state = hass.states.get(entity_id) + assert state.state == "56174" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "pulse" + assert state.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.TOTAL + + entry = entity_registry.async_get(entity_id) + assert entry + assert entry.unique_id == "123456789ABC-input:2-pulse_counter" + + entity_id = f"{SENSOR_DOMAIN}.gas_counter_value" + assert hass.states.get(entity_id).state == "561.74" + + entry = entity_registry.async_get(entity_id) + assert entry + assert entry.unique_id == "123456789ABC-input:2-counter_value" + + +async def test_rpc_disabled_pulse_counter_sensors( + hass: HomeAssistant, mock_rpc_device: Mock, monkeypatch: pytest.MonkeyPatch +) -> None: + """Test RPC disabled counter sensor.""" + new_config = deepcopy(mock_rpc_device.config) + new_config["input:2"]["enable"] = False + monkeypatch.setattr(mock_rpc_device, "config", new_config) + + await init_integration(hass, 2) + + entity_id = f"{SENSOR_DOMAIN}.gas_pulse_counter" + assert hass.states.get(entity_id) is None + + entity_id = f"{SENSOR_DOMAIN}.gas_counter_value" + assert hass.states.get(entity_id) is None + + +async def test_rpc_disabled_xtotal_counter( + hass: HomeAssistant, mock_rpc_device: Mock, monkeypatch: pytest.MonkeyPatch +) -> None: + """Test RPC disabled xtotal counter.""" + mutate_rpc_device_status( + monkeypatch, + mock_rpc_device, + "input:2", + "counts", + {"total": 20635}, + ) + await init_integration(hass, 2) + + entity_id = f"{SENSOR_DOMAIN}.gas_pulse_counter" + assert hass.states.get(entity_id).state == "20635" + + entity_id = f"{SENSOR_DOMAIN}.gas_counter_value" + assert hass.states.get(entity_id) is None