/************************************************************** TinyGSM Getting Started guide: https://tiny.cc/tinygsm-readme NOTE: Some of the functions may be unavailable for your modem. Just comment them out. https://simcom.ee/documents/SIM7600C/SIM7500_SIM7600%20Series_AT%20Command%20Manual_V1.01.pdf **************************************************************/ #define TINY_GSM_MODEM_SIM7600 // Set serial for debug console (to the Serial Monitor, default speed 115200) #define SerialMon Serial // Set serial for AT commands (to the module) // Use Hardware Serial on Mega, Leonardo, Micro #define SerialAT Serial1 // See all AT commands, if wanted #define DUMP_AT_COMMANDS // Define the serial console for debug prints, if needed #define TINY_GSM_DEBUG SerialMon /* Tests enabled */ #define TINY_GSM_TEST_GPRS true #define TINY_GSM_TEST_TCP true // #define TINY_GSM_TEST_CALL true // #define TINY_GSM_TEST_SMS true // #define TINY_GSM_TEST_USSD true // #define TINY_GSM_TEST_TEMPERATURE true // #define TINY_GSM_TEST_TIME true #define TINY_GSM_TEST_GPS true // powerdown modem after tests #define TINY_GSM_POWERDOWN true // #define TEST_RING_RI_PIN true // set GSM PIN, if any #define GSM_PIN "" // Set phone numbers, if you want to test SMS and Calls // #define SMS_TARGET "+380xxxxxxxxx" // #define CALL_TARGET "+380xxxxxxxxx" #define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */ #define TIME_TO_SLEEP 30 /* Time ESP32 will go to sleep (in seconds) */ #define UART_BAUD 115200 #define MODEM_TX 27 #define MODEM_RX 26 #define MODEM_PWRKEY 4 #define MODEM_DTR 32 #define MODEM_RI 33 #define MODEM_FLIGHT 25 #define MODEM_STATUS 34 #define SD_MISO 2 #define SD_MOSI 15 #define SD_SCLK 14 #define SD_CS 13 #define LED_PIN 12 // Default GPRS credentials const char defaultAPN[] = "YourAPN"; // const char apn[] = "ibasis.iot"; const char defaultGprsUser[] = "YourGprsUser"; const char defaultGprsPass[] = "YourGprsPass"; // Default WiFi credentials const char* defaultSSID = "AP_1_IOT"; const char* defaultPassword = "YOUR-WIFI-PASSWORD"; // Default Access Point credentials const char* defaultAPSSID = "ESP32-AP"; const char* defaultAPPassword = "12345678"; // Server details to test TCP/SSL const char testServer[] = "vsh.pp.ua"; const char resource[] = "/TinyGSM/logo.txt"; #include #include #include #include #include #include #include #include #include #include #include //#include "utilities.h" #ifdef DUMP_AT_COMMANDS #include StreamDebugger debugger(SerialAT, SerialMon); TinyGsm modem(debugger); #else TinyGsm modem(SerialAT); #endif AsyncWebServer server(80); ESPWebFileManager fileManager; Preferences preferences; void connectToWiFi() { // Read saved WiFi credentials preferences.begin("wifi", true); String ssid = preferences.getString("ssid", ""); String password = preferences.getString("password", ""); preferences.end(); if (ssid != "") { // Connect to WiFi with saved credentials WiFi.begin(ssid.c_str(), password.c_str()); Serial.printf("Connecting to WiFi SSID: %s\n", ssid.c_str()); } else { // Use default credentials if no saved credentials are found WiFi.begin(defaultSSID, defaultPassword); Serial.println("No saved WiFi credentials found, using default credentials"); Serial.printf("Connecting to WiFi SSID: %s\n", defaultSSID); } // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } if (WiFi.status() == WL_CONNECTED) { Serial.println("\nConnected to WiFi"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); } else { Serial.println("\nFailed to connect to WiFi"); } } void setupAccessPoint() { // Read saved AP credentials preferences.begin("ap", true); String apSSID = preferences.getString("apSSID", defaultAPSSID); String apPassword = preferences.getString("apPassword", defaultAPPassword); preferences.end(); Serial.println("Setting up Access Point..."); bool result = WiFi.softAP(apSSID.c_str(), apPassword.c_str()); if (result) { Serial.println("Access Point started successfully!"); Serial.print("AP IP Address: "); Serial.println(WiFi.softAPIP()); } else { Serial.println("Failed to start Access Point."); } } void setupWebServer() { // Serve HTML file server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ // Read saved WiFi credentials preferences.begin("wifi", true); String ssid = preferences.getString("ssid", defaultSSID); String password = preferences.getString("password", defaultPassword); preferences.end(); // Read saved AP credentials preferences.begin("ap", true); String apSSID = preferences.getString("apSSID", defaultAPSSID); String apPassword = preferences.getString("apPassword", defaultAPPassword); preferences.end(); // Read saved GPRS credentials preferences.begin("gprs", true); String apn = preferences.getString("apn", defaultAPN); String gprsUser = preferences.getString("gprsUser", defaultGprsUser); String gprsPass = preferences.getString("gprsPass", defaultGprsPass); preferences.end(); // Read saved GSM PIN preferences.begin("gsm", true); String gsmPin = preferences.getString("gsmPin", GSM_PIN); preferences.end(); // Get IP addresses String wifiIP = WiFi.isConnected() ? WiFi.localIP().toString() : "Not connected"; String apIP = WiFi.softAPIP().toString(); String gprsIP = modem.localIP().toString(); // Get MAC addresses String wifiMAC = WiFi.macAddress(); String apMAC = WiFi.softAPmacAddress(); String gprsMAC = modem.getIMEI(); // Using IMEI as a unique identifier // Get GPRS status and other details bool gprsStatus = modem.isGprsConnected(); String gprsStatusStr = gprsStatus ? "connected" : "not connected"; String ccid = modem.getSimCCID(); String imei = modem.getIMEI(); String imsi = modem.getIMSI(); String cop = modem.getOperator(); int csq = modem.getSignalQuality(); String signalQuality = String(csq); // Get GPS data float lat2 = 0; float lon2 = 0; float speed2 = 0; float alt2 = 0; int vsat2 = 0; int usat2 = 0; float accuracy2 = 0; int year2 = 0; int month2 = 0; int day2 = 0; int hour2 = 0; int min2 = 0; int sec2 = 0; String latitude, longitude, altitude, speed, visibleSatellites, usedSatellites, accuracy, date, time; if (modem.getGPS(&lat2, &lon2, &speed2, &alt2, &vsat2, &usat2, &accuracy2, &year2, &month2, &day2, &hour2, &min2, &sec2)) { latitude = String(lat2, 8); longitude = String(lon2, 8); altitude = String(alt2); speed = String(speed2); visibleSatellites = String(vsat2); usedSatellites = String(usat2); accuracy = String(accuracy2); date = String(year2) + "-" + String(month2) + "-" + String(day2); time = String(hour2) + ":" + String(min2) + ":" + String(sec2); } else { latitude = "N/A"; longitude = "N/A"; altitude = "N/A"; speed = "N/A"; visibleSatellites = "N/A"; usedSatellites = "N/A"; accuracy = "N/A"; date = "N/A"; time = "N/A"; } // Read the HTML file from the filesystem File file = FFat.open("/web_admin.html", "r"); if (!file) { request->send(500, "text/plain", "Failed to open web_admin.html"); return; } // Read the file content into a string String html = file.readString(); file.close(); // Replace placeholders with actual values html.replace("{{WiFiSSID}}", ssid); html.replace("{{WiFiPassword}}", password); html.replace("{{WiFiIP}}", wifiIP); html.replace("{{WiFiMAC}}", wifiMAC); html.replace("{{APSSID}}", apSSID); html.replace("{{APPassword}}", apPassword); html.replace("{{APIP}}", apIP); html.replace("{{APMAC}}", apMAC); html.replace("{{APN}}", apn); html.replace("{{GPRSUser}}", gprsUser); html.replace("{{GPRSPass}}", gprsPass); html.replace("{{GPRSIP}}", gprsIP); html.replace("{{GPRSMAC}}", gprsMAC); html.replace("{{GPRSStatus}}", gprsStatusStr); html.replace("{{CCID}}", ccid); html.replace("{{IMEI}}", imei); html.replace("{{IMSI}}", imsi); html.replace("{{Operator}}", cop); html.replace("{{SignalQuality}}", signalQuality); html.replace("{{GSMPIN}}", gsmPin); html.replace("{{Latitude}}", latitude); html.replace("{{Longitude}}", longitude); html.replace("{{Altitude}}", altitude); html.replace("{{Speed}}", speed); html.replace("{{VisibleSatellites}}", visibleSatellites); html.replace("{{UsedSatellites}}", usedSatellites); html.replace("{{Accuracy}}", accuracy); html.replace("{{Date}}", date); html.replace("{{Time}}", time); // Send the modified HTML content request->send(200, "text/html", html); }); // Handle WiFi configuration form submission server.on("/setWiFi", HTTP_POST, [](AsyncWebServerRequest *request) { String ssid = request->getParam("ssid", true)->value(); String password = request->getParam("password", true)->value(); // Save the credentials to a secure location preferences.begin("wifi", false); preferences.putString("ssid", ssid); preferences.putString("password", password); preferences.end(); Serial.printf("New WiFi SSID: %s, Password: %s\n", ssid.c_str(), password.c_str()); // Restart WiFi with new credentials WiFi.disconnect(); WiFi.begin(ssid.c_str(), password.c_str()); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } if (WiFi.status() == WL_CONNECTED) { Serial.println("\nConnected to WiFi"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); } else { Serial.println("\nFailed to connect to WiFi"); } // Send a response with a popup alert String response = ""; request->send(200, "text/html", response); }); // Handle Access Point configuration form submission server.on("/setAP", HTTP_POST, [](AsyncWebServerRequest *request) { String apSSID = request->getParam("apSSID", true)->value(); String apPassword = request->getParam("apPassword", true)->value(); // Save the credentials to a secure location preferences.begin("ap", false); preferences.putString("apSSID", apSSID); preferences.putString("apPassword", apPassword); preferences.end(); Serial.printf("New AP SSID: %s, Password: %s\n", apSSID.c_str(), apPassword.c_str()); // Restart Access Point with new credentials WiFi.softAPdisconnect(true); bool result = WiFi.softAP(apSSID.c_str(), apPassword.c_str()); if (result) { Serial.println("Access Point started successfully!"); Serial.print("AP IP Address: "); Serial.println(WiFi.softAPIP()); } else { Serial.println("Failed to start Access Point."); } // Send a response with a popup alert String response = ""; request->send(200, "text/html", response); }); // Handle GPRS configuration form submission server.on("/setGPRS", HTTP_POST, [](AsyncWebServerRequest *request) { String apn = request->getParam("apn", true)->value(); String gprsUser = request->getParam("gprsUser", true)->value(); String gprsPass = request->getParam("gprsPass", true)->value(); // Save the credentials to a secure location preferences.begin("gprs", false); preferences.putString("apn", apn); preferences.putString("gprsUser", gprsUser); preferences.putString("gprsPass", gprsPass); preferences.end(); Serial.printf("New GPRS APN: %s, User: %s, Pass: %s\n", apn.c_str(), gprsUser.c_str(), gprsPass.c_str()); // Restart GPRS with new credentials modem.gprsDisconnect(); delay(1000); // Wait for disconnection if (modem.gprsConnect(apn.c_str(), gprsUser.c_str(), gprsPass.c_str())) { Serial.println("GPRS reconnected successfully!"); } else { Serial.println("Failed to reconnect GPRS."); } // Send a response with a popup alert String response = ""; request->send(200, "text/html", response); }); // Handle GSM PIN configuration form submission server.on("/setGSM", HTTP_POST, [](AsyncWebServerRequest *request) { String gsmPin = request->getParam("gsmPin", true)->value(); // Save the GSM PIN to a secure location preferences.begin("gsm", false); preferences.putString("gsmPin", gsmPin); preferences.end(); Serial.printf("New GSM PIN: %s\n", gsmPin.c_str()); // Send a response with a popup alert String response = ""; request->send(200, "text/html", response); }); // Start server server.begin(); Serial.println("Web server started."); } void fatfs () { if (!FFat.begin(true)) { // Format on fail: 'true' forces formatting if mounting fails Serial.println("Failed to initialize eMMC storage (FFat). Trying to format..."); if (!FFat.format()) { Serial.println("FFat format failed. Check partition table and storage."); return; // Halt setup if FFat fails } if (!FFat.begin()) { Serial.println("Failed to mount FFat after formatting."); return; } } Serial.println("FFat initialized successfully."); } void sdcard() { //Initialize SDCard SPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS); if (!SD.begin(SD_CS)) { Serial.println("SDCard MOUNT FAIL"); } else { uint32_t cardSize = SD.cardSize() / (1024 * 1024); String str = "SDCard Size: " + String(cardSize) + "MB"; Serial.println(str); } } void setup() { // Set console baud rate SerialMon.begin(115200); delay(10); // Set GSM module baud rate SerialAT.begin(UART_BAUD, SERIAL_8N1, MODEM_RX, MODEM_TX); /* The indicator light of the board can be controlled */ pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); /* MODEM_PWRKEY IO:4 The power-on signal of the modulator must be given to it, otherwise the modulator will not reply when the command is sent */ pinMode(MODEM_PWRKEY, OUTPUT); digitalWrite(MODEM_PWRKEY, HIGH); delay(300); //Need delay digitalWrite(MODEM_PWRKEY, LOW); /* MODEM_FLIGHT IO:25 Modulator flight mode control, need to enable modulator, this pin must be set to high */ pinMode(MODEM_FLIGHT, OUTPUT); digitalWrite(MODEM_FLIGHT, HIGH); fatfs (); sdcard(); connectToWiFi(); setupAccessPoint(); setupWebServer(); // Uncomment below will perform loopback test // while (1) { // while (SerialMon.available()) { // SerialAT.write(SerialMon.read()); // } // while (SerialAT.available()) { // SerialMon.write(SerialAT.read()); // } // } // Read saved GPRS credentials preferences.begin("gprs", true); String apn = preferences.getString("apn", defaultAPN); String gprsUser = preferences.getString("gprsUser", defaultGprsUser); String gprsPass = preferences.getString("gprsPass", defaultGprsPass); preferences.end(); // Read saved GSM PIN preferences.begin("gsm", true); String gsmPin = preferences.getString("gsmPin", GSM_PIN); preferences.end(); // Initialize FATFS (Change to other types as needed, Valid types: FS_SD_CARD, FS_SPIFFS, FS_LITTLEFS, FS_FATFS ) if (!fileManager.initFileSystem(ESPWebFileManager::FS_FATFS, true)) { DEBUG_SERIAL.println("Failed to initialize file system"); } fileManager.setServer(&server); server.begin(); DEBUG_SERIAL.println("Web server started"); } void light_sleep(uint32_t sec ) { esp_sleep_enable_timer_wakeup(sec * 1000000ULL); esp_light_sleep_start(); } void loop() { bool res ; // Restart takes quite some time // To skip it, call init() instead of restart() DBG("Initializing modem..."); if (!modem.init()) { DBG("Failed to restart modem, delaying 10s and retrying"); return; } // // // Restart takes quite some time // // To skip it, call init() instead of restart() // DBG("Initializing modem..."); // if (!modem.restart()) { // DBG("Failed to restart modem, delaying 10s and retrying"); // // restart autobaud in case GSM just rebooted // return; // } #if TINY_GSM_TEST_GPRS /* Preferred mode selection : AT+CNMP 2 – Automatic 13 – GSM Only 14 – WCDMA Only 38 – LTE Only 59 – TDS-CDMA Only 9 – CDMA Only 10 – EVDO Only 19 – GSM+WCDMA Only 22 – CDMA+EVDO Only 48 – Any but LTE 60 – GSM+TDSCDMA Only 63 – GSM+WCDMA+TDSCDMA Only 67 – CDMA+EVDO+GSM+WCDMA+TDSCDMA Only 39 – GSM+WCDMA+LTE Only 51 – GSM+LTE Only 54 – WCDMA+LTE Only */ String ret; // do { // ret = modem.setNetworkMode(2); // delay(500); // } while (ret != "OK"); ret = modem.setNetworkMode(2); DBG("setNetworkMode:", ret); //https://github.com/vshymanskyy/TinyGSM/pull/405 uint8_t mode = modem.getGNSSMode(); DBG("GNSS Mode:", mode); /** CGNSSMODE: , This command is used to configure GPS, GLONASS, BEIDOU and QZSS support mode. gnss_mode: 0 : GLONASS 1 : BEIDOU 2 : GALILEO 3 : QZSS dpo_mode : 0 disable 1 enable */ modem.setGNSSMode(1, 1); light_sleep(1); String name = modem.getModemName(); DBG("Modem Name:", name); String modemInfo = modem.getModemInfo(); DBG("Modem Info:", modemInfo); // Unlock your SIM card with a PIN if needed if (GSM_PIN && modem.getSimStatus() != 3) { modem.simUnlock(GSM_PIN); } DBG("Waiting for network..."); if (!modem.waitForNetwork(600000L)) { light_sleep(10); return; } if (modem.isNetworkConnected()) { DBG("Network connected"); } #endif #if TINY_GSM_TEST_GPRS // Read saved GPRS credentials preferences.begin("gprs", true); String apn = preferences.getString("apn", defaultAPN); String gprsUser = preferences.getString("gprsUser", defaultGprsUser); String gprsPass = preferences.getString("gprsPass", defaultGprsPass); preferences.end(); DBG("Connecting to", apn); if (!modem.gprsConnect(apn.c_str(), gprsUser.c_str(), gprsPass.c_str())) { light_sleep(10); return; } res = modem.isGprsConnected(); DBG("GPRS status:", res ? "connected" : "not connected"); String ccid = modem.getSimCCID(); DBG("CCID:", ccid); String imei = modem.getIMEI(); DBG("IMEI:", imei); String imsi = modem.getIMSI(); DBG("IMSI:", imsi); String cop = modem.getOperator(); DBG("Operator:", cop); IPAddress local = modem.localIP(); DBG("Local IP:", local); int csq = modem.getSignalQuality(); DBG("Signal quality:", csq); #endif #if TINY_GSM_TEST_USSD && defined TINY_GSM_MODEM_HAS_SMS String ussd_balance = modem.sendUSSD("*111#"); DBG("Balance (USSD):", ussd_balance); String ussd_phone_num = modem.sendUSSD("*161#"); DBG("Phone number (USSD):", ussd_phone_num); #endif #if TINY_GSM_TEST_TCP && defined TINY_GSM_MODEM_HAS_TCP TinyGsmClient client(modem, 0); const int port = 80; DBG("Connecting to ", testServer); if (!client.connect(testServer, port)) { DBG("... failed"); } else { // Make a HTTP GET request: client.print(String("GET ") + resource + " HTTP/1.0\r\n"); client.print(String("Host: ") + testServer + "\r\n"); client.print("Connection: close\r\n\r\n"); // Wait for data to arrive uint32_t start = millis(); while (client.connected() && !client.available() && millis() - start < 30000L) { delay(100); }; // Read data start = millis(); while (client.connected() && millis() - start < 5000L) { while (client.available()) { SerialMon.write(client.read()); start = millis(); } } client.stop(); } #endif #if TINY_GSM_TEST_CALL && defined(CALL_TARGET) DBG("Calling:", CALL_TARGET); SerialAT.println("ATD"CALL_TARGET";"); modem.waitResponse(); light_sleep(20); #endif #if TINY_GSM_TEST_GPS && defined TINY_GSM_MODEM_HAS_GPS DBG("Enabling GPS/GNSS/GLONASS"); modem.enableGPS(); light_sleep(2); float lat2 = 0; float lon2 = 0; float speed2 = 0; float alt2 = 0; int vsat2 = 0; int usat2 = 0; float accuracy2 = 0; int year2 = 0; int month2 = 0; int day2 = 0; int hour2 = 0; int min2 = 0; int sec2 = 0; DBG("Requesting current GPS/GNSS/GLONASS location"); for (;;) { digitalWrite(LED_PIN, !digitalRead(LED_PIN)); if (modem.getGPS(&lat2, &lon2, &speed2, &alt2, &vsat2, &usat2, &accuracy2, &year2, &month2, &day2, &hour2, &min2, &sec2)) { DBG("Latitude:", String(lat2, 8), "\tLongitude:", String(lon2, 8)); DBG("Speed:", speed2, "\tAltitude:", alt2); DBG("Visible Satellites:", vsat2, "\tUsed Satellites:", usat2); DBG("Accuracy:", accuracy2); DBG("Year:", year2, "\tMonth:", month2, "\tDay:", day2); DBG("Hour:", hour2, "\tMinute:", min2, "\tSecond:", sec2); break; } else { light_sleep(2); } } DBG("Retrieving GPS/GNSS/GLONASS location again as a string"); String gps_raw = modem.getGPSraw(); DBG("GPS/GNSS Based Location String:", gps_raw); DBG("Disabling GPS"); modem.disableGPS(); #endif #if TINY_GSM_TEST_TIME && defined TINY_GSM_MODEM_HAS_TIME int year3 = 0; int month3 = 0; int day3 = 0; int hour3 = 0; int min3 = 0; int sec3 = 0; float timezone = 0; for (int8_t i = 5; i; i--) { DBG("Requesting current network time"); if (modem.getNetworkTime(&year3, &month3, &day3, &hour3, &min3, &sec3, &timezone)) { DBG("Year:", year3, "\tMonth:", month3, "\tDay:", day3); DBG("Hour:", hour3, "\tMinute:", min3, "\tSecond:", sec3); DBG("Timezone:", timezone); break; } else { DBG("Couldn't get network time, retrying in 15s."); light_sleep(15); } } DBG("Retrieving time again as a string"); String time = modem.getGSMDateTime(DATE_FULL); DBG("Current Network Time:", time); #endif #if TINY_GSM_TEST_GPRS modem.gprsDisconnect(); light_sleep(5); if (!modem.isGprsConnected()) { DBG("GPRS disconnected"); } else { DBG("GPRS disconnect: Failed."); } #endif #if TINY_GSM_TEST_TEMPERATURE && defined TINY_GSM_MODEM_HAS_TEMPERATURE float temp = modem.getTemperature(); DBG("Chip temperature:", temp); #endif #ifdef TEST_RING_RI_PIN #ifdef MODEM_RI //Set RI Pin input pinMode(MODEM_RI, INPUT); Serial.println("Wait for call in"); //When is no calling ,RI pin is high level while (digitalRead(MODEM_RI)) { Serial.print('.'); delay(500); } Serial.println("call in "); //Wait for 5 seconds to connect the call delay(5000); //Accept call SerialAT.println("ATA"); // Hang up after 20 seconds of talk time delay(20000); SerialAT.println("ATH"); #endif //MODEM_RI #endif //TEST_RING_RI_PIN #ifdef MODEM_DTR1 modem.sleepEnable(); delay(100); // test modem response , res == 0 , modem is sleep res = modem.testAT(); Serial.print(" Test AT result -> "); Serial.println(res); delay(1000); Serial.println("Use DTR Pin Wakeup"); pinMode(MODEM_DTR, OUTPUT); //Set DTR Pin low , wakeup modem . digitalWrite(MODEM_DTR, LOW); // test modem response , res == 1 , modem is wakeup res = modem.testAT(); Serial.print(" Test AT result -> "); Serial.println(res); #endif #if TINY_GSM_POWERDOWN // Try to power-off (modem may decide to restart automatically) // To turn off modem completely, please use Reset/Enable pins modem.poweroff(); DBG("Poweroff."); #endif SerialMon.printf("End of tests. Enable deep sleep , Will wake up in %d seconds", TIME_TO_SLEEP); // Wait for modem to power off light_sleep(5); esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); delay(200); esp_deep_sleep_start(); while (1); }