15 minutes without additional modules, delay and appeals to server Home Assistant

Hello, please help a newbie. How to write code (in lambda) so that esp turns on the relay itself every 15 minutes without using delay and commands from Home Assistant. Thank you very much in advance!

Maybe use interval Component

or on_time Trigger

Thanks for the quick response. But as I understand it, time: - platform: sntp is a call to the server, but how to do it without calling the server. On Arduino it looks like this.

..........
long previousMillis = 0;       
long interval = 1000;  
void loop()
{
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis; 
........
  }
}

How to do it here?

Wouldn’t the interval component do that ?

I need to write it in lambda in order to work with it further.

No, it’s a call done to an external SNTP server once at startup. Your device does not need to be connected to HA. If you don’t have a connection to the internet, use an RTC like a DS1307. Otherwise, if none of the above, the internal RTC will set to GMT 0:00 at startup, then your on_time: trigger will execute very 15 minutes after startup. Note that even if your device isn’t connected to a time source you will need to include SNTP as the default.

How about using a modulo function on an Uptime sensor?

Where abouts is this lambda located? Like in a sensor or in a custom component etc…

I cleaned up the code I use, see if it works for you.


esphome:
  includes:
    - ./teste/teste.h

custom_component:
- lambda: |-
    auto command = new CommandComponent();
    return {command};  

#include "esphome.h"
#include "WiFi.h"
////  Status Check intervel
unsigned long previousMillis = 0;
unsigned long currentMillis = millis();
const long interval = 1200;


//// Check loop time
unsigned long StartTime = millis();
unsigned long CurrentTime = millis();
unsigned long ElapsedTime = CurrentTime - StartTime;

//// Delay for connection with HA
unsigned long DelayAfterBoot = 8000;


class CommandComponent  : public Component  {
  public:
    void setup() override {

    }

    void loop() override {
      if (millis() >= DelayAfterBoot) {

    

        currentMillis = millis();

        if (millis() - previousMillis >= interval) {
          previousMillis = millis();

          //status_update();

          unsigned long CurrentTime = millis();
          unsigned long ElapsedTime = CurrentTime - StartTime;
          if ((ElapsedTime >= 30) && (ElapsedTime <= 1000)) {
            Serial.print("ElapsedTime: ");
            Serial.println(ElapsedTime);
          }
          Serial.print("ElapsedTime: ");
          Serial.println(ElapsedTime);
        }

      }
    }
 

  
};

I don’t remember why I redeclared the variables below. :thinking:

          unsigned long CurrentTime = millis();
          unsigned long ElapsedTime = CurrentTime - Star

But you don’t need that part

Thanks to all. I found a piece of code on the Internet that, it seems to me, can solve the problem without additional modules, calls to the server, etc. But I do not have enough knowledge and experience to apply it.

sensor:
  - platform: uptime
    id: uptime_sensor # it's work time esp…
 …
      on_value:
        then:
          - lambda: |-
              int seconds = round(id(uptime_sensor).raw_state); # this is the current second
              id(last_seen).publish_state(1);
              id(prev_seen) = seconds; # is to remember her
  - platform: template
    id: last_seen
    lambda: |-
        int seconds = round(id(uptime_sensor).raw_state);
        return seconds - id(prev_seen); # this is how many seconds have passed since the above memorized
?????????

How to apply it?

If you want to sync time without a call to the network, get a gps sensor.

https://esphome.io/components/time/gps.html

and

Where will your lambda be located @mixxx77 ?

^^^ That code uses a uptime approach like I suggested, which is fine if you just need an interval and not the actual time (and don’t need to track across restarts).

From there a modulo approach would probably succinctly solve your problem.

If the modulo is 0, then do something…

I need a time interval of 15 minutes, without reference to real time.

Third time lucky.

The idea is to create a lighting effect that would switch the installed lighting effects in random order, the duration of the glow of each effect is 15 minutes.
P / S The effect itself was clumsily written. But the HA server considers the operating time of the light effects, I want to do it without additional modules, without requests from the HA server.

light:
  - platform: neopixelbus
......
    effects:
      - addressable_rainbow:
          name: "Color1"
......
      - addressable_color_wipe:
          name: "Color2"
......
      - lambda:
           name: "Color3" 
......
      - addressable_color_wipe:
          name: "Color4"
......
      - addressable_twinkle:
          name: "Color14"
......
      - addressable_random_twinkle:
          name: "Color15"
......
      - addressable_fireworks:
          name: "Color16"
......
      - addressable_lambda:
          name: snowflack
......
      - addressable_lambda:
          name: "Expo Light"
......
      - addressable_random_twinkle:
          name: Random Twinkle 20%
......
      - addressable_random_twinkle:
          name: Random Twinkle 80%
......
      - addressable_scan:
          scan_width: 4
      - addressable_lambda:
          name: "Christmas RedGreenWhite"
......
      - addressable_lambda:
          name: "color change"
......
      - addressable_lambda:
          name: "candles"
......
      - addressable_lambda:
         name: "My Custom Effect"
         lambda: |-           
            const int v = 14;
            int c[v] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14};
            int x = random(v);
            int z = c[x];
            static int effect_index = 0; // this value will persist across triggers
            id(neo).turn_on().set_effect(id(neo).get_effects().at(effect_index)->get_name().c_str()).perform();
            effect_index += z;
            auto call = id(neo).turn_on();                  
            if (effect_index >= id(neo).get_effects().size()) {
              effect_index = 0; // restart from the beginning once the last effect is reached
            }            
            if (effect_index + id(neo).get_effects().size() == 16){
                effect_index = 0; // restart from the beginning once the last effect is reached
              }
            return;            

switch:
  - platform: template
    name: "light_1"
    icon: "mdi:alarm-light-outline"
    turn_on_action:
      - light.turn_on:
......
         effect: "My Custom Effect"

I noticed the examples here makes use of update_interval.

If you set that it should set the interval for when your lambda is being evaluated?