Program design issue for curtain control

So I have this roller curtain project. At present, the time for which the motor runs, which is the amount the curtain rolls up or down, is hard coded into my sketch but I'm thinking of making it variable. I want/need to avoid the curtain over- or under- rolling.

I’m thinking that an option would be to send the amount of time with each call to raise or lower the curtains but I believe at some point it might still cause issues.

Are limit switches the better choice? Better than sending an mqtt message with an encoded time? I mean apart from the obvious ease of just saying "open" vs "close"?

#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
//#include <Adafruit_INA219.h>

#define in1 3 //We are not using PWM for this demo.
#define in2 4

// Connect to the WiFi
const char* ssid = "myssid";
const char* password = "mypwd";
IPAddress mqtt_server(192, 168, 1, 113);
 
WiFiClient espClient;
PubSubClient client(espClient);
 
const byte ledPin = 0; // Pin with LED on Adafruit Huzzah UNNECESSARY
 
void callback(char* topic, byte* payload, unsigned int length) {
 Serial.print("Message arrived [");
 Serial.print(topic);
 Serial.print("] ");
 for (int i=0;i<length;i++) {
  char receivedChar = (char)payload[i];
  Serial.print(receivedChar);
  if (receivedChar == '0')
  // ESP8266 Huzzah outputs are "reversed"
  raiseCurtain();
  digitalWrite(ledPin, HIGH);
  if (receivedChar == '1')
  lowerCurtain();
   digitalWrite(ledPin, LOW);
  }
  Serial.println();
}
 
 
void reconnect() {
 // Loop until we're reconnected
 while (!client.connected()) {
 Serial.print("Attempting MQTT connection...");
 // Attempt to connect
 if (client.connect("ESP8266 Client")) {
  Serial.println("connected");
  // ... and subscribe to topic
  client.subscribe("curtainStatus");
 } else {
  Serial.print("failed, rc=");
  Serial.print(client.state());
  Serial.println(" try again in 5 seconds");
  // Wait 5 seconds before retrying
  delay(5000);
  }
 }
}
 
void setup(){
 Serial.begin(9600);
 
 client.setServer(mqtt_server, 1883);
 client.setCallback(callback);
 
 pinMode(ledPin, OUTPUT);//UNNECESSARY
 setupMotor();
 
}

void setupMotor(){
    //set the pins for output
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
 //set the pins low - this will keep the motor from moving.
 digitalWrite(in1, LOW);
 digitalWrite(in2, LOW);
}

void raiseCurtain() {
 Serial.println("raising curtains");
  //set the pins low - this will keep the motor from moving.
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
 
  //Spin Motor in one direction UP
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  delay(5000); //let it spin for about 10 seconds
}
void lowerCurtain() {
 Serial.println("lowering curtains");
    //Spin Motor in the other direction DOWN
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  delay(5000); //let it spin for about 10 seconds

  //Stop the motor
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);

}

void loop(){
 if (!client.connected()) {
  reconnect();
 }
 client.loop();
}

“Are limit switches the better choice?“

When it comes to motors moving things, limit switches and even crash switches are always warranted.