Referencing and using a state/string inside a component

I’ve run into this before and it confuses me. I’m using LVGL and displaying text in a label on the display. I have a Text Template where I can change the value (on the ESPHome’s web page or, eventually, through Home Assistant) and, when the value is changed, I want to display it on the label.

I’ve read docs that give info on various parts of this, but I’m trying to get a picture of just what’s happening. It’s like I’ve seen parts of it, now I’m trying to understand how it all fits together.

The issue is, mostly, format and protocol for me. I’ve asked similar questions in the past and now I realize I don’t know just what I’m referencing - is it a YAML value (I don’t think so), or am I using C++ format to access a value within an object? Just what am I reference if I want to get to the text in a Text Template? Am I right that what I’m doing is trying to access the actual text string within the Text Template component

I’m also not clear about what to do to format the YAML code for this, which includes when to use single and double quotes, and whether I have to do this as part of a dictionary or if I can just specify the text in one line.

Here’s the main YAML code for the component:

text:
  - platform: template
    id: test_text
    name: "Test text"
    mode: text
    optimistic: true
    min_length: 0
    max_length: 128
    on_value:
      then:
        - logger.log:
           format: "New text value: %s"
           args: 'id(test_text).state.c_str()'

In the code above, all I’m doing is reporting the new text value in the log and, as I understand it, I am accessing the text string in the last line of that code block. I do want to clarify the issue of quotation marks in that last line. What does it mean, or how does ESPHome interpret it, if use no quotes, single quotes, or double quotes?

Also, I added this on the end of the code above:

        - lvgl.label.update:
            id: InfoDisplay            
            text: "This is replacement text."

InfoDisplay is a LVGL Label Widget. This changes the text in that widget to “This is replacement text.” But then, when I change it to this:

        - lvgl.label.update:
            id: InfoDisplay
            text: 'id(test_text).state.c_str()'

Then the output displayed is test_text->state.c_str(), which, I see, is a representation of where I’m pointing to for the data I want. It’s the same whether I use single or double quotes. (Odd ‘text_text’ is not put in parenthesis.)

        - lvgl.label.update:
            id: InfoDisplay
            text: 
              format: "%s"
              args: 'id(test_text).state.c_str()'

The difference, here, is that I don’t use just one line to get the text from the Text Template component, I set it up as a dictionary, with both “format” and “args” keys. (I’ve also put square brackets around the value in args - works either way.)

Note that, when I was just using actual text as a replacement, I only needed one line to specify it. But when I tried to do that by using the value of the Text Template, it did not work.

I’m not clear on just what rules I need to follow here. As asked above, what difference does it make to ESPHome if I’m using no quotes, single, or double?

And how can I get the value of the Text Template state for the LVGL widget in just one line? Something like:

        - lvgl.label.update:
            id: InfoDisplay            
            text: <use text in the state of the Text Template here>

And one last issue that’s tangential to this, but still significant: If I do this to set up the label widget InfoDisplay:

lvgl:
  widgets:
    - label:
        id: InfoDisplay
        align: CENTER
        text: "Speak Friend and enter."
        text_align: CENTER
        text_font: montserrat_48

I can easily put the text I want into the widget. In this case, I know using single quotes will take what I write directly, but using double quotes will recognize escape sequences, so if I use:

        text: "Speak Friend\nand enter."

I get:

Speak Friend
and enter.

If I do this in single quotes, like this:

        text: 'Speak Friend\nand enter.'

I get it all on one linke, like this:

Speak Friend\nand enter.

I’d like to be able to do this with the text string in the Template Text component, but it doesn’t make a difference if I use single or double quotes around it when I’m getting that value from the Text Template component.

So I’m not clear about the rules for just how I’m referencing the value/state of the Text Template component, whether I’m using C++ formatting or YAML, what the rules are about the quotes used, and why I can’t seem to use that value with just a text key, but have to use a dictionary to be able to do that. (It feels like the rules change depending on where and how I’m accessing the Text Template’s value.)

And there’s the side issue - how can I get escaped characters in the Text Template recognized?

1 Like

I have one answer: At the simplest level, to get the text in one line, I used a lambda:

text:
  - platform: template
    id: test_text
    name: "Test text"
    mode: text
    optimistic: true
    min_length: 0
    max_length: 128
    on_value:
      then:
        - logger.log:
           format: "New text value: %s"
           args: 'id(test_text).state.c_str()'
        - lvgl.label.update:
            id: InfoDisplay
            text: !lambda return id(test_text).state.c_str();

While that helps make my code simpler, it doesn’t answer a lot of questions - like why I couldn’t just get the text of the item simply, in one line, instead of having to use a dictionary for the text element and include format and args as 2 separate lines in my file.

It also doesn’t let me escape the text along the way. I would think, once I get the actual string from the component, I should be able to do something to handle escaped characters - but I have no idea how.

Another partial answer. It turns out what I remember reading about escaped characters was specific to LVGL configuration. Apparently it’s either not a standard part of ESPHome or, as best I can tell, it’s handled during the compile process.

In short, to escape a text string in LVGL configuration, enclose it in double quote marks instead of single ones. But this can only be done in defining or creating the widget. That’s what makes me think it’s only handled during compiling the YAML file.

I’m going to start a new thread about processing a string in a Text Template. I would think there would have to be a way to read the value of a string from there and replacing sequences like “\n” and replacing it with a newline. I’m wondering if it could be done in a multi-command YAML file. I know I can use std::replace in a C++ program, but I don’t know how to make sure that’s included during compiling, how to use it in a lambda, and it’s been so long since I’ve programmed in C++, I’m just not sure how to set it up.

As to the other questions - about the quotation marks, like single vs. double, I’d still like to hear more about that.