How do I access the value of a Template Number?

I have a Template Number:

number:
  #
  #Switch delays
  #
  - platform: template
    id: "Switch1Wait"
    name: "Switch 1 Wait"
    optimistic: true
    min_value: 0
    max_value: 600
    step: 1
    initial_value: 120
    restore_value: true
    web_server:
      sorting_group_id: sorting_group_switch1
      sorting_weight: 20

I want to be able to access the value, both to print out in logs, and to use the value in other functions and statements. For logging, I’ve tried:

      - logger.log:
          format:  "DEBUG MAIN PRESS 2: Switch 1 Delay: %i"
          args: 'id(Switch1Delay)'

This is part of a Binary Sensor that response to a button press. When I press the button, I see:


(Relevant lines are the 1st and 2nd line in the log.)

The value is currently set at 120, but when I try to log the value of it, I get 0, so I’m not actually getting the value when I try to print it in the log. I would think %i would be the right pattern to use to print an integer - is something else better? Or is the problem in the next line?

I know if it’s a string, I can access the value, for logging, like this:

          - logger.log:
              format: "        Changed on div by 15 value, TestVar: ->%s<-"
              args: id(TestVar).c_str()

But I know c_str() is to read strings terminated with a null byte, so that wouldn’t be appropriate for a number.

Aslo, I’d like to be able to use this value (of the Template Number) in statements, like:

- delay: <template value> seconds

I’ve tried doing some debugging to work this out. I’m not clear if the value of the template is a C++ variable or just a variable within the YAML file that I should be able to read.

Instead of string try state i.e.


id(my_number).state

For sensors, binary sensors, numbers, … You can access value/state as

id(xxx).state

Yes it’s in the docs, the example is

'id(temperature_sensor).state'

Clarification on quotation marks here.

I see all answers use id(sensor).state, but one uses single quotation marks. So enclosing it in quotes is necessary? And that’d work the same for printing it in a log and using it in a command?

I saw one paragraph in the documentation that described .state as returning something different - more like the state of whether it had been defined or not. It’s not under Template Number or Number Component. I’ll see if I can find it again and bring it up so it can be edited.

I am just copying the docs.

Okay, I had refactored the code, since I had added labels and components at each new step of testing and experimenting and realized the errors I was getting were from not refactoring this section - so it was working, just for the wrong component.

Made some changes - including making sure I’m using the right component name, but still not getting the right results. Here’s the Template Number:

number:
  - platform: template
    id: "Switch1Wait"
    name: "Switch 1 Wait"
    optimistic: true
    min_value: 0
    max_value: 600
    step: 1
    initial_value: 120
    restore_value: true
    web_server:
      sorting_group_id: sorting_group_switch1
      sorting_weight: 20

And here’s the log statement:

      - logger.log:
          format:  "DEBUG MAIN PRESS 2: Switch 1 Delay: %i"
          args: 'id(Switch1Wait).state'

Now, this is the kind of thing I can easily miss a difference due to a perception/reading issue, so I am hoping it’s something simple, stupid, and obvious, that I’m missing, but I’ve gone over it several times.

So the formatting for the log part should be:

'id(Switch1Wait).state'

The entire thing should be in single quotes and I want the state of the component.

Then I compiled and ran it and it’s reporting the value as 0, not 11, what it’s set to:


I boxed in the relevant parts in red. The value is set at 11 on the Template, and the log is reporting it as 0.

I even did a search to be sure the logging part was using the same spelling and referring to the specific Number Template I wanted to use. (There are 8 number templates - all set to 120 except the one I’m testing, so none should be reporting a 0.)

Try %f

Working with %f.

I thought %i was supposed to handle integers. What did I miss in that?

Beyond my pay grade. As I said I just copy the docs LOL.

Now I’m having trouble using it in the delay statement. I tried:

delay 'id(Switch1Wait).state' seconds

and I get this:

while parsing a block mapping
  in "/config/esphome/durin.yaml", line 253, column 9
expected <block end>, but found '<scalar>'
  in "/config/esphome/durin.yaml", line 253, column 40

So I changed to no quote marks:

INFO ESPHome 2024.11.2
INFO Reading configuration /config/esphome/durin.yaml...
Failed config

script: [source /config/esphome/durin.yaml:247]
  - id: Switch1DelayScript
    mode: restart
    then: 
      - logger.log: 
          format: DEBUG SCRIPT 1: Test boolean value: %d
          args: id(Switch1Delay)
      - 
        Expected time period with unit, got id(Switch1Wait).state seconds.
        delay: id(Switch1Wait).state seconds
      - logger.log: 
          format: DEBUG SCRIPT 2: Test boolean value: %d
          args: id(Switch1Delay)
      - globals.set: 
          id: Switch1Delay

For reference, this is the full script, with debugging statements:

script:
  - id: Switch1DelayScript
    mode: restart
    then:
      - logger.log:
          format: "DEBUG SCRIPT 1: Test boolean value: %d"
          args: 'id(Switch1Delay)'
      - delay: 'id(Switch1Wait).state' seconds
      - logger.log:
          format: "DEBUG SCRIPT 2: Test boolean value: %d"
          args: 'id(Switch1Delay)'
      - globals.set:
          id: Switch1Delay
          value: 'false'
      - logger.log:
          format: "DEBUG SCRIPT 3: Test Variable value: %d"
          args: 'id(Switch1Delay)'
      - logger.log: "DEBUG SCRIPT 4: <-- Delay script ending"

So I know this format works in the log:

'id(Switch1Wait).state`

But using the same thing is not returning a numerical value the delay command is accepting. The way I interpret the error message is that it’s not seeing the variable state as a number that can be seen as a time period.

Should it be

delay: !lambda return id(Switch1Delay)

Changed the line to:

- delay: !lambda return id(Switch1Delay) seconds

And it threw errors:

I use the following, by default delay uses milliseconds so times by 1000

- delay: !lambda "return id(Switch1Delay).state * 1000;"

Short version: @EBME2’s comment worked.

A note, for those in the future, using this as a resource: I have trouble keeping names and symbols organized and straight. I’m also building this up from scratch, in a new environment, so I’m finding I’m not at the point where I can plan things out yet. Since I’m adding things on as I test one thing and move to the next, I don’t have an organized nomenclature yet. So I’ve had Switch1Wait and Switch1Delay and similar names, so it’s really easy to mix them up.

I have Switch1Delay as a bool - to determine whether the delay is active or not. But the value in question is in Switch1Wait. At one point, we started referring to Switch1Wait, when I needed to be using Switch1Delay. That may confuse people in the future trying to keep track of what is going on here. Thought I should note that so it all made sense to anyone trying to figure out the same thing I’m doing here.

1 Like