Switch Template "turn_off_action" gets called during setup. Why?

I wrote a refrigerator control a year ago. I wanted to swap the unit_of_measurement from C to F for display on both the controller and the HA dashboard. Not being too clever I changed the units in ESPHome and then re-booted the board to force an update to the HA front end. All works.

I have a template switch to switch the unit (and save a global). The framework a year ago worked. Now with 2024.6.0 (and 5.5) the “turn_off_action” gets called during setup and my doodad gets into an endless reboot loop. I looked at the change log and didn’t see anything obvious.

I “publish” the initial state for the switch in “on_boot:” (based on the saved global), but commenting that out doesn’t affect the above behavior. I have some buttons driving a menu which also set the value, and those don’t appear to be firing either. So, the call to “turn_off_action” seems to be limited to the setup of ESPHome framework after boot.

Any thoughts beyond a gross hack to ignore the first call to “turn_off_action”?

switch:
  - platform: template
    name: Farenheit        # keep this internal to ESPHome end device
    id: farenheit
    turn_on_action:
      - lambda: |-
          id(bFarenheit) = true;  // global value saved through reboots
          ESP_LOGI("refer", "Farenheit turned on");
      - script.execute: update
      - script.execute: restart_refrigerator
    turn_off_action:
      - lambda: |-
          id(bFarenheit) = false;
          ESP_LOGI("refer", "Farenheit turned off");
      - script.execute: update
      - script.execute: restart_refrigerator

    lambda: return id(bFarenheit);

Ok, I did a bit of a hack, modifying “turn_off_action”

    turn_off_action:
      - lambda: |-
          ESP_LOGI("refer", "farenheit \"turn_off_action\" called");
          if (id(bFarenheit) == true) {
            id(bFarenheit) = false;
            ESP_LOGI("refer", "Farenheit turned off");
            id(update).execute();
            id(restart_refrigerator).execute();
          }

Which solves the problem of the endless reboot (but why is it being called in the first place).

Second problem, the global “bFarenheit” and “bEnable” are not being saved/restored. All the numeric values seem to be saved and restored properly. Again, I see nothing in the release notes regarding global behavior changing (Oh, BTW: ESP32)

globals:
  # NB: Store setpoints in either C or F (floats) and convert upon editing the scale.
  - id: refer_sp
    type: float
    restore_value: yes
    initial_value: '3'      # 37 f
  - id: freezer_sp
    type: float
    restore_value: yes
    initial_value: '-18'      # 0f
  - id: bFarenheit          # Default F
    type: bool
    restore_value: yes
    initial_value: 'true'
  - id: nTimeout
    type: int
    restore_value: yes
    initial_value: '15'
  - id: bEnable
    type: bool
    restore_value: yes
    initial_value: 'false'

Why just not to use restore_mode to restore state on bootup for template switch.

So far it works perfect for me. No need to store smth in globals as soon template switch have built-in feature to restore state.

I was unaware that templates could be “restored”. Will look into that as it simplifies the code.

Cool, works. Still having issues with one template switch working and the other stuck. But it is late and I need to put this away for a couple days.

Thanks!

Just FYI:

Unless you delete the name, or set internal: true that will not be an internal only device.

That is a bug in the documentation. I do expose the template to HA which is how the dashboard can control the units display on the remote device.

However, I am still struggling a bit. The OLD framework never called “on_turn_off/on” automation during boot. I used a stored global “bFarenheit” to set the initial state of the template switch in the “on_boot” automation.

The NEW framework calls the “on_turn_on/off” during boot to reflect its state regardless of publishing the global state. How can I disable this? Can I disable this? I want to disable this.

I mirror the state of the template switch with my global and use that to decide if I need to run the automation. Super clunky. NB. printf (e.g. ESP_LOGI) debugging. Uhg.

    turn_off_action:
      - lambda: |-
          ESP_LOGI("refer", "farenheit \"turn_off_action\" called");
          if (id(bFarenheit) == true) {
            id(bFarenheit) = false;
            ESP_LOGI("refer", "Farenheit turned off");
            id(update).execute();
            id(restart_refrigerator).execute();
          }

TIA

P.S. I tried setting the on_boot priority to 800 in an attempt to “publish_state” before the template switch automation was called. Anyway, my old code, which was pretty clean, relied on no automations being called during boot.

TIA^2

DOH.

restore_mode: DISABLE (apparently default mode a year ago)

So:

  1. OTA platform change (trivial)
  2. dallas → one_wire (trivial)
  3. restore_mode default → DISABLE - WAY TOO MUCH WORK…

original code all good now. Whoo hoo.