Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error logged while rounding missing humidity values on device registration #131837

Open
JRInge opened this issue Nov 28, 2024 · 4 comments
Open

Comments

@JRInge
Copy link

JRInge commented Nov 28, 2024

The problem

The climate integration logs errors when an ESPHome climate device that takes a humidity input from Home Assistant is restarted. The error appears to occur because the humidity value unknown at startup. The ESPHome integration in Home Assistant sets the current_humidity attribute of the climate entity to nan. When Home Assistant tries to read this value, the ESPHome integration tries to round it to an integer result. As nan is a float, this throws an error.

What version of Home Assistant Core has the issue?

core-2024.11.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

config_entry-esphome-01JDS82XRM5QPX250XAJFJJG18.json

Example YAML snippet

---
# Minimal ESPHome configuration to reproduce problem
esphome:
  name: thermo2

esp32:
  board: esp32dev
  framework:
    type: esp-idf

# Enable Home Assistant API
api:
  encryption:
    key: "xxx"

ota:
  - platform: esphome
    password: "xxx"

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

logger:

sensor:
  # Import current temperature from Home Assistant
  # Filtered to try to avoid outputing NaN (didn't solve problem)
  - platform: homeassistant
    id: current_temp
    entity_id: sensor.thermostat_input_temperature
    filters: 
      - filter_out: 
          - NaN
  - platform: homeassistant
    id: current_humidity
    entity_id: sensor.landing_humidity
    filters: 
      - filter_out: 
          - NaN

climate:
  - platform: thermostat
    id: controller
    name: Thermostat
    sensor: current_temp
    humidity_sensor: current_humidity
    heat_action:
      - switch.turn_on: boiler
    idle_action:
      - switch.turn_off: boiler
    min_idle_time: 30s
    min_heating_off_time: 300s
    min_heating_run_time: 300s

switch:
  - platform: output
    id: boiler
    icon: mdi:water-boiler
    output: relay_1
    name: Boiler

output:
  # Physical relay on GPIO
  - platform: gpio
    pin: GPIO26
    id: relay_1
...

Anything in the logs that might be useful for us?

Logger: homeassistant.components.esphome.entry_data
Source: components/esphome/entry_data.py:395
integration: ESPHome (documentation, issues)
First occurred: 27 November 2024 at 21:05:03 (10 occurrences)
Last logged: 13:17:55

Error while calling subscription
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/esphome/entry_data.py", line 395, in async_update_state
    subscription()
  File "/usr/src/homeassistant/homeassistant/components/esphome/entity.py", line 295, in _on_state_update
    self.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1007, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1132, in _async_write_ha_state
    self.__async_calculate_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1071, in __async_calculate_state
    if state_attributes := self.state_attributes:
                           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/climate/__init__.py", line 324, in __getattribute__
    return super().__getattribute__(__name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/climate/__init__.py", line 549, in state_attributes
    if (current_humidity := self.current_humidity) is not None:
                            ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/climate/__init__.py", line 324, in __getattribute__
    return super().__getattribute__(__name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/esphome/entity.py", line 127, in _wrapper
    return func(self) if self._has_state else None
           ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/esphome/climate.py", line 242, in current_humidity
    return round(self._state.current_humidity)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: cannot convert float NaN to integer

Additional information

The cause of the issue seems to be in the getter function for the current_humidity method, which is supposed to return an int:

def current_humidity(self) -> int | None:

It either needs to return None when self._state.current_humidity is nan, or perhaps return a float rather than an int (I'm not sure what propagating the nan would do in the latter case.

Adding this code before the final return statement might fix it:

if type(self._state.current_humidity) == float and math.isnan(self._state.current_humidity):
    return None
@home-assistant
Copy link

Hey there @OttoWinter, @jesserockz, @kbx81, @bdraco, 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.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component) to the issue.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component) on the issue.

(message by CodeOwnersMention)


esphome documentation
esphome source
(message by IssueLinks)

@joostlek
Copy link
Member

Why is the value NaN in the first place?

@JRInge
Copy link
Author

JRInge commented Nov 28, 2024

Because the ESPHome device doesn't have a physical sensors, the climate component on the ESP32 gets its humidity value from a Home Assistant sensor component, then reports the same value back to HA as an attribute of the climate entity. I think that the ESPHome integration in HA probably has to register the ESPHome device before it can supply it with the current reading, so the climate entity in HA is initialized with missing values. Registration is mentioned in the HA error log.

I've checked the ESP32 device logs, and as far as I can tell, it doesn't seem to be a case of the ESP32 actually outputting a NaN. I would guess that the same thing happens with temperature (another value imported to the ESP32 from HA), but doesn't cause problems because temperature is float rather than int, so doesn't get rounded.

@JRInge
Copy link
Author

JRInge commented Nov 29, 2024

I checked the ESPHome logs in more detail. In my setup, the ESPHome thermostat climate component sensor and humity_sensor settings are both Home Assistant sensors rather than onboard the device. When the ESP32 connects to HA, HA tells it the value of the temperature sensor first. On receiving the temperature value, ESPHome publishes an update to the climate entity to HA, including the current temperature as an attribute. At this point, ESPHome hasn't received the humidity value, so that attribute is nan. Next the Home Assistant integration sends the humidity value, and ESPHome responds with valid values for both humidity and temperature. Here's the relevant log section:

[19:06:23][D][api.connection:1446]: Home Assistant 2024.11.3 (192.168.0.136): Connected successfully
[19:06:24][D][homeassistant.sensor:024]: 'sensor.thermostat_input_temperature': Got state 20.40
[19:06:24][D][sensor:094]: 'current_temp': Sending state 20.40000  with 1 decimals of accuracy
[19:06:24][D][climate:396]: 'Thermostat' - Sending state:
[19:06:24][D][climate:399]:   Mode: OFF
[19:06:24][D][climate:401]:   Action: OFF
[19:06:24][D][climate:419]:   Current Temperature: 20.40°C
[19:06:24][D][climate:425]:   Target Temperature: 10.00°C
[19:06:24][D][climate:428]:   Current Humidity: nan%
[19:06:24][D][homeassistant.sensor:024]: 'sensor.landing_humidity': Got state 56.00
[19:06:24][D][sensor:094]: 'current_humidity': Sending state 56.00000  with 1 decimals of accuracy
[19:06:24][D][climate:396]: 'Thermostat' - Sending state:
[19:06:24][D][climate:399]:   Mode: OFF
[19:06:24][D][climate:401]:   Action: OFF
[19:06:24][D][climate:419]:   Current Temperature: 20.40°C
[19:06:24][D][climate:425]:   Target Temperature: 10.00°C
[19:06:24][D][climate:428]:   Current Humidity: 56
```%

I think that the proper fix would be to make sure that the ESPHome integration can handle the `nan` at the Home Assistant end.  However, an alternative would be to edit the thermostat component in ESPHome itself, so that it doesn't send attributes with invalid values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants