diff --git a/homeassistant/components/shelly/sensor.py b/homeassistant/components/shelly/sensor.py index abcca888005..99ccd9ab2ff 100644 --- a/homeassistant/components/shelly/sensor.py +++ b/homeassistant/components/shelly/sensor.py @@ -363,6 +363,14 @@ RPC_SENSORS: Final = { device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, ), + "power_em1": RpcSensorDescription( + key="em1", + sub_key="act_power", + name="Power", + native_unit_of_measurement=UnitOfPower.WATT, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + ), "power_pm1": RpcSensorDescription( key="pm1", sub_key="apower", @@ -427,6 +435,14 @@ RPC_SENSORS: Final = { device_class=SensorDeviceClass.APPARENT_POWER, state_class=SensorStateClass.MEASUREMENT, ), + "aprt_power_em1": RpcSensorDescription( + key="em1", + sub_key="aprt_power", + name="Apparent power", + native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE, + device_class=SensorDeviceClass.APPARENT_POWER, + state_class=SensorStateClass.MEASUREMENT, + ), "total_aprt_power": RpcSensorDescription( key="em", sub_key="total_aprt_power", @@ -435,6 +451,13 @@ RPC_SENSORS: Final = { device_class=SensorDeviceClass.APPARENT_POWER, state_class=SensorStateClass.MEASUREMENT, ), + "pf_em1": RpcSensorDescription( + key="em1", + sub_key="pf", + name="Power factor", + device_class=SensorDeviceClass.POWER_FACTOR, + state_class=SensorStateClass.MEASUREMENT, + ), "a_pf": RpcSensorDescription( key="em", sub_key="a_pf", @@ -467,6 +490,17 @@ RPC_SENSORS: Final = { state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, ), + "voltage_em1": RpcSensorDescription( + key="em1", + sub_key="voltage", + name="Voltage", + native_unit_of_measurement=UnitOfElectricPotential.VOLT, + value=lambda status, _: None if status is None else float(status), + suggested_display_precision=1, + device_class=SensorDeviceClass.VOLTAGE, + state_class=SensorStateClass.MEASUREMENT, + entity_registry_enabled_default=False, + ), "voltage_pm1": RpcSensorDescription( key="pm1", sub_key="voltage", @@ -515,6 +549,16 @@ RPC_SENSORS: Final = { state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, ), + "current_em1": RpcSensorDescription( + key="em1", + sub_key="current", + name="Current", + native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, + value=lambda status, _: None if status is None else float(status), + device_class=SensorDeviceClass.CURRENT, + state_class=SensorStateClass.MEASUREMENT, + entity_registry_enabled_default=False, + ), "current_pm1": RpcSensorDescription( key="pm1", sub_key="current", @@ -605,6 +649,18 @@ RPC_SENSORS: Final = { device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, ), + "total_act_energy": RpcSensorDescription( + key="em1data", + sub_key="total_act_energy", + name="Total active energy", + native_unit_of_measurement=UnitOfEnergy.WATT_HOUR, + suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value=lambda status, _: float(status), + suggested_display_precision=2, + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + entity_registry_enabled_default=False, + ), "a_total_act_energy": RpcSensorDescription( key="emdata", sub_key="a_total_act_energy", @@ -652,6 +708,18 @@ RPC_SENSORS: Final = { device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, ), + "total_act_ret_energy": RpcSensorDescription( + key="em1data", + sub_key="total_act_ret_energy", + name="Total active returned energy", + native_unit_of_measurement=UnitOfEnergy.WATT_HOUR, + suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value=lambda status, _: float(status), + suggested_display_precision=2, + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + entity_registry_enabled_default=False, + ), "a_total_act_ret_energy": RpcSensorDescription( key="emdata", sub_key="a_total_act_ret_energy", @@ -698,6 +766,16 @@ RPC_SENSORS: Final = { state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, ), + "freq_em1": RpcSensorDescription( + key="em1", + sub_key="freq", + name="Frequency", + native_unit_of_measurement=UnitOfFrequency.HERTZ, + suggested_display_precision=0, + device_class=SensorDeviceClass.FREQUENCY, + state_class=SensorStateClass.MEASUREMENT, + entity_registry_enabled_default=False, + ), "freq_pm1": RpcSensorDescription( key="pm1", sub_key="freq", diff --git a/homeassistant/components/shelly/utils.py b/homeassistant/components/shelly/utils.py index a66b77ed94b..e78b44db15e 100644 --- a/homeassistant/components/shelly/utils.py +++ b/homeassistant/components/shelly/utils.py @@ -288,6 +288,7 @@ def get_model_name(info: dict[str, Any]) -> str: def get_rpc_channel_name(device: RpcDevice, key: str) -> str: """Get name based on device and channel name.""" key = key.replace("emdata", "em") + key = key.replace("em1data", "em1") if device.config.get("switch:0"): key = key.replace("input", "switch") device_name = device.name @@ -298,6 +299,8 @@ def get_rpc_channel_name(device: RpcDevice, key: str) -> str: if entity_name is None: if key.startswith(("input:", "light:", "switch:")): return f"{device_name} {key.replace(':', '_')}" + if key.startswith("em1"): + return f"{device_name} EM{key.split(':')[-1]}" return device_name return entity_name diff --git a/tests/components/shelly/conftest.py b/tests/components/shelly/conftest.py index 797673265a6..e72604260f5 100644 --- a/tests/components/shelly/conftest.py +++ b/tests/components/shelly/conftest.py @@ -202,6 +202,10 @@ MOCK_STATUS_RPC = { "devicepower:0": {"external": {"present": True}}, "temperature:0": {"tC": 22.9}, "illuminance:0": {"lux": 345}, + "em1:0": {"act_power": 85.3}, + "em1:1": {"act_power": 123.3}, + "em1data:0": {"total_act_energy": 123456.4}, + "em1data:1": {"total_act_energy": 987654.3}, "sys": { "available_updates": { "beta": {"version": "some_beta_version"}, diff --git a/tests/components/shelly/test_sensor.py b/tests/components/shelly/test_sensor.py index 892d06ad626..a738113f18f 100644 --- a/tests/components/shelly/test_sensor.py +++ b/tests/components/shelly/test_sensor.py @@ -408,3 +408,43 @@ async def test_rpc_restored_sleeping_sensor_no_last_state( await hass.async_block_till_done() assert hass.states.get(entity_id).state == "22.9" + + +async def test_rpc_em1_sensors( + hass: HomeAssistant, mock_rpc_device, entity_registry_enabled_by_default: None +) -> None: + """Test RPC sensors for EM1 component.""" + registry = async_get(hass) + await init_integration(hass, 2) + + state = hass.states.get("sensor.test_name_em0_power") + assert state + assert state.state == "85.3" + + entry = registry.async_get("sensor.test_name_em0_power") + assert entry + assert entry.unique_id == "123456789ABC-em1:0-power_em1" + + state = hass.states.get("sensor.test_name_em1_power") + assert state + assert state.state == "123.3" + + entry = registry.async_get("sensor.test_name_em1_power") + assert entry + assert entry.unique_id == "123456789ABC-em1:1-power_em1" + + state = hass.states.get("sensor.test_name_em0_total_active_energy") + assert state + assert state.state == "123.4564" + + entry = registry.async_get("sensor.test_name_em0_total_active_energy") + assert entry + assert entry.unique_id == "123456789ABC-em1data:0-total_act_energy" + + state = hass.states.get("sensor.test_name_em1_total_active_energy") + assert state + assert state.state == "987.6543" + + entry = registry.async_get("sensor.test_name_em1_total_active_energy") + assert entry + assert entry.unique_id == "123456789ABC-em1data:1-total_act_energy"