SIM7600g-h problems. sending sms commands

Hello. All

having. problem sending. sms. commands

project: location tracker. operates. by 3. sms commands

L- location (shows. location when hit it. on phone)

T - tracking. Live S - stop. tracking ( T & S are beyond. this. scope. of this post)

equipment :XIAO esp32 c6, - SIM 7600 g-h - TP4056. - buck. converter

SIM card - Hologram. for. now. im. focusing. on troubleshooting. of. sending. receiving. sms

no power. issue. steady. read. light. green. light. blkinks.
following. AT commands. i. sent. and. responses ( took. me. hours. to. succed...)

Testing modem...
AT
OK
AT+CMGF=1
OK
AT+CNMI=2,1
OK
SMS + GPS tracker ready.

----------------------------------------------

some. number. and. message. body.
Message (Enter to send message to 'XIAO_ESP32C6' on '/dev/cu.usbmodem21201')
Both NL & CR
115200 baud
+CMTI: "SM",1
AT+CMGR=1
+CMGR: "REC UNREAD","467190002980389","","26/04/29,04:25:10+08"

hello. please. send. my. message

OK
AT+CMGL="ALL"
+CMGL: 1,"REC READ","467190002980389","","26/04/29,04:25:10+08"
hello. please. send. my. message

+CMGL: 0,"REC UNREAD","467190002980389","","26/04/28,19:22:50+08"

Lsome. number. and. message. body.
Message (Enter to send message to 'XIAO_ESP32C6' on '/dev/cu.usbmodem21201')
Both NL & CR
115200 baud
+CMTI: "SM",1
AT+CMGR=1
+CMGR: "REC UNREAD","467190002980389","","26/04/29,04:25:10+08"
hello. please. send. my. message
OK
AT+CMGL="ALL"
L

____________________________________

AT
OK
AT+CMGF=1
OK
AT+CNMI=2,1
OK
SMS + GPS tracker ready.
+

+________________________________________

so. seems. like. the. modem respons. sends/. receives. sms. but. something. is. still. wrong. Also. on. hologram. dashboard. it. says sms. semds. and. i. can. see L. in received. messages (. by the. way. purchased a. hologram phone. number)

Thank. you. for. your. help!!

code

#include <Arduino.h>
#include <HardwareSerial.h>

// =====================================================
// PINS
// =====================================================
static const int SIM7600_PWRKEY_PIN = D0;
static const int SIM7600_TX_PIN     = D6;
static const int SIM7600_RX_PIN     = D7;
static const int MOTION_PIN         = D4;

// =====================================================
// SERIAL
// =====================================================
HardwareSerial sim7600(1);

// =====================================================
// USER SETTINGS
// =====================================================
const char *OWNER_NUMBER = "467190002980389";

// =====================================================
// TIMING
// =====================================================
const unsigned long MOTION_COOLDOWN_MS = 60000;
const unsigned long TRACK_INTERVAL_MS  = 30000;
const unsigned long GPS_RETRY_DELAY_MS = 2000;
const int GPS_MAX_TRIES                = 8;

// =====================================================
// STATE
// =====================================================
bool trackingActive = false;
unsigned long lastMotionAlert = 0;
unsigned long lastTrackUpdate = 0;
String modemBuffer = "";

// =====================================================
// GPS STRUCT
// =====================================================
struct GPSData {
  bool valid;
  float lat;
  float lon;
  String latStr;
  String lonStr;
};

// =====================================================
// FUNCTION DECLARATIONS
// =====================================================
void powerOnSIM7600();
String sendAT(const String &cmd, const String &expect, unsigned long timeout);
bool sendSMS(const String &number, const String &message);
String extractSmsBody(const String &raw);
String extractSmsSender(const String &raw);
bool isOwnerNumber(const String &sender);
float convertDegMinToDecimal(String dm, String hemi);
GPSData parseCGPSINFO(const String &resp);
GPSData readGPS();
String buildGoogleMapsLink(const GPSData &gps);
void sendLocationSMS();
void handleMotionAlert();
void handleLiveTracking();
void processSmsSlot(int slot);

// =====================================================
// MODEM POWER
// =====================================================
void powerOnSIM7600() {
  pinMode(SIM7600_PWRKEY_PIN, OUTPUT);
  digitalWrite(SIM7600_PWRKEY_PIN, HIGH);
  delay(200);

  digitalWrite(SIM7600_PWRKEY_PIN, LOW);
  delay(300);
  digitalWrite(SIM7600_PWRKEY_PIN, HIGH);

  delay(6000);
}

// =====================================================
// AT HELPER
// =====================================================
String sendAT(const String &cmd, const String &expect, unsigned long timeout) {
  while (sim7600.available()) {
    sim7600.read();
  }

  sim7600.println(cmd);

  String response = "";
  unsigned long start = millis();

  while (millis() - start < timeout) {
    while (sim7600.available()) {
      char c = (char)sim7600.read();
      response += c;

      if (expect.length() > 0 && response.indexOf(expect) != -1) {
        return response;
      }
    }
  }

  return response;
}

// =====================================================
// SEND SMS
// =====================================================
bool sendSMS(const String &number, const String &message) {
  sendAT("AT+CMGF=1", "OK", 3000);

  while (sim7600.available()) {
    sim7600.read();
  }

  sim7600.print("AT+CMGS=\"");
  sim7600.print(number);
  sim7600.print("\"\r");

  String prompt = "";
  unsigned long start = millis();

  while (millis() - start < 8000) {
    while (sim7600.available()) {
      char c = (char)sim7600.read();
      prompt += c;

      if (prompt.indexOf(">") != -1) {
        sim7600.print(message);
        sim7600.write(26);

        String result = "";
        unsigned long sendStart = millis();

        while (millis() - sendStart < 15000) {
          while (sim7600.available()) {
            char r = (char)sim7600.read();
            result += r;

            if (result.indexOf("OK") != -1) return true;
            if (result.indexOf("ERROR") != -1) return false;
          }
        }
      }
    }
  }

  return false;
}

// =====================================================
// SMS PARSING
// =====================================================
String extractSmsBody(const String &raw) {
  int headerEnd = raw.indexOf('\n');
  if (headerEnd == -1) return "";

  String body = raw.substring(headerEnd + 1);
  body.trim();

  int okPos = body.lastIndexOf("OK");
  if (okPos != -1) {
    body = body.substring(0, okPos);
  }

  body.trim();
  return body;
}

String extractSmsSender(const String &raw) {
  int idx = raw.indexOf("+CMGR:");
  if (idx == -1) return "";

  int lineEnd = raw.indexOf('\n', idx);
  String header = (lineEnd == -1) ? raw.substring(idx) : raw.substring(idx, lineEnd);

  int q1 = header.indexOf('"');
  if (q1 == -1) return "";
  int q2 = header.indexOf('"', q1 + 1);
  if (q2 == -1) return "";
  int q3 = header.indexOf('"', q2 + 1);
  if (q3 == -1) return "";
  int q4 = header.indexOf('"', q3 + 1);
  if (q4 == -1) return "";

  return header.substring(q3 + 1, q4);
}

bool isOwnerNumber(const String &sender) {
  if (sender.length() == 0) return false;
  return sender.indexOf(OWNER_NUMBER) != -1;
}

// =====================================================
// GPS HELPERS
// =====================================================
float convertDegMinToDecimal(String dm, String hemi) {
  if (dm.length() < 4) return 0.0;

  int dot = dm.indexOf('.');
  if (dot == -1) return 0.0;

  int degDigits = (dot > 4) ? 3 : 2;
  float degrees = dm.substring(0, degDigits).toFloat();
  float minutes = dm.substring(degDigits).toFloat();

  float decimal = degrees + (minutes / 60.0);

  if (hemi == "S" || hemi == "W") {
    decimal = -decimal;
  }

  return decimal;
}

GPSData parseCGPSINFO(const String &resp) {
  GPSData gps = {false, 0.0, 0.0, "", ""};

  int idx = resp.indexOf("+CGPSINFO:");
  if (idx == -1) return gps;

  int endLine = resp.indexOf('\n', idx);
  String line = (endLine == -1) ? resp.substring(idx) : resp.substring(idx, endLine);
  line.trim();

  int colon = line.indexOf(':');
  if (colon == -1) return gps;

  String data = line.substring(colon + 1);
  data.trim();

  int p1 = data.indexOf(',');
  if (p1 == -1) return gps;
  int p2 = data.indexOf(',', p1 + 1);
  if (p2 == -1) return gps;
  int p3 = data.indexOf(',', p2 + 1);
  if (p3 == -1) return gps;
  int p4 = data.indexOf(',', p3 + 1);
  if (p4 == -1) return gps;

  String rawLat = data.substring(0, p1);
  String ns     = data.substring(p1 + 1, p2);
  String rawLon = data.substring(p2 + 1, p3);
  String ew     = data.substring(p3 + 1, p4);

  rawLat.trim();
  ns.trim();
  rawLon.trim();
  ew.trim();

  if (rawLat.length() == 0 || rawLon.length() == 0) return gps;

  gps.lat = convertDegMinToDecimal(rawLat, ns);
  gps.lon = convertDegMinToDecimal(rawLon, ew);
  gps.latStr = String(gps.lat, 6);
  gps.lonStr = String(gps.lon, 6);
  gps.valid = true;

  return gps;
}

GPSData readGPS() {
  GPSData gps = {false, 0.0, 0.0, "", ""};

  sendAT("AT+CGPS=1", "OK", 5000);

  for (int i = 0; i < GPS_MAX_TRIES; i++) {
    delay(GPS_RETRY_DELAY_MS);
    String resp = sendAT("AT+CGPSINFO", "OK", 6000);
    Serial.println("----- CGPSINFO RAW -----");
    Serial.println(resp);
    Serial.println("------------------------");

    gps = parseCGPSINFO(resp);
    if (gps.valid) return gps;
  }

  return gps;
}

String buildGoogleMapsLink(const GPSData &gps) {
  return "https://maps.google.com/?q=" + gps.latStr + "," + gps.lonStr;
}

// =====================================================
// ACTIONS
// =====================================================
void sendLocationSMS() {
  GPSData gps = readGPS();

  if (!gps.valid) {
    sendSMS(OWNER_NUMBER, "GPS fix not available yet.");
    return;
  }

  String msg = "Location: " + buildGoogleMapsLink(gps);
  sendSMS(OWNER_NUMBER, msg);
}

void handleMotionAlert() {
  if (digitalRead(MOTION_PIN) != HIGH) return;

  unsigned long now = millis();
  if (now - lastMotionAlert < MOTION_COOLDOWN_MS) return;

  lastMotionAlert = now;
  sendSMS(OWNER_NUMBER, "ALERT: Motion detected.");
}

void handleLiveTracking() {
  if (!trackingActive) return;

  unsigned long now = millis();
  if (now - lastTrackUpdate < TRACK_INTERVAL_MS) return;

  lastTrackUpdate = now;
  sendLocationSMS();
}

// =====================================================
// SMS SLOT PROCESSOR
// =====================================================
void processSmsSlot(int slot) {
  sendAT("AT+CMGF=1", "OK", 3000);
  String raw = sendAT("AT+CMGR=" + String(slot), "OK", 5000);

  Serial.println("----- CMGR RAW -----");
  Serial.println(raw);
  Serial.println("--------------------");

  String upper = raw;
  upper.toUpperCase();

  if (upper.indexOf("\nL") != -1 || upper.indexOf("\r\nL") != -1 || upper.endsWith("L")) {
    sendLocationSMS();
  } else if (upper.indexOf("\nT") != -1 || upper.indexOf("\r\nT") != -1 || upper.endsWith("T")) {
    trackingActive = true;
    sendSMS(OWNER_NUMBER, "Live tracking started.");
  } else if (upper.indexOf("\nS") != -1 || upper.indexOf("\r\nS") != -1 || upper.endsWith("S")) {
    trackingActive = false;
    sendSMS(OWNER_NUMBER, "Live tracking stopped.");
  } else {
    sendSMS(OWNER_NUMBER, "Unknown command. Use L, T, or S.");
  }

  sendAT("AT+CMGD=" + String(slot), "OK", 3000);
}

// =====================================================
// SETUP
// =====================================================
void setup() {
  Serial.begin(115200);
  delay(5000);

  Serial.println("Testing... Serial is alive!");

  pinMode(MOTION_PIN, INPUT);

  powerOnSIM7600();

  sim7600.begin(115200, SERIAL_8N1, SIM7600_RX_PIN, SIM7600_TX_PIN);
  delay(3000);

  Serial.println("Testing modem...");
  Serial.println(sendAT("AT", "OK", 3000));
  Serial.println(sendAT("AT+CMGF=1", "OK", 3000));
  Serial.println(sendAT("AT+CNMI=2,1", "OK", 3000));

  Serial.println("SMS + GPS tracker ready.");
}

// =====================================================
// LOOP
// =====================================================
void loop() {
  while (sim7600.available()) {
    char c = (char)sim7600.read();
    modemBuffer += c;
    Serial.write(c);

    int idx = modemBuffer.indexOf("+CMTI:");
    if (idx != -1) {
      int comma = modemBuffer.lastIndexOf(',');
      if (comma != -1) {
        int slot = modemBuffer.substring(comma + 1).toInt();
        if (slot > 0) {
          processSmsSlot(slot);
        }
      }
      modemBuffer = "";
    }

    if (modemBuffer.length() > 160) {
      modemBuffer = "";
    }
  }

  handleMotionAlert();
  handleLiveTracking();