diff --git a/homeassistant/components/shelly/button.py b/homeassistant/components/shelly/button.py index a505867b3e8..edc33c9a8a0 100644 --- a/homeassistant/components/shelly/button.py +++ b/homeassistant/components/shelly/button.py @@ -154,7 +154,6 @@ class ShellyButton( entity_description: ShellyButtonDescription[ ShellyRpcCoordinator | ShellyBlockCoordinator ] - _attr_has_entity_name = True def __init__( self, @@ -167,6 +166,7 @@ class ShellyButton( super().__init__(coordinator) self.entity_description = description + self._attr_name = f"{coordinator.device.name} {description.name}" self._attr_unique_id = f"{coordinator.mac}_{description.key}" self._attr_device_info = DeviceInfo( connections={(CONNECTION_NETWORK_MAC, coordinator.mac)} diff --git a/homeassistant/components/shelly/climate.py b/homeassistant/components/shelly/climate.py index d77a491661c..a9712e62d25 100644 --- a/homeassistant/components/shelly/climate.py +++ b/homeassistant/components/shelly/climate.py @@ -130,7 +130,6 @@ class BlockSleepingClimate( ) _attr_target_temperature_step = SHTRV_01_TEMPERATURE_SETTINGS["step"] _attr_temperature_unit = UnitOfTemperature.CELSIUS - _attr_has_entity_name = True def __init__( self, @@ -174,6 +173,11 @@ class BlockSleepingClimate( """Set unique id of entity.""" return self._unique_id + @property + def name(self) -> str: + """Name of entity.""" + return self.coordinator.name + @property def target_temperature(self) -> float | None: """Set target temperature.""" @@ -350,7 +354,7 @@ class BlockSleepingClimate( severity=ir.IssueSeverity.ERROR, translation_key="device_not_calibrated", translation_placeholders={ - "device_name": self.coordinator.name, + "device_name": self.name, "ip_address": self.coordinator.device.ip_address, }, ) diff --git a/homeassistant/components/shelly/entity.py b/homeassistant/components/shelly/entity.py index ac06624c750..1dc7573b738 100644 --- a/homeassistant/components/shelly/entity.py +++ b/homeassistant/components/shelly/entity.py @@ -321,8 +321,6 @@ class RestEntityDescription(EntityDescription): class ShellyBlockEntity(CoordinatorEntity[ShellyBlockCoordinator]): """Helper class to represent a block entity.""" - _attr_has_entity_name = True - def __init__(self, coordinator: ShellyBlockCoordinator, block: Block) -> None: """Initialize Shelly entity.""" super().__init__(coordinator) @@ -361,8 +359,6 @@ class ShellyBlockEntity(CoordinatorEntity[ShellyBlockCoordinator]): class ShellyRpcEntity(CoordinatorEntity[ShellyRpcCoordinator]): """Helper class to represent a rpc entity.""" - _attr_has_entity_name = True - def __init__(self, coordinator: ShellyRpcCoordinator, key: str) -> None: """Initialize Shelly entity.""" super().__init__(coordinator) @@ -466,7 +462,6 @@ class ShellyRestAttributeEntity(CoordinatorEntity[ShellyBlockCoordinator]): """Class to load info from REST.""" entity_description: RestEntityDescription - _attr_has_entity_name = True def __init__( self, diff --git a/homeassistant/components/shelly/logbook.py b/homeassistant/components/shelly/logbook.py index b8f0c8e1744..d55ffe0fd28 100644 --- a/homeassistant/components/shelly/logbook.py +++ b/homeassistant/components/shelly/logbook.py @@ -42,8 +42,7 @@ def async_describe_events( rpc_coordinator = get_rpc_coordinator_by_device_id(hass, device_id) if rpc_coordinator and rpc_coordinator.device.initialized: key = f"input:{channel-1}" - if iname := get_rpc_entity_name(rpc_coordinator.device, key): - input_name = iname + input_name = get_rpc_entity_name(rpc_coordinator.device, key) elif click_type in BLOCK_INPUTS_EVENTS_TYPES: block_coordinator = get_block_coordinator_by_device_id(hass, device_id) diff --git a/homeassistant/components/shelly/utils.py b/homeassistant/components/shelly/utils.py index 1faa36ce118..a66b77ed94b 100644 --- a/homeassistant/components/shelly/utils.py +++ b/homeassistant/components/shelly/utils.py @@ -72,26 +72,26 @@ def get_block_entity_name( device: BlockDevice, block: Block | None, description: str | None = None, -) -> str | None: +) -> str: """Naming for block based switch and sensors.""" channel_name = get_block_channel_name(device, block) - if description and channel_name: - return f"{channel_name} {uncapitalize(description)}" if description: - return description + return f"{channel_name} {description.lower()}" return channel_name -def get_block_channel_name(device: BlockDevice, block: Block | None) -> str | None: +def get_block_channel_name(device: BlockDevice, block: Block | None) -> str: """Get name based on device and channel name.""" + entity_name = device.name + if ( not block or block.type == "device" or get_number_of_channels(device, block) == 1 ): - return None + return entity_name assert block.channel @@ -108,7 +108,7 @@ def get_block_channel_name(device: BlockDevice, block: Block | None) -> str | No else: base = ord("1") - return f"Channel {chr(int(block.channel)+base)}" + return f"{entity_name} channel {chr(int(block.channel)+base)}" def is_block_momentary_input( @@ -285,32 +285,32 @@ def get_model_name(info: dict[str, Any]) -> str: return cast(str, MODEL_NAMES.get(info["type"], info["type"])) -def get_rpc_channel_name(device: RpcDevice, key: str) -> str | None: +def get_rpc_channel_name(device: RpcDevice, key: str) -> str: """Get name based on device and channel name.""" key = key.replace("emdata", "em") if device.config.get("switch:0"): key = key.replace("input", "switch") + device_name = device.name entity_name: str | None = None if key in device.config: - entity_name = device.config[key].get("name") + entity_name = device.config[key].get("name", device_name) if entity_name is None: if key.startswith(("input:", "light:", "switch:")): - return key.replace(":", " ").capitalize() + return f"{device_name} {key.replace(':', '_')}" + return device_name return entity_name def get_rpc_entity_name( device: RpcDevice, key: str, description: str | None = None -) -> str | None: +) -> str: """Naming for RPC based switch and sensors.""" channel_name = get_rpc_channel_name(device, key) - if description and channel_name: - return f"{channel_name} {uncapitalize(description)}" if description: - return description + return f"{channel_name} {description.lower()}" return channel_name @@ -405,8 +405,3 @@ def mac_address_from_name(name: str) -> str | None: """Convert a name to a mac address.""" mac = name.partition(".")[0].partition("-")[-1] return mac.upper() if len(mac) == 12 else None - - -def uncapitalize(description: str) -> str: - """Uncapitalize the first letter of a description.""" - return description[:1].lower() + description[1:] diff --git a/tests/components/shelly/test_binary_sensor.py b/tests/components/shelly/test_binary_sensor.py index a54b5398b11..8905ff5c3e8 100644 --- a/tests/components/shelly/test_binary_sensor.py +++ b/tests/components/shelly/test_binary_sensor.py @@ -167,7 +167,7 @@ async def test_rpc_binary_sensor( hass: HomeAssistant, mock_rpc_device, monkeypatch ) -> None: """Test RPC binary sensor.""" - entity_id = f"{BINARY_SENSOR_DOMAIN}.test_name_test_cover_0_overpowering" + entity_id = f"{BINARY_SENSOR_DOMAIN}.test_cover_0_overpowering" await init_integration(hass, 2) assert hass.states.get(entity_id).state == STATE_OFF diff --git a/tests/components/shelly/test_coordinator.py b/tests/components/shelly/test_coordinator.py index a7fa64962e9..3872f6f5a1a 100644 --- a/tests/components/shelly/test_coordinator.py +++ b/tests/components/shelly/test_coordinator.py @@ -347,14 +347,14 @@ async def test_rpc_reload_on_cfg_change( ) await hass.async_block_till_done() - assert hass.states.get("switch.test_name_test_switch_0") is not None + assert hass.states.get("switch.test_switch_0") is not None # Wait for debouncer freezer.tick(timedelta(seconds=ENTRY_RELOAD_COOLDOWN)) async_fire_time_changed(hass) await hass.async_block_till_done() - assert hass.states.get("switch.test_name_test_switch_0") is None + assert hass.states.get("switch.test_switch_0") is None async def test_rpc_reload_with_invalid_auth( @@ -577,7 +577,7 @@ async def test_rpc_reconnect_error( """Test RPC reconnect error.""" await init_integration(hass, 2) - assert hass.states.get("switch.test_name_test_switch_0").state == STATE_ON + assert hass.states.get("switch.test_switch_0").state == STATE_ON monkeypatch.setattr(mock_rpc_device, "connected", False) monkeypatch.setattr( @@ -593,7 +593,7 @@ async def test_rpc_reconnect_error( async_fire_time_changed(hass) await hass.async_block_till_done() - assert hass.states.get("switch.test_name_test_switch_0").state == STATE_UNAVAILABLE + assert hass.states.get("switch.test_switch_0").state == STATE_UNAVAILABLE async def test_rpc_polling_connection_error( diff --git a/tests/components/shelly/test_cover.py b/tests/components/shelly/test_cover.py index 56740981fc5..08c0c76d35e 100644 --- a/tests/components/shelly/test_cover.py +++ b/tests/components/shelly/test_cover.py @@ -97,10 +97,10 @@ async def test_rpc_device_services( await hass.services.async_call( COVER_DOMAIN, SERVICE_SET_COVER_POSITION, - {ATTR_ENTITY_ID: "cover.test_name_test_cover_0", ATTR_POSITION: 50}, + {ATTR_ENTITY_ID: "cover.test_cover_0", ATTR_POSITION: 50}, blocking=True, ) - state = hass.states.get("cover.test_name_test_cover_0") + state = hass.states.get("cover.test_cover_0") assert state.attributes[ATTR_CURRENT_POSITION] == 50 mutate_rpc_device_status( @@ -109,11 +109,11 @@ async def test_rpc_device_services( await hass.services.async_call( COVER_DOMAIN, SERVICE_OPEN_COVER, - {ATTR_ENTITY_ID: "cover.test_name_test_cover_0"}, + {ATTR_ENTITY_ID: "cover.test_cover_0"}, blocking=True, ) mock_rpc_device.mock_update() - assert hass.states.get("cover.test_name_test_cover_0").state == STATE_OPENING + assert hass.states.get("cover.test_cover_0").state == STATE_OPENING mutate_rpc_device_status( monkeypatch, mock_rpc_device, "cover:0", "state", "closing" @@ -121,21 +121,21 @@ async def test_rpc_device_services( await hass.services.async_call( COVER_DOMAIN, SERVICE_CLOSE_COVER, - {ATTR_ENTITY_ID: "cover.test_name_test_cover_0"}, + {ATTR_ENTITY_ID: "cover.test_cover_0"}, blocking=True, ) mock_rpc_device.mock_update() - assert hass.states.get("cover.test_name_test_cover_0").state == STATE_CLOSING + assert hass.states.get("cover.test_cover_0").state == STATE_CLOSING mutate_rpc_device_status(monkeypatch, mock_rpc_device, "cover:0", "state", "closed") await hass.services.async_call( COVER_DOMAIN, SERVICE_STOP_COVER, - {ATTR_ENTITY_ID: "cover.test_name_test_cover_0"}, + {ATTR_ENTITY_ID: "cover.test_cover_0"}, blocking=True, ) mock_rpc_device.mock_update() - assert hass.states.get("cover.test_name_test_cover_0").state == STATE_CLOSED + assert hass.states.get("cover.test_cover_0").state == STATE_CLOSED async def test_rpc_device_no_cover_keys( @@ -144,7 +144,7 @@ async def test_rpc_device_no_cover_keys( """Test RPC device without cover keys.""" monkeypatch.delitem(mock_rpc_device.status, "cover:0") await init_integration(hass, 2) - assert hass.states.get("cover.test_name_test_cover_0") is None + assert hass.states.get("cover.test_cover_0") is None async def test_rpc_device_update( @@ -153,11 +153,11 @@ async def test_rpc_device_update( """Test RPC device update.""" mutate_rpc_device_status(monkeypatch, mock_rpc_device, "cover:0", "state", "closed") await init_integration(hass, 2) - assert hass.states.get("cover.test_name_test_cover_0").state == STATE_CLOSED + assert hass.states.get("cover.test_cover_0").state == STATE_CLOSED mutate_rpc_device_status(monkeypatch, mock_rpc_device, "cover:0", "state", "open") mock_rpc_device.mock_update() - assert hass.states.get("cover.test_name_test_cover_0").state == STATE_OPEN + assert hass.states.get("cover.test_cover_0").state == STATE_OPEN async def test_rpc_device_no_position_control( @@ -168,4 +168,4 @@ async def test_rpc_device_no_position_control( monkeypatch, mock_rpc_device, "cover:0", "pos_control", False ) await init_integration(hass, 2) - assert hass.states.get("cover.test_name_test_cover_0").state == STATE_OPEN + assert hass.states.get("cover.test_cover_0").state == STATE_OPEN diff --git a/tests/components/shelly/test_init.py b/tests/components/shelly/test_init.py index 1fdfc9d4304..2ead9cba198 100644 --- a/tests/components/shelly/test_init.py +++ b/tests/components/shelly/test_init.py @@ -195,7 +195,7 @@ async def test_sleeping_rpc_device_online_new_firmware( ("gen", "entity_id"), [ (1, "switch.test_name_channel_1"), - (2, "switch.test_name_test_switch_0"), + (2, "switch.test_switch_0"), ], ) async def test_entry_unload( @@ -218,7 +218,7 @@ async def test_entry_unload( ("gen", "entity_id"), [ (1, "switch.test_name_channel_1"), - (2, "switch.test_name_test_switch_0"), + (2, "switch.test_switch_0"), ], ) async def test_entry_unload_device_not_ready( @@ -246,7 +246,7 @@ async def test_entry_unload_not_connected( entry = await init_integration( hass, 2, options={CONF_BLE_SCANNER_MODE: BLEScannerMode.ACTIVE} ) - entity_id = "switch.test_name_test_switch_0" + entity_id = "switch.test_switch_0" assert entry.state is ConfigEntryState.LOADED assert hass.states.get(entity_id).state is STATE_ON @@ -272,7 +272,7 @@ async def test_entry_unload_not_connected_but_we_think_we_are( entry = await init_integration( hass, 2, options={CONF_BLE_SCANNER_MODE: BLEScannerMode.ACTIVE} ) - entity_id = "switch.test_name_test_switch_0" + entity_id = "switch.test_switch_0" assert entry.state is ConfigEntryState.LOADED assert hass.states.get(entity_id).state is STATE_ON diff --git a/tests/components/shelly/test_light.py b/tests/components/shelly/test_light.py index ab631516ec2..69d0fccf421 100644 --- a/tests/components/shelly/test_light.py +++ b/tests/components/shelly/test_light.py @@ -385,25 +385,25 @@ async def test_rpc_device_switch_type_lights_mode( await hass.services.async_call( LIGHT_DOMAIN, SERVICE_TURN_ON, - {ATTR_ENTITY_ID: "light.test_name_test_switch_0"}, + {ATTR_ENTITY_ID: "light.test_switch_0"}, blocking=True, ) - assert hass.states.get("light.test_name_test_switch_0").state == STATE_ON + assert hass.states.get("light.test_switch_0").state == STATE_ON mutate_rpc_device_status(monkeypatch, mock_rpc_device, "switch:0", "output", False) await hass.services.async_call( LIGHT_DOMAIN, SERVICE_TURN_OFF, - {ATTR_ENTITY_ID: "light.test_name_test_switch_0"}, + {ATTR_ENTITY_ID: "light.test_switch_0"}, blocking=True, ) mock_rpc_device.mock_update() - assert hass.states.get("light.test_name_test_switch_0").state == STATE_OFF + assert hass.states.get("light.test_switch_0").state == STATE_OFF async def test_rpc_light(hass: HomeAssistant, mock_rpc_device, monkeypatch) -> None: """Test RPC light.""" - entity_id = f"{LIGHT_DOMAIN}.test_name_test_light_0" + entity_id = f"{LIGHT_DOMAIN}.test_light_0" monkeypatch.delitem(mock_rpc_device.status, "switch:0") await init_integration(hass, 2) diff --git a/tests/components/shelly/test_sensor.py b/tests/components/shelly/test_sensor.py index 630ee551e89..892d06ad626 100644 --- a/tests/components/shelly/test_sensor.py +++ b/tests/components/shelly/test_sensor.py @@ -264,7 +264,7 @@ async def test_block_sensor_unknown_value( async def test_rpc_sensor(hass: HomeAssistant, mock_rpc_device, monkeypatch) -> None: """Test RPC sensor.""" - entity_id = f"{SENSOR_DOMAIN}.test_name_test_cover_0_power" + entity_id = f"{SENSOR_DOMAIN}.test_cover_0_power" await init_integration(hass, 2) assert hass.states.get(entity_id).state == "85.3" diff --git a/tests/components/shelly/test_switch.py b/tests/components/shelly/test_switch.py index a53c5dc185b..115ad5edabb 100644 --- a/tests/components/shelly/test_switch.py +++ b/tests/components/shelly/test_switch.py @@ -152,20 +152,20 @@ async def test_rpc_device_services( await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, - {ATTR_ENTITY_ID: "switch.test_name_test_switch_0"}, + {ATTR_ENTITY_ID: "switch.test_switch_0"}, blocking=True, ) - assert hass.states.get("switch.test_name_test_switch_0").state == STATE_ON + assert hass.states.get("switch.test_switch_0").state == STATE_ON monkeypatch.setitem(mock_rpc_device.status["switch:0"], "output", False) await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, - {ATTR_ENTITY_ID: "switch.test_name_test_switch_0"}, + {ATTR_ENTITY_ID: "switch.test_switch_0"}, blocking=True, ) mock_rpc_device.mock_update() - assert hass.states.get("switch.test_name_test_switch_0").state == STATE_OFF + assert hass.states.get("switch.test_switch_0").state == STATE_OFF async def test_rpc_device_switch_type_lights_mode( @@ -176,7 +176,7 @@ async def test_rpc_device_switch_type_lights_mode( mock_rpc_device.config["sys"]["ui_data"], "consumption_types", ["lights"] ) await init_integration(hass, 2) - assert hass.states.get("switch.test_name_test_switch_0") is None + assert hass.states.get("switch.test_switch_0") is None @pytest.mark.parametrize("exc", [DeviceConnectionError, RpcCallError(-1, "error")]) @@ -191,7 +191,7 @@ async def test_rpc_set_state_errors( await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, - {ATTR_ENTITY_ID: "switch.test_name_test_switch_0"}, + {ATTR_ENTITY_ID: "switch.test_switch_0"}, blocking=True, ) @@ -212,7 +212,7 @@ async def test_rpc_auth_error( await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, - {ATTR_ENTITY_ID: "switch.test_name_test_switch_0"}, + {ATTR_ENTITY_ID: "switch.test_switch_0"}, blocking=True, ) await hass.async_block_till_done() diff --git a/tests/components/shelly/test_utils.py b/tests/components/shelly/test_utils.py index 53fc77ed6ef..1bf660deb2a 100644 --- a/tests/components/shelly/test_utils.py +++ b/tests/components/shelly/test_utils.py @@ -58,7 +58,7 @@ async def test_block_get_block_channel_name(mock_block_device, monkeypatch) -> N mock_block_device, mock_block_device.blocks[DEVICE_BLOCK_ID], ) - == "Channel 1" + == "Test name channel 1" ) monkeypatch.setitem(mock_block_device.settings["device"], "type", "SHEM-3") @@ -68,7 +68,7 @@ async def test_block_get_block_channel_name(mock_block_device, monkeypatch) -> N mock_block_device, mock_block_device.blocks[DEVICE_BLOCK_ID], ) - == "Channel A" + == "Test name channel A" ) monkeypatch.setitem( @@ -207,7 +207,7 @@ async def test_get_block_input_triggers(mock_block_device, monkeypatch) -> None: async def test_get_rpc_channel_name(mock_rpc_device) -> None: """Test get RPC channel name.""" assert get_rpc_channel_name(mock_rpc_device, "input:0") == "test switch_0" - assert get_rpc_channel_name(mock_rpc_device, "input:3") == "Switch 3" + assert get_rpc_channel_name(mock_rpc_device, "input:3") == "Test name switch_3" async def test_get_rpc_input_triggers(mock_rpc_device, monkeypatch) -> None: