home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
72.4k stars 30.3k forks source link

ESPHome integration does not prepend device name to sensor/switch names when friendly_name is not set in the ESPHome YAML #94118

Closed wrouesnel closed 1 year ago

wrouesnel commented 1 year ago

The problem

The ESPHome integration does not append the device name to sensor or switch names like other integrations such as Govee do. Leading to a situation like this:

image

There are 3 devices here - Washing Machine, Dryer, Light - and they are named as such.

However, these names are not appended to the sensor outputs, which are instead identical.

The Govee integration handles this correctly - if the name is default and there's no other names, then it's removed. If the device name is set to a specific value, then that is appended.

The expected outcome here would be instead of:

that we'd get

What version of Home Assistant Core has the issue?

core-2023.5.3

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant Container

Integration causing the issue

ESPHome

Link to integration documentation on our website

https://www.home-assistant.io/integrations/esphome/

Diagnostics information

No response

Example YAML snippet

No response

Anything in the logs that might be useful for us?

No response

Additional information

No response

home-assistant[bot] commented 1 year ago

Hey there @ottowinter, @jesserockz, mind taking a look at this issue as it has been labeled with an integration (esphome) you are listed as a code owner for? Thanks!

Code owner commands Code owners of `esphome` can trigger bot actions by commenting: - `@home-assistant close` Closes the issue. - `@home-assistant rename Awesome new title` Renames the issue. - `@home-assistant reopen` Reopen the issue. - `@home-assistant unassign esphome` Removes the current integration label and assignees on the issue, add the integration domain after the command.

(message by CodeOwnersMention)


esphome documentation esphome source (message by IssueLinks)

j4n-e4t commented 1 year ago

Could you please provide a bit more information on how you configured ESPHome itself and the HA integration? Also, did you try to update Home Assistant to the latest version (2023.05.04)?

wrouesnel commented 1 year ago

I've upgraded just now to core-2023.5.4 and the problem remains.

The HA integration has no special configuration - devices are added via "Add Integration" with the IP address being entered manually.

ESPHome is running completely separately as it's own docker container.

The problem appears to be that the ESPHome Integration in HA does not use the device-name logic that other integration (namely Govee since I have direct experience and it works as you'd want) do.

EDIT: To be clear - these ESPHome devices do not include the "friendly name" substitution in the variables they export themselves, but this is intentional - I shouldn't need to flash room name's to my actual devices to get them to work (since they might move around - i.e. if I unplug a smart plug, I should be able to just update the location/name in HA).

EDIT 2:

For example, using Govee thermometers, I get this in the Overview with two of them in the same room:

image

One device is un-named, and the other is labelled "Cot". The effect is that it is clear which is which. I have not had to rename any entities to achieve this.

j4n-e4t commented 1 year ago

Ok, thank you for the clarification. I’ll check that later.

j4n-e4t commented 1 year ago

With this config, I was able to reproduce the issue:

esphome:
  name: esp_test
  platform: ESP32
  board: nodemcu-32s

# Enable logging
logger:

# Enable Home Assistant API
api:

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

captive_portal:

web_server:
  port: 80

sensor:
  # Just an unnamed sensor to have an example
  - platform: uptime
    name: Uptime
    filters:
      - lambda: return x / 3600;
    unit_of_measurement: "hours"
    accuracy_decimals: 2

But I might have an idea on how to fix it: Maybe we could add an name property to the ESPHomeSensor class that overwrites the existing one. This would allow to set a name for the sensor. This would allow to first check, if there is a friendly_name set and if not, it'd use the device_name instead to make it unique and identifiable.

EDIT: Sensor is just an example here. This would probably need to be changed for all domains that ESPHome supports.

wrouesnel commented 1 year ago

It's worth noting that the Athom devices I am using come with an initial configuration like here: https://github.com/athom-tech/athom-configs/blob/main/athom-smart-plug-v2.yaml

Which transposed to your example defaults to something like:

substitutions:
  friendly_name: "Vendor Name"

esphome:
  name: esp_test
  platform: ESP32
  board: nodemcu-32s

# Enable logging
logger:

# Enable Home Assistant API
api:

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

captive_portal:

web_server:
  port: 80

sensor:
  # Just an unnamed sensor to have an example
  - platform: uptime
    name: "${friendly_name} uptime"
    filters:
      - lambda: return x / 3600;
    unit_of_measurement: "hours"
    accuracy_decimals: 2

The behavior that it seems should happen is that even if friendly_name is set, the displayed name should include device_name if it is not unique within the area it's been added to (and not set explicitly for the entity).

jgverweij commented 1 year ago

The Atom example configuration uses substitutions: for the friendly_name, and it is added manually via templates to the sensor names.

Since some time this is not necessary anymore if friendly_name is added under the esphome: section.

Configuration variables:

name (Required, string): This is the name of the node. It should always be unique in your ESPHome network. May only contain lowercase characters, digits and hyphens, and can be at most 24 characters long by default, or 31 characters long if name_add_mac_suffix is false.

friendly_name (Optional, string): This is the name sent to the frontend. It is used by Home Assistant as the integration name, device name, and is automatically prefixed to entities where necessary.

So you might consider to set the friendly_name here, and for your case perhaps set to the same value as the name itself.

esphome:
  name: esp_test
  friendly_name: esp_test

...

sensor:
  # Just an unnamed sensor to have an example
  - platform: uptime
    name: "uptime"
    filters:
      - lambda: return x / 3600;
    unit_of_measurement: "hours"
    accuracy_decimals: 2
j4n-e4t commented 1 year ago

So, you think this isn't an issue with the integration but rather a config change in ESPHome?

jgverweij commented 1 year ago

So, you think this isn't an issue with the integration but rather a config change in ESPHome?

At least this is the standard behaviour for ESPHome. You are able to define the name that is used in the frontend yourself.

By means of providing friendly_name in the esphome: section, Home Assistant adds it as a prefix which enables to distinguish between entities from different devices.

I do not know about the behaviour of Govee. In general renaming devices in Home Assistant might influence the display name.

wrouesnel commented 1 year ago

I can set friendly_name and reflash the plugs, that's fine it just seems like a dramatic step for them - i.e. reprogramming the plugs themselves.

The issue is that the "automatic" friendly name displayed in Home Assistant should at least try and de-conflict within integrations when there's an obvious key - i.e. in my case I named the devices what they are in the UI, but the automatic displayed names are indistinguishable.

I mention the Govee plugin because this seems to somehow get it exactly right in the way I'd expect - setting a device name renames the entity, which then hides the name if it matches the area.

i.e. it appears that naming a Govee device Laundry and then putting in a zone named Laundry means that the entities are given automatic friendly names of just Temperature and Humidity. But if I name it Cot and put it in Bedroom, then they display as Cot Temperature and Cot Humidity - which for the Overview and most modes, is exactly what I want.

Ideally ESPHome devices would work similarly - setting a device name would mean the automatic entity name has that entity name prepended, unless the device name is identical to whatever's already prepended.

So naming a smart plug Washing Machine should result in an automatic entity display name of Washing Machine Power...unless the entity is being sent with a name of Washing Machine Power already.

Because the typical use-case I imagine (certainly my use case) is that I bought a bunch of pre-flashed Athom plugs, got them into Home Assistant with no trouble at all, and could use them right away...but I had multiple devices with Power and Energy in my overview (and in the energy dashboard).

EDIT: I will note there seems to be a separate issue as well which is that entity name generation from ESPHome doesn't seem to work properly either - all my smartplugs come out as sensor.voltage_2 and sensor.voltage_3 which seems to have caused some issues for others on the forums. Since the name in ESPhome is meant to be unique, I would've expected a plug named sp-laundry-dryer to result in entity names of sensor.sp-laundry-dryer_voltage - which is another thing the Govee integration does right - my thermometer called H5075 6BB9 gets entity names like sensor.h5075_6bb9_humidity.

wrouesnel commented 1 year ago

Okay so some additional testing finds that if friendly_name is set on the device then it looks like things get handled properly. This prompts the device to appear under the ESPHome integration with that name too - but, if I rename the device manually at the integration level -

image

then even after a restart there'll be no change.

Renaming the device by clicking through to the device and doing "rename" also leads to no change.

However, if I flash friendly_name to the device itself, and then restart Home Assistant then the correct name will be displayed - i.e. on the device info page I get:

image

and on the overview page I get

image

Interestingly, if I update the device name in Home Assistant on the device page (i.e. change it from Dryer to Not A Dryer) in Home Assistant then I get correct behavior - i.e.

image

and then changing it back restores the name.

So the entire problem might be to do with the friendly_name in ESPHome not being set (or sent?) which seems to disable all the device name appending code. Whereas if I send any type of friendly_name then things work fine.

So I would conclude this is a problem on the Home Assistant side: when friendly_name isn't sent, whatever code looks at that isn't substituting in name correctly. That change would, I suspect, fix everything (give or take the devices currently out there which likely push variables with the substitution ${friendly_name} Some Variable as the smartplugs were originally flashed.

bdraco commented 1 year ago

Likely https://github.com/home-assistant/core/issues/77150 is the same issue since there is no friendly name there either

bdraco commented 1 year ago

If friendly name is set, the friendly name is prepended to entity friendly name

If friendly name is not set than its not prepended

https://github.com/home-assistant/core/blob/d973e43b9013f4c4959c00e264a467fec2514f2e/homeassistant/components/esphome/entity.py#L167

This is working as designed, and changing the behavior would be a breaking change which is something we don't want to entertain as there is always a way to achieve the desired functionality by adding a friendly_name to the ESPHome configuration and reflashing.

bdraco commented 1 year ago

I dug into this some more and there is a regression here.

bdraco commented 1 year ago

It turns out this was a conscious decision to require friendly_name to be set to opt-in. As such the fix for this is being reverted in https://github.com/home-assistant/core/pull/97488

I'm going to change this to close as not planned instead.

Sorry for the confusion