Global variables within lambdas?

Hello guys,
I know the way to set global variables. But I find it very uncomfortable when you need many varriables.

Is there a way to define global varriables inside a lambda?

And, is there a way to write/read data directly to the flash?

I ask these questions because I am planning to program a light control for my aquarium. I have not found anything like this. For this I need many variables to calculate the dimming curves for all color channels.

Cheer Gabriel

2 Likes

Thanks Blayk, but that doesn’t begin to answer my questions. Perhaps I need to be more clear. I wrote that I know about the “globals:”. And I find them too cumbersome for the many variables I need.

globals:
- id: value
type: int
restore_value: no
initial_value: ‘0’

is one way…

lambda: |-
int value=0;

is much easier. Unfortunately different ‘lambdas’ have no common namespace.

lambda: |-
int value=5;

lambda: |-
if (value) …

does not work.

I also don’t need the variables to be storable. But I would like to write something on the flash myself…

1 Like

I have now found my solution. I write this here times purely, if someone looks for such a solution.

I have created my own class and in this class I have created my own structure. I can access this structure from any lambda…

First:
Create a .h file at any place within your structures. I have created a subfolder aquarium-lucas the file GeoGab.h.

aquarium-lucas/GeoGab.h

Second:
Write your class with your varriables or/and structures or whatever you want.

Example:

#include "esphome.h"
using namespace esphome;

class GeoGab {
  public:

    struct settings_t {
        string name="Main";
        int timeout=60;
    } settings;

    struct timeout_t {
      int lowwater=30;
      int waterlock=60;
    } timeout;

    struct color_t {
          Color bgreen = Color(84, 130, 53);
          Color bgrey = Color(100, 100, 100);
          Color bdgrey = Color(50, 50, 50);
          Color bblue = Color(77, 98, 253);
          Color bdblue = Color(90, 90, 120);
    } color; 
} geogab;

Third:
Import this .h file into your device YALM.

esphome:
    name: $devicename
    platform: ESP32
...
    includes:
      - aquarium-lucas/GeoGab.h

Fourth:
Use these varriables/funtions or whatever in all lambdas.

lambda: |-
        ......
        esp_logi("GeoGab", "Timeout: %d", geogab.settings.timeout);

lambda: |-
        ......
       esp_logi("GeoGab", "Waterlock Timeout: %d", geogab.timeout.waterlock);
3 Likes

Hi Gabriel,
I came across this post and your solution when doing things with global variables in ESPHome. Almost sure you have your thing running already with your class, but just in case I post my findings:

Defining global variable like this:

globals:
  - id: count1
    type: unsigned int
    restore_value: no
    initial_value: '0'
  - id: count2
    type: unsigned int
    restore_value: no
    initial_value: '0'

I can use them inside lambdas like this:

      - lambda: 'id(count1)++;'
      - lambda: 'return (++id(count2) == id(count1));'

Note that you will need to use the id( var ) syntax to pick the global context. Hope this helps.

Why did I need these globals?
I did something like this in a project that I needed to turn on a fan for only 15 min. At first, I did something like this:

switch:
  - platform: gpio
    name: "Bathroom Fan"
    id: bathroom_fan
    pin: GPIO4
    inverted: yes
    restore_mode: RESTORE_INVERTED_DEFAULT_OFF
    on_turn_on:
      - delay: 10s
      - switch.turn_off: bathroom_fan

But I realized that if you turned on and off multiple times in a row, it was queuing multiple events to ‘turn off’. Consequently, the fan went off 15 min after the first ‘turn on’ even if the switch was turned on and off very recently.
So I thought to use 2 global counters incremented in the ‘on_turn_on’ and when the delayed action was performed. Comparing these 2 counters I make sure I only turn off the fan 15 min after the last turn on.
This is the code:

switch:
  - platform: gpio
    name: "Bathroom Fan"
    id: bathroom_fan
    pin: GPIO4
    inverted: yes
    restore_mode: RESTORE_INVERTED_DEFAULT_OFF
    on_turn_on:
      - lambda: 'id(count1)++;'
      - logger.log:
          format: "on: count1 %u count2 %u"
          args: [ 'id(count1)', 'id(count2)' ]
      - delay: 10s
      - if:
          condition:
            lambda: 'return (++id(count2) == id(count1));'
          then:
            - switch.turn_off: bathroom_fan