rgc99 / irrigation_unlimited

♒Irrigation controller for Home Assistant
MIT License
333 stars 49 forks source link

Exception in callback Entity._async_write_ha_state_from_call_soon_threadsafe() #190

Open Kolia56 opened 1 week ago

Kolia56 commented 1 week ago

Version of the custom_component: 2024.10.0

Configuration


irrigation_unlimited:
    - name: "Controleur 1"
      all_zones_config:
        show:
          timeline: true
        allow_manual: true
        volume:
          entity_id: sensor.556
        # duration: "0:10:00"
          volume_scale: 1000
          flow_rate_scale: 60
          flow_rate_precision: 1
      zones:
        - name: Test
          zone_id: "1"
          # entity_id: switch.562
          enabled: false
          entity_id: switch.ev_id1
          # check_back:
          #   delay: 3
          #   retries: 1
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id1_ack
          maximum: "00:50:00"
        - name: Café François
          zone_id: "2"
          # entity_id: switch.562
          entity_id: switch.ev_id2
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id2_ack
          maximum: "00:50:00"
        - name: Serre
          zone_id: "3"
          # entity_id: switch.564
          entity_id: switch.ev_id3
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id3_ack
          maximum: "00:35:00"
        - name: If Cour carrée
          # entity_id: switch.565
          entity_id: switch.ev_id4
          zone_id: "4"
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id4_ack
          maximum: "00:20:00"          
        - name: Pare-terre Julie 
          zone_id: "6"
          # entity_id: switch.569
          entity_id: switch.ev_id6
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id6_ack
          maximum: "00:50:00"
        # - name: Pelouse
        #   zone_id: "7"
        #   # entity_id : switch.566
        #   entity_id : switch.ev_id7
        #   check_back:
        #     delay: 10
        #     retries: 3
        #     resync: true
        #     toggle: false
        #     entity_id: input_boolean.ev_id7_ack
        #   maximum: "01:00:00"
        - name: Deux carrés
          zone_id: "9"
          # entity_id: switch.713
          entity_id: switch.ev_id9
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id9_ack
          maximum: "00:50:00"
        - name: Un carré
          zone_id: "10"
          # entity_id: switch.714
          entity_id: switch.ev_id10
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id10_ack
          maximum: "00:30:00"
        - name: Petits fruits
          zone_id: "11"
          # entity_id: switch.715
          entity_id: switch.ev_id11
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id11_ack
          maximum: "00:50:00"
        - name: Haie - Céanothe - Fleurs
          zone_id: "12"
          # entity_id: switch.716
          entity_id: switch.ev_id12
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id12_ack
          maximum: "01:00:00"
        - name: Pommiers
          # entity_id: switch.717
          entity_id: switch.ev_id13
          zone_id: "13"
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id13_ack
          maximum: "00:50:00"

        - name: Haies pelouses
          zone_id: "14"
          # entity_id: switch.718
          entity_id: switch.ev_id14
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id14_ack
          maximum: "00:45:00"

        - name: Haie du fond
          zone_id: "15"
          # entity_id: switch.719
          entity_id: switch.ev_id15
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id15_ack
          maximum: "01:00:00"
        - name: Tilleul
          zone_id: "16"
          # entity_id: switch.720
          entity_id: switch.ev_id16
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id16_ack
          maximum: "00:50:00"
        - name: Bordure pelouse
          zone_id: "17"
          # entity_id: switch.720
          entity_id: switch.ev_id17
          # check_back:
          #   delay: 15
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id17_ack
          maximum: "00:40:00"
        - name: Circulaire pelouse
          zone_id: "18"
          # entity_id: switch.720
          entity_id: switch.ev_id18
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id18_ack
          maximum: "01:00:00"
        - name: Circulaire statue
          zone_id: "19"
          # entity_id: switch.720
          entity_id: switch.ev_id19
          # check_back:
          #   delay: 10
          #   retries: 3
          #   resync: true
          #   toggle: false
          #   entity_id: input_boolean.ev_id19_ack
          maximum: "01:00:00"
      sequences:
      - name: nuit
        enabled: true
        schedules:
          - name: 1
            time: "22:00"
            schedule_id: "s1"
        delay : 15
        zones:
          - zone_id: "2" # Café François (id2)
            duration: "00:30"
            # volume: 30
          - zone_id: "3" # Serre et autres (id3)
            duration: "00:15"
            # volume: 30
          - zone_id: "6" # Pare-terre Julie (id6)
            duration: "00:40"
            # volume: 20
          - zone_id: "9" # Deux carrés (id8)
            duration: "00:25"
          - zone_id: "10" # Un carré (id9)
            duration: "00:18"
          - zone_id: "11" # Petits fruits (id10)
            duration: "00:40"
          - zone_id: "12" # Haie - Céanothe (id11)
            duration: "00:40"
          - zone_id: "13" # Pommiers (id12)
            duration: "00:25"
          - zone_id: "14" # Haies pelouse (id13)
            duration: "00:20"
          - zone_id: "4" # If cour carrée (id4)
            duration: "00:10"
          - zone_id: "15" # Haie du fond (id15)
            duration: "00:25"            
          - zone_id: "16" # Tilleul - Cerisier (id16)
            duration: "00:25"    
          - zone_id: "17" # Bordure pelouse
            duration: "00:15"
            # volume: 150
          - zone_id: "18" # Pelouse (id7)
            duration: "00:20"
            # volume: 200
          - zone_id: "19" # circulaire statue
            duration: "00:20"
            # volume: 200
      - name: jour
        enabled: true
        duration: "00:05"
        delay: "03:25"
        repeat: 2
        schedules: 
          - name: 2
            time: "12:00"
            schedule_id: "s2"
        zones:
          - zone_id: 3

    - name: "Controleur 2"
      all_zones_config:
        show:
          timeline: false
        allow_manual: true
      zones:
        - name: Aérateur bac
          zone_id: "1"
          entity_id: switch.aerateur_bac
      sequences:
      - name: Bac
        schedules:
          - name: "bac"
            time: "07:00"
            schedule_id: "bac"
        zones:
          - zone_id: 1 # bac
            duration: "00:50"
            delay: "01:40"
            repeat: 6

Describe the bug

The following error is logged repeatedly in the main log error journal. Both controllers are currently off.

Debug log

These messages are very important in helping to determine the problem. Go into Settings -> System -> Logs. In the search box put in irrigation_unlimited (Note the underscore between the two words) and press the LOAD FULL LOGS button. Copy and paste below.

This error originated from a custom integration.

Logger: homeassistant
Source: custom_components/irrigation_unlimited/binary_sensor.py:334
integration: Irrigation Unlimited (documentation, issues)
First occurred: November 13, 2024 at 07:50:00 (20 occurrences)
Last logged: 17:50:30

Error doing job: Exception in callback Entity._async_write_ha_state_from_call_soon_threadsafe() (None)
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 996, in _async_write_ha_state_from_call_soon_threadsafe
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1130, in _async_write_ha_state
    self.__async_calculate_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1071, in __async_calculate_state
    if extra_state_attributes := self.extra_state_attributes:
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/irrigation_unlimited/binary_sensor.py", line 334, in extra_state_attributes
    f"{current.current_zone.sequence_repeat + 1}/{self._sequence.repeat}"
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'sequence_repeat'
rgc99 commented 1 week ago

Sequence jour is causing this. It's a sequence with a repeat and one zone and a delay. The fix is in the repository if you want to update.

Cheers

Kolia56 commented 1 week ago

I installed the dev version. There is a major issue: all actions (formerly services) are gone. I reverted back to 2024.10.0 and actions are back. I did the test twice and I confirm the regression. In the meantime I upgraded HA to 2024.11.2 and the initial issue has disappeared. I'm quite puzzled.

rgc99 commented 6 days ago

What version of HA were you on before the upgrade to 2024.11.2?

Kolia56 commented 5 days ago

Not too sure, not very far away, at least 2024.9 I guess

rgc99 commented 4 days ago

Odd, that's the release I am currently testing against.

Kolia56 commented 3 days ago

It's back, currently running HA 2024.11.2 and irrigation unlimited 2024.10.0. Shall I upgrade to 2024.11.0? I will have no irrigation run for nearly 6 months, not very far away from winter, and today it's like winter already.

This error originated from a custom integration.

Logger: homeassistant
Source: custom_components/irrigation_unlimited/binary_sensor.py:334
integration: Irrigation Unlimited (documentation, issues)
First occurred: November 18, 2024 at 07:50:00 (32 occurrences)
Last logged: 07:50:30

Error doing job: Exception in callback Entity._async_write_ha_state_from_call_soon_threadsafe() (None)
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 998, in _async_write_ha_state_from_call_soon_threadsafe
    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 1073, in __async_calculate_state
    if extra_state_attributes := self.extra_state_attributes:
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/irrigation_unlimited/binary_sensor.py", line 334, in extra_state_attributes
    f"{current.current_zone.sequence_repeat + 1}/{self._sequence.repeat}"
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'sequence_repeat'
rgc99 commented 2 days ago

Please update irrigation unlimited from the repository. I have it running here on HA 2024.11.2.

Hint: A way to shut down the irrigation and leave the system running for testing is to comment out the zone entity_id: lines. I do this for testing configurations.

Kolia56 commented 2 days ago

HA 2024.11.2. I just upgraded to the dev branch. There are a few issues:

Setup of package 'irrigation_configuration' at packages/irrigation/irrigation_configuration.yaml, line 19 failed: Integration irrigation_unlimited caused error: cannot import name 'DATA_INSTANCE' from 'homeassistant.components.recorder.const' (/usr/src/homeassistant/homeassistant/components/recorder/const.py)

```txt
Logger: homeassistant.util.loop
Source: util/loop.py:136
First occurred: 21:19:45 (1 occurrences)
Last logged: 21:19:45

Detected blocking call to import_module with args ('custom_components.irrigation_unlimited',) inside the event loop by integration 'mqtt' at homeassistant/components/mqtt/__init__.py, line 239: hass_config = await conf_util.async_hass_config_yaml(hass) (offender: /usr/src/homeassistant/homeassistant/loader.py, line 1071: ComponentProtocol, importlib.import_module(self.pkg_path)), please create a bug report at https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+mqtt%22 For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#import_module Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/src/homeassistant/homeassistant/__main__.py", line 223, in <module> sys.exit(main()) File "/usr/src/homeassistant/homeassistant/__main__.py", line 209, in main exit_code = runner.run(runtime_conf) File "/usr/src/homeassistant/homeassistant/runner.py", line 189, in run return loop.run_until_complete(setup_and_run_hass(runtime_config)) File "/usr/local/lib/python3.12/asyncio/base_events.py", line 674, in run_until_complete self.run_forever() File "/usr/local/lib/python3.12/asyncio/base_events.py", line 641, in run_forever self._run_once() File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1990, in _run_once handle._run() File "/usr/local/lib/python3.12/asyncio/events.py", line 88, in _run self._context.run(self._callback, *self._args) File "/usr/src/homeassistant/homeassistant/config_entries.py", line 783, in async_setup_locked await self.async_setup(hass, integ
ration=integration) File "/usr/src/homeassistant/homeassistant/config_entries.py", line 546, in async_setup await self.__async_setup_with_context(hass, integration) File "/usr/src/homeassistant/homeassistant/config_entries.py", line 635, in __async_setup_with_context result = await component.async_setup_entry(hass, self) File "/usr/src/homeassistant/homeassistant/components/mqtt/__init__.py", line 272, in async_setup_entry mqtt_data, conf = await _setup_client(client_available) File "/usr/src/homeassistant/homeassistant/components/mqtt/__init__.py", line 239, in _setup_client hass_config = await conf_util.async_hass_config_yaml(hass)