ESPHome - How are variables (text, numbers, etc) handled for comparison, and so on?

While I’ve programmed in a number of different languages, from low level like Assembler, to higher level like Python or Java, I’m having serious difficulty understanding how to use variables in YAML files on ESPHome. Right now I’m primarily dealing with numbers and text and I can’t find clear examples of how to compare one number to another, to use them in calculations and store the result, or how to change the value of a variable. (The same for texts.) I can use the web interface with a template to change the value of a text or number, but then I am not clear just how to use the resulting value in the YAML file.

It looks to me like most work with texts is done with lambda functions. Is that just for convenience, or is that often the only way to work with comparing values, or setting them, or using them together?

I have tried to work with global variables, but I’m not clear if I can declare a global variable, then use it in a template or sensor. I’m also not at all clear how I can add two numbers, concatenate text strings, change the value of a global variable, or even print the value of a text string in a log message. (I did find one example for logging the value of a text, but when I tried it, I got gibberish that looked like it could either be a pointer instead of the text, or maybe that it interpreted the text itself as a pointer to some random place in memory.)

Is there a good summary somewhere of how to handle variables in YAML? Or is it best to just do it in lambda functions?

Did you find these pages?
They might help a bit.

In summary, sometimes ESPHome offers a beginner friendly way to do things, like with filters.

But for more advanced things you’ll often be reaching for lambdas.

For globals the docs should get you started.
https://esphome.io/components/globals.html

Navigating the ESPHome docs can be more art than science.

Thank you - so I guess it’s not just me! Yes, I’ve looked over some of those pages. Read them in the earlier parts of my experimenting with YAML and they helped. But I’m ready to loop back and re-read for more info, so thanks for pointing them out. I realize I missed some stuff because, when I first read them, it wasn’t stuff I needed yet.

Globals - okay, so I can set them. I missed that. But can I declare a global, then use it in a Text Template (or Number Template, or other Templates)?

I’m still getting used to how YAML uses lambdas, since I haven’t used them much in other languages and am not well practiced with them.

One issue I ran into is with a Text Template:

text:
  - platform: template
    id: MasterSwitchName
    name: "Master Switch Name"
    optimistic: true
    min_length: 0
    max_length: 64
    initial_value: "Master Switch"
    restore_value: true
    mode: text
    web_server:
      sorting_group_id: sorting_group_values
      sorting_weight: 2
    on_value:
      then:
       - logger.log:
           format: "DEBUG: Name changed to: %s"
           args:
             - MasterSwitchName.c_str()

The web interface for changing the value is working and the value is persistent across boots. Then I tried to print the changed value in the logs, just to be sure that’s working. I saw this method (using c_str() as a function to get the value) and I got a compile error. (It made it throug the YAML check.) I get this error:

err: request for member 'c_str' in 'MasterSwitchName", which is of pointer type 'esphome::template::TemplateText*' (Maybe you want to use '->' ?)

So I’m thinking that I get it - it’s a pointer. But I haven’t used C++ in 15 years or more and have been using pointer-less languages since then. So I thought I’d try MasterSwitchName->name and that didn’t work - there’s no “name” in the class. I tried variations and it didn’t work.

For the more immediate, this brings up these questions:

1 - Can I use a global variable for a Text Template, is a Text Template global anyway? If so, then I should be able to refer to it by its name or ID, right?

2 - Is a Text Template basically an object, as in oop, with many different fields in it? (like the minimum value, the max, whether it is stored, and more)? If so, how can I just get the value of it for printing in a log or to use as I would a string variable in, say, Python?

3 - How can I use the text in a Text Template for comparisons? For instance, seeing if it’s empty (or null), or if it is equal to another text? I’m thinking this is something I’d use a lambda for, but, again, I’d need to get the text value of it, and that goes back to question #2.

4 - Any chance I could see an example of using the value of the Text Template, for instance, just a fix for the last line or two of my example so I can print the value out in the log?

Yes.

I struggle with logging sometimes too. Keep at it.
I find it easier to use the lowely documented ESP_LOGD(). Often it’s type conversion.

Once you get to more advanced usecases with lots of lambda your probably better off just trying to find some examples on the forum rather than trying to use the docs. There will be examples of most things you want to do somewhere. If you want to understand lower level things you can also try the ESPHOME Discord. I don’t know how things work under the hood much myself. Just self taught through examples rather than the theory.

Try like this

args: ['id(MasterSwitchName).state']

Just found something else and came back and saw your reply with the args suggestion. So I tried args: ['id(MasterSwitchName).state'] and got gibberish. (Which I’m guessing is a pointer issue - either it returns a pointer instead of the text or it interprets the text value as a pointer and points to some random location in memory.)

The other one I just found and tried is I tried args: ["x.c_str()"]. That returned the value, so it works.

But I went one step farther. I brought up, on this thread, the question of using the text template to get a value to use to rename an entity on the system. I used:

- lambda: |-
            if (!x.empty()) {
              id(MasterSwitch).set_name(x.c_str());
            }

(This is from the thread I linked to above.) When I do that, then refresh the web page from the ESP32, it does update the name of the entity, but it shows gibberish, just like when I got gibberish from just trying to get the id and then the state from that. This makes me think that when I’m using that lambda, directly above, that I need something more than id(MasterSwitch).set_name(), since it changes the name to gibberish instead of to the text value being passed to it.

So I’m guessing that’s also an issue of whether I’m referencing the value or changing a pointer to the value.

1 Like

What does putting it in brackets do?

I think the square brackets are for when you have a list of args. Probably redundant in this case.