How to display dynamic list on CYD?

Hi,
I have a CYD (with esphome) hanging in the kitchen that shows various things, including the current PV yield and things like that.

I have reminders for to-dos sent to my cell phone, e.g. washing machine finished, dishwasher finished, taking out the trash, flushing the water connection, etc.
Each of these to-dos generates a sticky/persistent notification on the cell phone, which has a callback action to delete the sticky notification again after it has been completed.
In addition, each to-do counts up a counter helper so that I can see how many to-dos are still open.
Completing a to-do reduces the counter accordingly.

On my CYD I have a tile that shows the number of unfinished to-dos, and the LED is red as long as the counter is > 0.

I would now like to configure a button on the counter tile that shows/opens a second page in the CYD.
So far, no problem.

But on this second page, a dynamic list of open to-dos should now be displayed. And that’s where I’m stuck.
I’m thinking that every new to-do should be written/added to an array or a JSON, for example.
I then read this out with an input_text helper as a template sensor and pass the list to esphome for displaying.
I’m still not sure if that’s even possible.
The problem is, for example, when I complete a to-do, it has to be removed from the array. How do I do that? So how can I delete a certain string from the array that is always in a different position?

Does anyone have any better ideas on how I can generate and display a dynamic list of to-dos on the CYD?

Many thanks!

WTH is a CYD?

1 Like

Oh, I taught this is a common term :sweat_smile:

It’s the Cheap Yellow Display, a nickname for a ESP32-2432S028R.
It’s a cheap 2.8" Display (+/- 15 USD on AliExpress), which you can use with esphome.
There are a couple of Blogs, GitHub projects out there…

Not sure where you are in your endeavour, but I guess the todo service to get the open items should be a starting point

LOL I googled harder and found it. Thanks. In fact I have one in my in tray.

Have you tried openhasp?

Well, didn’t know openhasp, but seems interessting, I’ll have a look into that as well.

But I finally managed it, thanks to @koying 's hint, which poked me in the right direction.

In case, one is interessted:

I have already automations which trigger a todo (see above describtion, i.e. a push). In those automations I added the todo.add_item service call to put a respective item on a todo list.
I created a template sensor, which extracts all open items from this todo list (using todo.get_items service), separate them with a comma and put all that in the sensor value.

template:
- trigger:
    - platform: state
      entity_id: todo.haushalt
  action:
    - service: todo.get_items
      data:
        status: needs_action
      target:
        entity_id: todo.haushalt
      response_variable: items
  sensor:
    - name: Todo Haushalt Items
      unique_id: todo_haushalt_items
      state: "{{ (items.values() | list)[0]['items'] | map(attribute='summary') | list | join(',') | truncate(255) }}"

In ESPhome I added a sensor, which gets to count of the todo list and a text sensor, which mirrors the state of the todo items sensor.
In the display component I then check if the count is >0 to color the icon and by pressing the icon it opens page2, which displays the text_sensor. Within this, I substitute the comma with a newline, to get a nice list on the screen:

sensor:
# Get open ToDo count
  - platform: homeassistant
    id: todo_haushalt_count
    entity_id: todo.haushalt
    internal: true

text_sensor:
# Get open ToDos
  - platform: homeassistant
    id: todo_haushalt
    entity_id: sensor.todo_haushalt_items
    internal: true 

display:
  - platform: ili9xxx
    id: cyd01_display
    model: ili9341
    spi_id: tft
    cs_pin: GPIO15
    dc_pin: GPIO2
    rotation: 0
    pages:
      - id: page1
        lambda: |-
          it.fill(id(Color::BLACK));
[...]
          it.rectangle(20, 120, 80, 80, id(ha_blue));
          if (id(todo_haushalt_count).state > 0) {
            it.print(60, 160, id(mdi48), id(todo_orange), TextAlign::CENTER, "\U000F0756");
          } else {
            it.print(60, 160, id(mdi48), id(off_blue), TextAlign::CENTER, "\U000F0756");
          }
[...]
      - id: page2
        lambda: |-
          it.fill(id(Color::BLACK));
          std::string str1 = id(todo_haushalt).state; 
          int xPos1 = 5, yPos1 = 5, lineHeight1 = 20;
          std::string delimiter1 = ",";
          std::size_t curPos1 = 0, commaPos1 = 0;
          while (commaPos1 != std::string::npos) {
              commaPos1 = str1.find(delimiter1, curPos1);
              it.print(xPos1, yPos1, id(roboto20), todo_white, str1.substr(curPos1, commaPos1 - curPos1).c_str());
              yPos1 += lineHeight1;
              curPos1 = commaPos1 + delimiter1.size();
          }
          it.rectangle(200, 280, 40, 40, id(ha_blue));
          it.print(210, 290, id(mdi24), id(todo_white), TextAlign::CENTER, "\U000F104D");
1 Like