Latching a relay for a time period using a function

I am trying to control a relay, which I want to switch on at a set time using a DS3231 RTC module and keeping the relay closed for a set period of time. It will be part of a plant irrigation setup.
I am ok with setting the alarms on the RTC module, but when the alarm is activated it does not hold the relay closed (I only get a pulse).
The only way of operating it to work like this is to use DELAY. This is no good, as I want to check a level sensor to make sure that the tank is not empty and I am aware that no processing happens during a delay.

You will see that I have tried several things to try to solve this, some of which are commented out.

The prefered method would be to use a function. When the program gets to the function it pulses the output, but does not hold the relay on. This method of delay is based on the blink without delay code, but I guess I have not adapted it correctly in my code. Below is the serial output.

→ alarm1 has been triggered
In the Delay
60000
25038
0
Out the Delay

→ alarm2 has been triggered
In the Delay
60000
145161
0
Out the Delay

I did try an idea using a for loop but that just switched the relay on but would not switch off. I was not sure how long a for iteration would take for a number.
Here is the code:

// rtc_ds3231_alarm4
// during an alarm the INT pin of the RTC is pulled low
//SDA - pin A4
// SCL - pin A5
// this is handy for minimizing power consumption for sensor-like devices, 
// since they can be started up by this pin on given time intervals.

#include <Wire.h>
#include "ds3231.h"
#define BUFF_MAX 256
// time when to wake up
uint8_t wake1_HOUR = 18;
uint8_t wake1_MINUTE = 23;
uint8_t wake1_SECOND = 00;

uint8_t wake2_HOUR = 18;
uint8_t wake2_MINUTE = 25;

int relaypin = 10;
int SQWpin = 8;
unsigned long relayDelay;
// Variables will change :
int relayState = LOW;             // ledState used to set the RELAY

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store

// constants won't change :
unsigned long prev = 1000, interval=1000;
void set_alarm(void){
    // flags define what calendar component to be checked against the current time in order
    // to trigger the alarm - see datasheet
    // A1M1 (seconds) (0 to enable, 1 to disable)
    // A1M2 (minutes) (0 to enable, 1 to disable)
    // A1M3 (hour)    (0 to enable, 1 to disable) 
    // A1M4 (day)     (0 to enable, 1 to disable)
    // DY/DT          (dayofweek == 1/dayofmonth == 0)
    uint8_t flags1[5] = { 0, 0, 0, 1, 1 };
    
    // A2M2 (minutes) (0 to enable, 1 to disable)
    // A2M3 (hour)    (0 to enable, 1 to disable) 
    // A2M4 (day)     (0 to enable, 1 to disable) 
    uint8_t flags2[3] = {0, 0, 1};
    
    // set Alarm1
    DS3231_set_a1(wake1_SECOND, wake1_MINUTE, wake1_HOUR, 0, flags1);

    // activate Alarm1
    DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
    
    // set Alarm2
    DS3231_set_a2(wake2_MINUTE, wake2_HOUR, 0, flags2);

    // activate Alarm2
    DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);
    
}
long notdelay(long interval1){
  Serial.println("In the Delay");
  Serial.println(interval1);
  //digitalWrite(relaypin, HIGH);
unsigned long  previousMillis;
unsigned long currentMillis = millis();
Serial.println(currentMillis);
Serial.println(previousMillis);
if(currentMillis - previousMillis >= interval1){
  previousMillis = currentMillis;
  Serial.println("Out the Delay");
  //digitalWrite(relaypin, LOW);
  return interval1;
}
}
/*void LoopDelay(){
  int i;
  digitalWrite(relaypin, HIGH);
  for(int i = 0; i < 100000; i++){
    println(i);
}
digitalWrite(relaypin, LOW);
}*/
void setup() {


    Serial.begin(9600);
    Wire.begin();
    pinMode(SQWpin, INPUT);
    pinMode(relaypin, OUTPUT);
    DS3231_init(DS3231_INTCN);
    DS3231_clear_a1f();
    DS3231_clear_a2f();
    set_alarm();
}

void loop()
{

    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;

    // once a while show what is going on
    if ((now - prev > interval) && (Serial.available() <= 0)) {
        DS3231_get(&t);

        // display current time
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);
        Serial.println(buff);

        // display a1 debug info
      //  DS3231_get_a1(&buff[0], 59);
      //  Serial.println(buff);

        if (DS3231_triggered_a1()) {
            // INT/SQW has been pulled low
            Serial.println(" -> alarm1 has been triggered");
            digitalWrite(relaypin, HIGH);
 //delay(600000);
   //relayDelay = notdelay(60000);
//LoopDelay();
notdelay(60000);
            // clear a1 alarm flag and let INT go into hi-z
            DS3231_clear_a1f();
           digitalWrite(relaypin, LOW);
        }
        
if (DS3231_triggered_a2()) {
            // INT/SQW has been pulled low
            Serial.println(" -> alarm2 has been triggered");
           digitalWrite(relaypin, HIGH);
 //delay(60000);
//relayDelay = notdelay(60000);  
//LoopDelay();
  notdelay(60000); 
            // clear a1 alarm flag and let INT go into hi-z
            DS3231_clear_a2f();
            digitalWrite(relaypin, LOW);
        }
      
       prev = now;
    }
}

Some help would be appreciated, as I am fairly new to programming.

How accurate does the on time need to be? You could use the alarm from the RTC to start the time and millis() for the on duration. Record the value of millis() at the alarm time and turn irrigation on. Use the blink without delay method (see IDE examples) to watch millis() for the end of the on time.

After pulling the relay, save millis in a variable.

            digitalWrite(relaypin, HIGH);
            relaystart=millis();

somewhere in loop()

if (millis()-relaystart>120000 || tanklevel<threshold ){ //120 sec or tanklevel fall below threshold
 digitalWrite(relaypin, LOW);
}

That did not work, so have decided to change the original spec. I will use the Alarm 1 for ON and Alarm 2 for OFF. This simplifes the problem. I have a problem with the tank sensor, so as this a different subject I will startn a new post.

volatile boolean alarm = false; boolean relayOn = false; uint32_t relay_start_ms;

loop() { if(relayOn) { if(millis() - relay_start_ms > RELAY_TIMEOUT_MS || water_level_sensed()) { turn the relay off relayOn = false; } } else { if(alarm) { turn the relay on; relayOn = true; relay_start_ms = millis(); alarm = false; // don't forget this bit } } }

ISR() { alarm = true; }