esphome / issues

Issue Tracker for ESPHome
https://esphome.io/
290 stars 34 forks source link

!include yaml using sensor platform template not shown in UI of Home Assistant #4286

Open tdy91 opened 1 year ago

tdy91 commented 1 year ago

The problem

Hi,

Including a sensor "-platform: template" section using "<<: !include" directive as explained on https://esphome.io/guides/configuration-types.html never create corresponding sensor entity in Home Assistant User Interface.

To reproduce, using the example described belon in "Details Example YAML snippet" section, sensor.foo will appear in Home Assistant, but sensor.bar does not !

I think there is a bug.

It seems to be similar to automatically marked as stale issue #3360

Thanks by advance.

Which version of ESPHome has the issue?

ESPHome 2023.2.4

What type of installation are you using?

Home Assistant Add-on

Which version of Home Assistant has the issue?

Home Assistant 2023.3.1

What platform are you using?

ESP8266

Board

ESP-01S

Component causing the issue

platform template

Example YAML snippet

MAIN FILE : esphome/iot.yaml
****************************
esphome:
  name: iot
  friendly_name: iot

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "+8WRiuCTpCmX8wuiT33C7wnhxBZGooKRdoO34Z0XbHA="

ota:
  password: "bd9ee5cc768cc4164ee4a000d5bf771c"

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

  # Optional manual IP
  manual_ip:
    static_ip: 192.168.1.18
    gateway: 192.168.1.254
    subnet: 255.255.255.0
    dns1: 192.168.1.254
    dns2: 192.168.1.30

  fast_connect: true # default false

  ap:
    ssid: "Iot Fallback Hotspot"
    password: "kxkdr7NOecJ2"

captive_portal:

sensor:

  - platform: template
    name: foo
    id: foo_id

<<: !include common/iot_platform_template_bar.yaml

INCLUDED FILE : esphome/common/iot_platform_template_bar.yaml
*************************************************************
sensor:
  - platform: template
    name: bar
    id: bar_id

Anything in the logs that might be useful for us?

I do not detect any error message.

Additional information

Results above were obtained on an Home Assistant OS installed on a virtual machine.

Trying to investigate, i installed EspHome on another Windows 10 computer in order to be able to run "esphome -v compile iot.yaml" command.

See attached file iot.zip which contains complete iot folder status after running this command :

tdy91 commented 1 year ago

In fact, using the following syntax, *sensor.foo and sensor.bar correctly appears in Home Assistant User Interface.

MAIN FILE : esphome/iot.yaml


esphome:
  name: iot
  friendly_name: iot

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "+8WRiuCTpCmX8wuiT33C7wnhxBZGooKRdoO34Z0XbHA="

ota:
  password: "bd9ee5cc768cc4164ee4a000d5bf771c"

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

  # Optional manual IP
  manual_ip:
    static_ip: 192.168.1.18
    gateway: 192.168.1.254
    subnet: 255.255.255.0
    dns1: 192.168.1.254
    dns2: 192.168.1.30

  fast_connect: true # default false

  ap:
    ssid: "Iot Fallback Hotspot"
    password: "kxkdr7NOecJ2"

captive_portal:

sensor:

  - platform: template
    name: foo
    id: foo_id

  - <<: !include common/iot_platform_template_bar.yaml

INCLUDED FILE : esphome/common/iot_platform_template_bar.yaml


#sensor:
  - platform: template
    name: bar
    id: bar_id
Unfocused commented 1 year ago

The code generation doesn't actually see any !include - the main YAML file and the extra files added via !include are processed all into one file first, and the output of that is read & used to generate the firmware code. So, whether or not a sensor is in a separate file included via !include is irrelevant (being a template sensor is also irrelevant). You can see the result of that step by running esphome config <filename> - this will show you the result of any !include (and some other advanced options like !include_dir_named - see the various options here), and any variable substitutions.

What's happening here is more of a misunderstanding of how YAML works: You're assuming it's smarter than it really is.

When you're adding in a second sensor: (from the included file), it's not smart enough to add it's contents to the original sensor:. Instead, it would result in a duplicate sensor: key. If you were to have two sensor: keys in a file normally (not using !include), it would fail and give a duplicate key error. The difference is, using !include doesn't give an error when you add a duplicate key (because it can be useful in some cases), but it still doesn't allow ducplicate keys. Instead, it sees the duplicate keys and only keeps one of them - the key in the parent file takes priority. See example 1 below.

The reason why your second example works as expected is because it's just adding content to an item in the array under sensor:. See example 2 below.

However, there is a way to include your other file as-is - using packages:, which is smart enough to know how to merge things as you expect (see documentation here). Packages are what I use to structure my files - I use them extensively, and it works really well. See example 3 below.

Note that the problems described in #3360 are slightly different again - but it's also due to misunderstanding YAML and <<: (and how it interacts with YAML's keys and arrays). The recommended solution there would also be to use packages.

Example 1 - broken

This is your first example, which didn't work as you expected.

If you have main.yaml:

sensor:
  - platform: template
    name: foo
    id: foo_id

<<: !include extra.yaml

And extra.yaml:

sensor:
  - platform: template
    name: bar
    id: bar_id

This is equivalent to writing:

sensor:
  - platform: template
    name: foo
    id: foo_id

sensor:
  - platform: template
    name: bar
    id: bar_id

If you were to run esphome config <filename> on that, it would give a duplicate key error.

But when you're using !include, the result will be:

sensor:
  - platform: template
    name: foo
    id: foo_id

Which is the sensor: from the parent file.

Example 2 - working, but awkward

This is your second example, which worked.

If you have main.yaml:

sensor:
  - platform: template
    name: foo
    id: foo_id
  - <<: !include extra.yaml

And extra.yaml:

platform: template
name: bar
id: bar_id

The result will be:

sensor:
  - platform: template
    name: foo
    id: foo_id
  - platform: template
    name: bar
    id: bar_id

Example 3 - using packages

This is how to have it work as you expect, using packages.

If you have main.yaml:

packages:
  extrapkg: !include extra.yaml

sensor:
  - platform: template
    name: foo
    id: foo_id

And extra.yaml:

sensor:
  - platform: template
    name: bar
    id: bar_id

The result will be:

sensor:
  - platform: template
    name: foo
    id: foo_id
  - platform: template
    name: bar
    id: bar_id

The key name for the package (in this example "extrapkg") can be anything you want - it just has to be unique.