LillyGo T-Call constantly rebooting

Hi I have a LillyGo T-Call that is constantly rebooting. Is there a way to stop the device from rebooting or find out why its reboot?

Thanks

esphome:
  name: "car-gps"
  friendly_name: "car-gps"
  on_boot:
    priority: 600
    then:
      - lambda: |-
          // Clear the SMS message on boot
          id(sms_message).publish_state("");
      - lambda: |-
          // Log the reboot event
          ESP_LOGD("on_boot", "Device has rebooted. Waiting for GPS lock...");

globals:
  - id: sms_sent
    type: bool
    initial_value: "false"
  - id: alarm_armed
    type: bool
    initial_value: "false"
  - id: phone_number
    type: std::string
    restore_value: no
    initial_value: '"phone_number"'  # Replace with your actual phone number

interval:
  - interval: 10s
    then:
      - lambda: |-
          // Check GPS lock and SMS status
          if (!id(sms_sent) && id(gps_time).now().is_valid() && id(gps_satellites).state > 3) {
            // Get the GPS time and format the message
            auto now = id(gps_time).now();
            char buffer[100];
            snprintf(buffer, sizeof(buffer), "Device rebooted successfully at (GPS time): %04d-%02d-%02d %02d:%02d:%02d UTC",
                     now.year, now.month, now.day_of_month, now.hour, now.minute, now.second);
            id(gsm).send_sms(id(phone_number).c_str(), buffer);  // Use global phone number variable
            id(sms_sent) = true;  // Mark SMS as sent for this session
            ESP_LOGD("interval", "SMS sent successfully.");
          } else if (!id(gps_time).now().is_valid() || id(gps_satellites).state <= 3) {
            ESP_LOGD("interval", "Waiting for valid GPS time or sufficient satellites...");
          }

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:
  encryption:
    key: ""

ota:
  platform: esphome
  password: ""

wifi:
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password
  fast_connect: true
  reboot_timeout: 0s

  manual_ip:
    static_ip: 172.16.102.15
    gateway: 172.16.102.1
    subnet: 255.255.255.224

web_server:
  port: 80
  log: true
  local: True
  version: 3
  include_internal: true


text_sensor:
  - platform: template
    id: sms_sender
    name: "Sms Sender"
  - platform: template
    id: sms_message
    name: "Sms Message"
  - platform: template
    id: alarm_state
    name: "Alarm State"
    lambda: |-
      if (id(alarm_armed)) {
        return {"Armed"};
      } else {
        return {"Disarmed"};
      }
    update_interval: 10s
  - platform: wifi_info
    ssid:
      name: "WiFi SSID"
      id: wifi_ssid
    ip_address:
      name: "WiFi IP Address"
  - platform: template
    name: "Phone Number"
    id: phone_number_sms

sensor:
  - platform: uptime
    name: Uptime
    id: uptime_sensor

  - platform: wifi_signal
    name: "WiFi Signal Strength"
    id: wifi_signal_sensor
    update_interval: 30s

uart:
  - id: sim
    baud_rate: 9600
    tx_pin: 27
    rx_pin: 26
  - id: gpsmodule
    baud_rate: 9600
    rx_pin: RX

sim800l:
  id: gsm
  uart_id: sim
  on_sms_received:
    # Publish the sender and message state to text sensors
    - lambda: |-
        id(sms_sender).publish_state(sender);
        id(sms_message).publish_state(message);

    # Check if the SMS sender is authorized
    - lambda: |-
        std::string sender_str = id(sms_sender).state.c_str();  // Convert to string
        if (sender_str != id(phone_number)) {
          // Send unauthorized message if sender does not match phone_number
          id(gsm).send_sms(sender_str.c_str(), "Unauthorized");
          return;  // Prevent further processing
        }

    # Handle the "phone_number" command to return the current phone number
    - lambda: |-
        auto sms_sender_raw = id(sms_sender).state;  // Get the state from the text sensor
        auto sms_message_raw = id(sms_message).state;
        std::string sms_sender(sms_sender_raw.begin(), sms_sender_raw.end());
        std::string sms_message(sms_message_raw.begin(), sms_message_raw.end());

        if (sms_sender == id(phone_number) && sms_message == "phone_number") {
          std::string response = "The phone number is: " + id(phone_number);  // id(phone_number) is a string, no need for .state
          id(gsm).send_sms(sms_sender.c_str(), response.c_str());  // Use sms_sender directly, which is the sender number
        }

      # Handle the "new_number" command to update the phone number
    - lambda: |-
        auto sms_sender_raw = id(sms_sender).state;  // Get the state from the text sensor
        auto sms_message_raw = id(sms_message).state;
        std::string sms_sender(sms_sender_raw.begin(), sms_sender_raw.end());
        std::string sms_message(sms_message_raw.begin(), sms_message_raw.end());

        if (sms_sender == id(phone_number) && sms_message.substr(0, 11) == "new_number ") {
          // Extract the new phone number from the message
          std::string new_phone_number = sms_message.substr(11);

          // Update the global phone_number with the new number
          id(phone_number) = new_phone_number;

          std::string response = "Phone number updated to: " + new_phone_number;
          id(gsm).send_sms(sms_sender.c_str(), response.c_str());  // Send confirmation
        }

    # Handle "relay_on" and "relay_off" commands for the fuel shutoff relay
    - lambda: |-
        if ((id(sms_sender).state == id(phone_number)) && 
            ((id(sms_message).state == "relay_on") || (id(sms_message).state == "Relay_on"))) {
          id(shutoff).turn_on();  // Turn the relay on
          delay(100);  // Allow relay to stabilize
          if (id(shutoff).state) {
            id(gsm).send_sms(id(phone_number).c_str(), "Fuel Shutoff Relay has been turned on.");
          } else {
            id(gsm).send_sms(id(phone_number).c_str(), "Fuel Shutoff Relay failed to turn on.");
          }
        }
        if ((id(sms_sender).state == id(phone_number)) && 
            ((id(sms_message).state == "relay_off") || (id(sms_message).state == "Relay_off"))) {
          id(shutoff).turn_off();  // Turn the relay off
          delay(100);  // Allow relay to stabilize
          if (!id(shutoff).state) {
            id(gsm).send_sms(id(phone_number).c_str(), "Fuel Shutoff Relay has been turned off.");
          } else {
            id(gsm).send_sms(id(phone_number).c_str(), "Fuel Shutoff Relay failed to turn off.");
          }
        }

    # Handle the "where" command to send GPS and ignition data
    - lambda: |-
        auto to_lower = [](std::string str) -> std::string {
          std::transform(str.begin(), str.end(), str.begin(), ::tolower);
          return str;
        };

        // Retrieve sender and message, convert the message to lowercase
        auto sms_sender_raw = id(sms_sender).state;
        auto sms_message_raw = id(sms_message).state;
        std::string sms_sender(sms_sender_raw.begin(), sms_sender_raw.end());
        std::string sms_message_lower = to_lower(std::string(sms_message_raw.begin(), sms_message_raw.end()));

        if (sms_sender == id(phone_number) && sms_message_lower == "where") {
          std::string response;

          // GPS data
          if (id(latitude).has_state() && id(longitude).has_state()) {
            float lat = id(latitude).state;
            float lon = id(longitude).state;
            response += "Device location:\n";
            response += "Lat: " + std::to_string(lat) + "\n";
            response += "Lon: " + std::to_string(lon) + "\n";
            response += "Google Maps: https://www.google.com/maps?q=" + std::to_string(lat) + "," + std::to_string(lon) + "\n";
          } else {
            response += "GPS coordinates are not available yet.\n";
          }

          // Ignition sensor status
          if (id(ignition).state) {
            response += "Ignition: ON\n";
          } else {
            response += "Ignition: OFF\n";
          }

          // GPS speed
          if (id(speed).has_state()) {
            float gps_speed = id(speed).state;
            response += "Speed: " + std::to_string(gps_speed) + " km/h\n";
          } else {
            response += "Speed: N/A\n";
          }

          // Send the response SMS
          id(gsm).send_sms(id(phone_number).c_str(), response.c_str());
        }

    # Handle the "arm" and "disarm" commands to arm/disarm the alarm
    - lambda: |-
        auto sms_sender_raw = id(sms_sender).state;
        auto sms_message_raw = id(sms_message).state;

        std::string sms_sender(sms_sender_raw.begin(), sms_sender_raw.end());
        std::string sms_message(sms_message_raw.begin(), sms_message_raw.end());

        auto to_upper = [](std::string str) -> std::string {
          std::transform(str.begin(), str.end(), str.begin(), ::toupper);
          return str;
        };
        sms_message = to_upper(sms_message);

        if (sms_sender == id(phone_number)) {
          if (sms_message == "ARM") {
            id(alarm_armed) = true;
            id(shutoff).turn_on();
            id(gsm).send_sms(id(phone_number).c_str(), "Alarm armed. Notifications enabled, and fuel shutoff is ON.");
            ESP_LOGD("sms", "Alarm armed by SMS.");
          } else if (sms_message == "DISARM") {
            id(alarm_armed) = false;
            id(shutoff).turn_off();
            id(gsm).send_sms(id(phone_number).c_str(), "Alarm disarmed. Notifications disabled, and fuel shutoff is OFF.");
            ESP_LOGD("sms", "Alarm disarmed by SMS.");
          }
        }

    # Handle the "RESET" command to restart the device
    - lambda: |-
        if (id(sms_sender).state == id(phone_number) && id(sms_message).state == "reboot") {
          // Send confirmation message before restarting
          id(gsm).send_sms(id(phone_number).c_str(), "The device is now rebooting...");
          
          // Clear the SMS message state before reboot to prevent loops
          id(sms_message).publish_state("");  // Clear the SMS message state

          delay(2000);  // Wait for the SMS to be sent
          delay(1000);  // Additional delay to ensure SMS is sent before reboot
          ESP.restart();  // Restart the device
        }

    # Handle the "STATUS" command to return sensor data
    - lambda: |-
        id(sms_sender).publish_state(sender);
        id(sms_message).publish_state(message);

        auto sms_sender_raw = id(sms_sender).state;
        auto sms_message_raw = id(sms_message).state;

        std::string sms_sender(sms_sender_raw.begin(), sms_sender_raw.end());
        std::string sms_message(sms_message_raw.begin(), sms_message_raw.end());

        auto to_upper = [](std::string str) -> std::string {
            std::transform(str.begin(), str.end(), str.begin(), ::toupper);
            return str;
        };
        sms_message = to_upper(sms_message);

        if (sms_sender == id(phone_number) && sms_message == "STATUS") { 
            std::string response;

            // GPS Fix
            if (id(gps_time).now().is_valid()) {
                response += "GPS Fix: True\n";
            } else {
                response += "GPS Fix: False\n";
            }

            // Number of Satellites
            if (id(gps_satellites).has_state()) {
                response += "Satellites: " + std::to_string((int)id(gps_satellites).state) + "\n";
            } else {
                response += "Satellites: N/A\n";
            }

            // Uptime
            if (id(uptime_sensor).has_state()) {
                int total_seconds = (int)id(uptime_sensor).state;
                int days = total_seconds / 86400;
                int hours = (total_seconds % 86400) / 3600;
                int minutes = (total_seconds % 3600) / 60;
                response += "Uptime: " + std::to_string(days) + "d " + std::to_string(hours) + "h " + std::to_string(minutes) + "m\n";
            } else {
                response += "Uptime: N/A\n";
            }

            // Ignition Status
            if (id(ignition).state) {
                response += "Ignition: ON\n";
            } else {
                response += "Ignition: OFF\n";
            }

            // Relay Status
            if (id(shutoff).state) {
                response += "Relay: ON\n";
            } else {
                response += "Relay: OFF\n";
            }

            // WiFi SSID
            if (id(wifi_ssid).has_state()) {
                response += "WiFi SSID: " + id(wifi_ssid).state + "\n";
            } else {
                response += "WiFi SSID: N/A\n";
            }

            // WiFi Signal Strength
            if (id(wifi_signal_sensor).has_state()) {
                int wifi_dbm = (int)id(wifi_signal_sensor).state;
                int wifi_percent = esphome::clamp((wifi_dbm + 100) * 2, 0, 100); // Convert dBm to percentage
                response += "WiFi Signal: " + std::to_string(wifi_percent) + "%\n";
            } else {
                response += "WiFi Signal: N/A\n";
            }

            // Send the SMS response
            id(gsm).send_sms(id(phone_number).c_str(), response.c_str());
        }

    # Fallback for unrecognized commands
    - lambda: |-
        auto sms_sender_raw = id(sms_sender).state;
        auto sms_message_raw = id(sms_message).state;
        std::string sms_sender(sms_sender_raw.begin(), sms_sender_raw.end());
        std::string sms_message(sms_message_raw.begin(), sms_message_raw.end());
        
        std::vector<std::string> valid_commands = {"ARM", "DISARM", "STATUS", "REBOOT", "WHERE", "RELAY_ON", "RELAY_OFF", "PHONE_NUMBER"};

        auto to_upper = [](std::string str) -> std::string {
            std::transform(str.begin(), str.end(), str.begin(), ::toupper);
            return str;
        };
        sms_message = to_upper(sms_message);

        if (sms_sender == id(phone_number)) {
          bool is_valid_command = false;
          for (auto& command : valid_commands) {
            if (sms_message == command) {
              is_valid_command = true;
              break;
            }
          }

          if (!is_valid_command) {
            if (sms_message == "PHONE_NUMBER") {
              std::string response = "The current phone number is: " + id(phone_number);  // Respond with the current phone number
              id(gsm).send_sms(sms_sender.c_str(), response.c_str());  // Send SMS back to sender
            } else {
              id(gsm).send_sms(id(phone_number).c_str(), "Unrecognized Command");
            }
          }
        }




binary_sensor:
  - platform: gpio
    id: ignition
    pin:
      number: 21
      mode: INPUT_PULLUP
      inverted: True
    name: "Ignition"
    filters:
    - delayed_on: 1000ms
    - delayed_off: 1000ms
    on_press:
      then:
        - lambda: |-
            if (id(alarm_armed)) {
              id(gsm).send_sms(id(phone_number).c_str(), "ALERT: Ignition turned ON while alarm is armed!");
              ESP_LOGD("ignition", "Ignition notification sent: Alarm is armed.");
            } else {
              ESP_LOGD("ignition", "Ignition ON detected, but alarm is not armed. No notification sent.");
            }
switch:
  - platform: gpio
    name: "SIM800_PWKEY"
    pin: 4
    restore_mode: ALWAYS_OFF
  - platform: gpio
    name: "SIM800_RST"
    pin: 5
    restore_mode: ALWAYS_ON
  - platform: gpio
    name: "SIM800_POWER"
    pin: 23
    restore_mode: ALWAYS_ON
  - platform: gpio
    id: shutoff
    pin: 14
    name: "Fuel Shutoff"
    inverted: True

button:
  - platform: restart
    name: "Restart"
    id: restart_command

# Declare GPS module
gps:
  uart_id: gpsmodule
  id: gps_sensor
  update_interval: 60s
  latitude:
    name: "GPS Latitude"
    id: latitude
  longitude:
    name: "GPS Longitude"
    id: longitude
  speed:
    name: "GPS Speed"
    id: speed
  satellites:
    name: "GPS Satellites"
    id: gps_satellites
    
time:
  - platform: gps
    id: gps_time

See the API docs and set reboot_timeout.

Thanks, but on my wifi component I have

wifi:
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password
  fast_connect: true
  reboot_timeout: 0s

I have now added to api:

api:
  encryption:
    key: ""
  reboot_timeout: 0s

Have a look at your log to see why it’s rebooting.

Yea I think API or WiFI makes sense as it only does it when not connected to wifi or away from wifi.