Files
Arduino/14041130/TestLCD/EC200U.h
2026-02-19 06:17:44 +03:30

1509 lines
44 KiB
C

#ifndef EC200U_H
#define EC200U_H
#include <Arduino.h>
#include "Config.h"
#include "Memory.h"
// -------------------- متغیرهای خارجی --------------------
extern HardwareSerial EC200U;
extern DeviceConfig config;
extern SensorData currentData;
extern bool networkConnected;
extern bool simConnected;
extern bool networkRegistered;
extern int signalStrength;
extern String lastMessage;
extern String currentAPN;
extern String tempPhoneNumber;
extern String tempTokenCode;
extern bool awaitingSMS2;
extern bool isInCall;
//extern bool calibrationComplete;
extern unsigned long lastUpload;
// Forward declarations
void initEC200U();
void updateNetworkStatus();
// -------------------- توابع کمکی جدید --------------------
bool checkAudioPlaybackStatus() {
Serial1.println("Checking audio playback status...");
EC200U.println("AT+QVTSTAT?");
String response = "";
unsigned long start = millis();
while (millis() - start < 2000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
}
if (response.indexOf("+QVTSTAT: 0,0") != -1) {
return true; // پخش تمام شده
} else if (response.indexOf("+QVTSTAT: 0,1") != -1) {
Serial1.println("Audio is playing");
return false; // در حال پخش است
} else {
Serial1.println("Unknown playback status");
return false;
}
}
inline bool sendAT(String cmd, uint16_t wait = 2000, bool showResponse = false) {
if (showResponse) {
Serial1.print(">> ");
Serial1.println(cmd);
}
EC200U.println(cmd);
String response = "";
unsigned long start = millis();
while (millis() - start < wait) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
if (showResponse) Serial1.write(c);
}
if (response.indexOf("OK") != -1) return true;
if (response.indexOf("ERROR") != -1) return false;
}
return false;
}
inline String stringSendAT(String cmd, uint16_t wait = 2000, bool showResponse = false) {
if (showResponse) {
Serial1.print(">> ");
Serial1.println(cmd);
}
EC200U.println(cmd);
String response = "";
unsigned long start = millis();
while (millis() - start < wait) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
if (showResponse) Serial1.write(c);
}
// اگر پاسخ کامل دریافت شده (دارای OK یا ERROR) خاتمه بده
if (response.indexOf("OK") != -1 ||
response.indexOf("ERROR") != -1 ||
response.indexOf("NO CARRIER") != -1 ||
response.indexOf("CONNECT") != -1) {
break;
}
}
return response;
}
// void initAudioSettings() {
// Serial1.println("Initializing audio settings...");
// // ریست تنظیمات صدا
// sendAT("AT+CRESET", 3000, true);
// delay(2000);
// // تنظیمات اولیه
// sendAT("AT+CLVL=5", 2000, true); // سطح صدا متوسط
// sendAT("AT+CMUT=0", 2000, true); // غیرفعال کردن mute
// sendAT("AT+QDAI=5", 2000, true); // تنظیم رابط صوتی
// sendAT("AT+VTD=1", 2000, true); // تنظیم تون DTMF
// // تنظیمات کدک صوتی
// sendAT("AT+QMBNCFG=\"select\",0", 2000, true);
// sendAT("AT+QCODECCFG=0,2,1", 2000, true); // AMR-NB, 12.2kbps
// Serial1.println("✅ Audio settings initialized");
// }
bool sendSMS(String numbers, String messages) {
Serial1.println("\n📱 SENDING SMS - FINAL OPTIMIZED VERSION");
// تقسیم شماره‌ها
int phoneCount = 0;
String phoneNumbers[10];
String numbersCopy = numbers;
numbersCopy.replace(" ", "");
int startIdx = 0;
int commaIdx = numbersCopy.indexOf(',');
while (commaIdx != -1 && phoneCount < 9) {
phoneNumbers[phoneCount] = numbersCopy.substring(startIdx, commaIdx);
phoneCount++;
startIdx = commaIdx + 1;
commaIdx = numbersCopy.indexOf(',', startIdx);
}
if (startIdx < numbersCopy.length()) {
phoneNumbers[phoneCount] = numbersCopy.substring(startIdx);
phoneCount++;
}
if (phoneCount == 0) {
Serial1.println("❌ No phone numbers");
return false;
}
// تقسیم پیام‌ها
int messageCount = 0;
String messageTexts[10];
String messagesCopy = messages;
startIdx = 0;
int atIdx = messagesCopy.indexOf('@');
while (atIdx != -1 && messageCount < 9) {
messageTexts[messageCount] = messagesCopy.substring(startIdx, atIdx);
messageCount++;
startIdx = atIdx + 1;
atIdx = messagesCopy.indexOf('@', startIdx);
}
if (startIdx < messagesCopy.length()) {
messageTexts[messageCount] = messagesCopy.substring(startIdx);
messageCount++;
}
if (messageCount == 0) {
Serial1.println("❌ No messages");
return false;
}
bool allSent = true;
int totalMessagesSent = 0;
// تنظیمات اولیه ماژول (یک بار انجام می‌شود)
Serial1.println("📋 Initializing module...");
while (EC200U.available()) EC200U.read(); // پاکسازی بافر
EC200U.println("AT+CMGF=1");
delay(50);
EC200U.println("AT+CSMP=17,167,0,8");
delay(50);
EC200U.println("AT+CSCS=\"UTF-8\"");
delay(50);
while (EC200U.available()) EC200U.read(); // پاکسازی مجدد
// ارسال به همه شماره‌ها
for (int i = 0; i < phoneCount; i++) {
String phone = phoneNumbers[i];
if (phone.length() < 10) {
Serial1.print("❌ Invalid number: ");
Serial1.println(phone);
allSent = false;
continue;
}
// انتخاب پیام
String message;
if (messageCount == 1) {
message = messageTexts[0];
} else if (i < messageCount) {
message = messageTexts[i];
} else {
message = messageTexts[messageCount - 1];
}
if (message.length() == 0) {
Serial1.print("❌ Empty message for: ");
Serial1.println(phone);
allSent = false;
continue;
}
Serial1.print("📤 To: ");
Serial1.print(phone);
Serial1.print(" | Msg: ");
if (message.length() > 30) {
Serial1.print(message.substring(0, 30));
Serial1.print("...");
} else {
Serial1.print(message);
}
Serial1.println();
// پاکسازی بافر قبل از ارسال
while (EC200U.available()) EC200U.read();
// ارسال دستور CMGS
EC200U.print("AT+CMGS=\"");
EC200U.print(phone);
EC200U.println("\"");
// منتظر prompt >
int timeout = 0;
bool gotPrompt = false;
while (timeout < 100) {
if (EC200U.available() && EC200U.read() == '>') {
gotPrompt = true;
break;
}
delay(50);
timeout++;
}
if (!gotPrompt) {
Serial1.println("❌ No prompt received");
allSent = false;
continue;
}
// ارسال متن (بدون خط جدید)
for (int j = 0; j < message.length(); j++) {
EC200U.write(message.charAt(j));
}
// ارسال Ctrl+Z
EC200U.write(26);
// بررسی نتیجه
timeout = 0;
bool sent = false;
String response = "";
while (timeout < 80) { // 8 ثانیه (80 * 100ms)
while (EC200U.available()) {
char c = EC200U.read();
response += c;
if (response.indexOf("+CMGS:") != -1 || response.indexOf("OK") != -1) {
sent = true;
break;
}
if (response.indexOf("ERROR") != -1 || response.indexOf("CMS ERROR") != -1) {
sent = false;
break;
}
}
if (sent || response.indexOf("ERROR") != -1) break;
delay(100);
timeout++;
}
if (sent || response.indexOf("ERROR") == -1) { // اگر خطایی نیامد، موفق فرض کن
totalMessagesSent++;
Serial1.println("✅ Sent successfully");
} else {
Serial1.println("❌ Failed");
allSent = false;
}
if (sent) {
Serial1.println("✅ Sent successfully");
} else {
Serial1.println("❌ Failed");
allSent = false;
}
// تاخیر بین ارسال‌ها
if (i < phoneCount - 1) {
Serial1.println("⏳ Waiting 2 seconds...");
delay(2000);
}
}
Serial1.print("\n📊 Result: ");
Serial1.print(totalMessagesSent);
Serial1.print("/");
Serial1.print(phoneCount);
Serial1.println(" messages sent");
return (totalMessagesSent > 0);
}
// {
// Serial1.println("\n📱 ارسال __ پیامک");
// Serial1.println("==============");
// // 1. تنظیم Text Mode
// if (!sendAT("AT+CMGF=1")) {
// Serial1.println("❌ خطا: Text Mode تنظیم نشد");
// return false;
// }
// // 2. تنظیم charset به UTF-8
// if (!sendAT("AT+CSCS=\"UTF-8\"")) {
// Serial1.println("❌ خطا: UTF-8 پشتیبانی نمی‌شود");
// return false;
// }
// // 3. تنظیم پارامترهای SMS (اختیاری)
// sendAT("AT+CSMP=1,167,0,8");
// // 4. ارسال دستور CMGS
// String cmd = "AT+CMGS=\"" + phoneNumber + "\"";
// EC200U.println(cmd);
// // منتظر prompt >
// delay(100);
// unsigned long startTime = millis();
// bool gotPrompt = false;
// while (millis() - startTime < 5000) {
// while (EC200U.available()) {
// if (EC200U.read() == '>') {
// gotPrompt = true;
// break;
// }
// }
// if (gotPrompt) break;
// }
// if (!gotPrompt) {
// Serial1.println("❌ خطا: Prompt دریافت نشد");
// return false;
// }
// // 5. ارسال متن UTF-8
// EC200U.println(message);
// delay(100);
// // 6. ارسال Ctrl+Z
// EC200U.write(26);
// // 7. دریافت پاسخ
// startTime = millis();
// String response = "";
// bool success = false;
// while (millis() - startTime < 15000) {
// while (EC200U.available()) {
// char c = EC200U.read();
// response += c;
// if (response.indexOf("+CMGS:") != -1) success = true;
// if (response.indexOf("+CMS ERROR") != -1) return false;
// }
// if (response.indexOf("OK") != -1) break;
// if (response.indexOf("ERROR") != -1) break;
// }
// if (success) {
// Serial1.println("✅ پیامک ارسال شد");
// return true;
// } else {
// Serial1.println("❌ ارسال ناموفق");
// return false;
// }
// }
// -------------------- پردازش SMS --------------------
inline void extractNumbersFromSMS2(String message, String numbers[], int &count) {
count = 0;
String current = "";
for (int i = 0; i < message.length(); i++) {
char c = message.charAt(i);
if (c >= '0' && c <= '9') {
current += c;
} else {
if (current.length() > 0) {
if (count < 10) {
numbers[count] = current;
count++;
}
current = "";
}
}
}
if (current.length() > 0 && count < 10) {
numbers[count] = current;
count++;
}
}
inline void updateNetworkStatus() {
if (!config.verified) {
simConnected = false;
networkRegistered = false;
signalStrength = 0;
return;
}
simConnected = sendAT("AT", 1000, false);
EC200U.println("AT+CSQ");
String response = "";
unsigned long start = millis();
while (millis() - start < 2000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
}
if (response.indexOf("OK") != -1 || response.indexOf("ERROR") != -1) break;
}
if (response.indexOf("+CSQ:") != -1) {
int idx = response.indexOf("+CSQ:");
int comma = response.indexOf(',', idx);
if (comma != -1) {
String rssiStr = response.substring(idx + 6, comma);
rssiStr.trim();
signalStrength = rssiStr.toInt();
if (signalStrength > 31) signalStrength = 0;
}
}
EC200U.println("AT+CREG?");
response = "";
start = millis();
while (millis() - start < 2000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
}
if (response.indexOf("OK") != -1 || response.indexOf("ERROR") != -1) break;
}
networkRegistered = (response.indexOf("+CREG:") != -1 &&
(response.indexOf(",1,") != -1 || response.indexOf(",5,") != -1));
}
inline int detectSMSType(String message) {
int count = 0;
String current = "";
for (int i = 0; i < message.length(); i++) {
char c = message.charAt(i);
if (c >= '0' && c <= '9') {
current += c;
} else {
if (current.length() > 0) {
count++;
current = "";
}
}
}
if (current.length() > 0) {
count++;
}
return (count >= 5) ? 2 : 1;
}
inline void connectToNetwork() {
Serial1.println("\n======== NETWORK CONNECTION ========");
lastMessage = "Connecting";
if (!config.verified) {
Serial1.println("❌ Cannot connect: Device not configured");
return;
}
currentAPN = simTypeToAPN(config.simType);
Serial1.print("Setting APN: ");
Serial1.println(currentAPN);
String apnCmd = "AT+CGDCONT=1,\"IP\",\"" + currentAPN + "\"";
sendAT(apnCmd, 2000, false);
Serial1.println("Waiting for network registration...");
bool registered = false;
for (int attempt = 1; attempt <= 30; attempt++) {
EC200U.println("AT+CREG?");
String response = "";
unsigned long start = millis();
while (millis() - start < 2000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
}
if (response.indexOf("OK") != -1) break;
}
if (response.indexOf(",1") != -1 || response.indexOf(",5") != -1) {
registered = true;
Serial1.print("✅ Network registered after ");
Serial1.print(attempt);
Serial1.println(" seconds");
break;
}
Serial1.print(" Attempt ");
Serial1.print(attempt);
Serial1.println("/30 - Searching...");
delay(1000);
}
if (!registered) {
Serial1.println("⚠️ Network registration timeout - continuing anyway");
}
Serial1.println("Deactivating old PDP context...");
sendAT("AT+QIDEACT=1", 5000, false);
delay(1000);
Serial1.println("Activating PDP context...");
if (sendAT("AT+QIACT=1", 30000, false)) {
networkConnected = true;
lastMessage = "Online";
Serial1.println("✅ Internet connection established!");
} else {
Serial1.println("First attempt failed, retrying...");
delay(2000);
if (sendAT("AT+QIACT=1", 30000, false)) {
networkConnected = true;
lastMessage = "Online";
Serial1.println("✅ Internet connection established on retry!");
} else {
networkConnected = false;
lastMessage = "Offline";
Serial1.println("❌ Failed to connect to internet");
}
}
if (networkConnected) {
Serial1.println("Configuring SSL for HTTPS...");
sendAT("AT+QSSLCFG=\"sslversion\",1,4", 2000, false);
sendAT("AT+QSSLCFG=\"ciphersuite\",1,0xFFFF", 2000, false);
sendAT("AT+QSSLCFG=\"seclevel\",1,0", 2000, false);
sendAT("AT+QHTTPCFG=\"sslctxid\",1", 2000, false);
Serial1.println("✅ SSL configured for HTTPS");
}
updateNetworkStatus();
Serial1.println("--- NETWORK STATUS ---");
Serial1.print(" SIM: ");
Serial1.println(simConnected ? "Connected" : "Not detected");
Serial1.print(" Network: ");
Serial1.println(networkRegistered ? "Registered" : "Searching");
Serial1.print(" Signal: ");
Serial1.print(signalStrength);
Serial1.println("/31");
Serial1.print(" Internet: ");
Serial1.println(networkConnected ? "Online" : "Offline");
Serial1.println("=================================\n");
}
inline void processSMS1(String message) {
Serial1.println("\n======== SMS1 RECEIVED ========");
Serial1.print("Raw Message: ");
Serial1.println(message);
String numbers[10];
int count = 0;
extractNumbersFromSMS2(message, numbers, count);
String phone = "";
String token = "";
if (count >= 2) {
phone = numbers[0];
token = numbers[1];
}
Serial1.print("Phone: ");
Serial1.println(phone);
Serial1.print("Token: ");
Serial1.println(token);
if (phone.length() >= 10 && token.length() == 5) {
tempPhoneNumber = phone;
tempTokenCode = token;
String verifyCode = generateVerificationCode(token);
String reply = "Code: " + verifyCode;
Serial1.print("Generated Verification Code: ");
Serial1.println(verifyCode);
Serial1.print("Sending SMS to: ");
Serial1.println(phone);
if (sendSMS(phone, reply)) {
Serial1.println("✅ SMS1: Verification code sent successfully!");
awaitingSMS2 = true;
lastMessage = "Wait SMS2";
} else {
Serial1.println("❌ SMS1: Failed to send verification code");
lastMessage = "SMS1 Failed";
}
} else {
Serial1.println("❌ SMS1: Invalid format - phone or token missing");
Serial1.print(" Phone length: ");
Serial1.print(phone.length());
Serial1.print(", Token length: ");
Serial1.println(token.length());
lastMessage = "Invalid SMS1";
}
Serial1.println("================================\n");
}
inline void processSMS2(String message) {
Serial1.println("\n======== SMS2 RECEIVED ========");
Serial1.print("Raw Message: ");
Serial1.println(message);
String numbers[10];
int count = 0;
extractNumbersFromSMS2(message, numbers, count);
Serial1.print("Numbers found: ");
Serial1.println(count);
for (int i = 0; i < count; i++) {
Serial1.print(" [");
Serial1.print(i);
Serial1.print("]: ");
Serial1.println(numbers[i]);
}
if (count >= 5) {
// 1. Device ID
String deviceId = numbers[0];
Serial1.print("Original Device ID: ");
Serial1.println(deviceId);
if (deviceId.length() > 2) {
deviceId = deviceId.substring(0, deviceId.length() - 2);
}
deviceId.toCharArray(config.deviceId, 16);
Serial1.print("Parsed Device ID: ");
Serial1.println(config.deviceId);
// 2. Upload Interval
if (numbers[1].length() > 1) {
config.uploadInterval = numbers[1].substring(1).toInt();
} else {
config.uploadInterval = numbers[1].toInt();
}
Serial1.print("Upload Interval: ");
Serial1.print(config.uploadInterval);
Serial1.println(" min");
// 3. SMS Settings
if (numbers[2].length() >= 2) {
config.smsEnabled = (numbers[2].charAt(0) == '1');
config.smsInterval = numbers[2].substring(1).toInt();
} else {
config.smsEnabled = false;
config.smsInterval = 0;
}
Serial1.print("SMS Enabled: ");
Serial1.println(config.smsEnabled ? "Yes" : "No");
Serial1.print("SMS Interval: ");
Serial1.print(config.smsInterval);
Serial1.println(" min");
// 4. SIM Type (index 4 if 6 numbers, else last)
int simIndex = (count >= 6) ? 4 : (count - 1);
String simValue = numbers[simIndex];
Serial1.print("SIM Value (raw): ");
Serial1.println(simValue);
if (simValue.length() >= 2) {
String simCode = simValue.substring(simValue.length() - 2);
if (simCode == "21") config.simType = SIM_HAMRAHE_AVAL;
else if (simCode == "22") config.simType = SIM_IRANCELL;
else if (simCode == "23") config.simType = SIM_RIGHTEL;
else if (simCode == "71") config.simType = SIM_HAMRAHE_AVAL;
else config.simType = SIM_UNKNOWN;
} else {
int simInt = simValue.toInt();
if (simInt == 21 || simInt == 71) config.simType = SIM_HAMRAHE_AVAL;
else if (simInt == 22) config.simType = SIM_IRANCELL;
else if (simInt == 23) config.simType = SIM_RIGHTEL;
else config.simType = SIM_UNKNOWN;
}
Serial1.print("SIM Type: ");
Serial1.println(simTypeToString(config.simType));
// 5. Phone number
if (tempPhoneNumber.length() > 0) {
tempPhoneNumber.toCharArray(config.serverPhoneNumber, 16);
} else {
strcpy(config.serverPhoneNumber, "");
}
Serial1.print("Server Phone: ");
Serial1.println(config.serverPhoneNumber);
// 6. Save and connect
config.verified = true;
saveConfig();
currentAPN = simTypeToAPN(config.simType);
awaitingSMS2 = false;
Serial1.println("\n✅ SMS2: Configuration Complete!");
Serial1.println("--- FINAL CONFIG ---");
Serial1.print(" Device ID: ");
Serial1.println(config.deviceId);
Serial1.print(" SIM Type: ");
Serial1.println(simTypeToString(config.simType));
Serial1.print(" APN: ");
Serial1.println(currentAPN);
Serial1.print(" Upload Int: ");
Serial1.print(config.uploadInterval);
Serial1.println(" min");
Serial1.print(" SMS Enabled: ");
Serial1.println(config.smsEnabled ? "Yes" : "No");
Serial1.print(" Server Phone: ");
Serial1.println(config.serverPhoneNumber);
Serial1.println("--------------------");
lastMessage = "Configured";
Serial1.println("Connecting to network...");
connectToNetwork();
} else {
Serial1.println("❌ SMS2: Invalid format - need at least 5 numbers");
Serial1.print(" Found only: ");
Serial1.println(count);
lastMessage = "Invalid SMS2";
}
Serial1.println("================================\n");
}
inline void checkSMS() {
if (!sendAT("AT", 2000, false)) return;
sendAT("AT+CMGF=1", 2000, false);
delay(100);
EC200U.println("AT+CMGL=\"REC UNREAD\"");
String response = "";
unsigned long start = millis();
while (millis() - start < 5000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
}
if (response.indexOf("OK") != -1) break;
}
if (response.indexOf("+CMGL:") != -1) {
int msgIndex = response.indexOf("+CMGL:");
int comma1 = response.indexOf(',', msgIndex);
int comma2 = response.indexOf(',', comma1 + 1);
int quote1 = response.indexOf('\"', comma2 + 1);
int quote2 = response.indexOf('\"', quote1 + 1);
if (quote1 != -1 && quote2 != -1) {
int msgStart = response.indexOf('\n', quote2) + 1;
int msgEnd = response.indexOf('\n', msgStart);
if (msgEnd == -1) msgEnd = response.length();
String message = response.substring(msgStart, msgEnd);
message.trim();
Serial1.println("\n📱 SMS received");
int smsType = detectSMSType(message);
if (config.verified) {
Serial1.println("⚠️ Already configured - try SMS Proccess2");
lastMessage = "Already Configured - try sms process 2";
processSMS2(message);
} else if (smsType == 1 && !awaitingSMS2) {
processSMS1(message);
} else if (smsType == 2 && awaitingSMS2) {
processSMS2(message);
} else if (smsType == 2 && !awaitingSMS2 && !config.verified) {
// این حالت برای زمانی است که مستقیم SMS2 دریافت شود
processSMS2(message);
} else {
Serial1.println("❌ Invalid SMS or wrong state");
lastMessage = "Invalid SMS";
}
String indexStr = response.substring(msgIndex + 6, comma1);
indexStr.trim();
sendAT("AT+CMGD=" + indexStr, 2000, false);
}
}
}
// -------------------- توابع مدیریت EC200U --------------------
inline void powerOffEC200U() {
Serial1.println("Powering off EC200U...");
sendAT("AT+QPOWD", 3000, true);
delay(3000);
digitalWrite(PWRKEY_PIN, HIGH);
delay(1500);
digitalWrite(PWRKEY_PIN, LOW);
Serial1.println("EC200U powered off");
networkConnected = false;
}
inline void initEC200U() {
Serial1.println("\n======== MODEM INITIALIZATION ========");
lastMessage = "Modem Initializing";
Serial1.println("Checking if modem is already running...");
bool modemAlreadyOn = sendAT("AT", 2000, false);
if (modemAlreadyOn) {
Serial1.println("✅ Modem is already ON");
lastMessage = "Modem Ready";
} else {
Serial1.println("Waiting for modem to boot (8s)...");
delay(8000);
if (!sendAT("AT", 5000, false)) {
Serial1.println("❌ Modem not responding!");
lastMessage = "Modem Err";
Serial1.println("=================================\n");
return;
}
Serial1.println("✅ Modem powered on successfully");
lastMessage = "Modem Ready";
}
digitalWrite(PWRKEY_PIN, LOW);
// تنظیمات اولیه
sendAT("AT+CMGF=1", 2000, false); // تنظیم فرمت SMS
sendAT("AT+CNMI=2,1,0,0,0", 2000, false); // اعلان SMS جدید
// تنظیمات صوتی
//initAudioSettings();
// فقط اگر config.verified بود به شبکه وصل شود
if (config.verified) {
Serial1.println("Device is configured, connecting to network...");
connectToNetwork();
} else {
Serial1.println("⏳ Device not configured. Waiting for configuration SMS...");
Serial1.println("📱 Send SMS1 format: PHONENUMBER TOKENCODE");
lastMessage = "Wait SMS1";
}
updateNetworkStatus();
Serial1.println("=================================\n");
}
// -------------------- توابع SSL و HTTP --------------------
inline void configureSSL() {
Serial1.println("Configuring SSL for HTTPS...");
sendAT("AT+QSSLCFG=\"sslversion\",1,4", 2000, false);
sendAT("AT+QSSLCFG=\"ciphersuite\",1,0xFFFF", 2000, false);
sendAT("AT+QSSLCFG=\"seclevel\",1,0", 2000, false);
sendAT("AT+QHTTPCFG=\"sslctxid\",1", 2000, false);
Serial1.println("✅ SSL configured");
}
inline String readHttpResponse() {
Serial1.println("Reading HTTP response body...");
while (EC200U.available()) {
EC200U.read();
}
EC200U.println("AT+QHTTPREAD=80");
char buffer[600];
int bufIndex = 0;
unsigned long start = millis();
bool gotConnect = false;
int bodyStart = -1;
while (millis() - start < 30000 && bufIndex < 599) {
if (EC200U.available()) {
char c = EC200U.read();
buffer[bufIndex++] = c;
Serial1.write(c);
if (!gotConnect && bufIndex >= 7) {
if (strncmp(&buffer[bufIndex-7], "CONNECT", 7) == 0) {
gotConnect = true;
}
}
}
if (bufIndex >= 12) {
buffer[bufIndex] = '\0';
if (strstr(buffer, "+QHTTPREAD: 0") != NULL) {
delay(100);
while (EC200U.available() && bufIndex < 599) {
buffer[bufIndex++] = EC200U.read();
}
break;
}
if (strstr(buffer, "ERROR") != NULL) {
Serial1.println("\n❌ Error reading HTTP response");
return "";
}
}
}
buffer[bufIndex] = '\0';
Serial1.println("\n--- Raw buffer ---");
Serial1.println(buffer);
Serial1.println("--- End raw ---");
String body = "";
char* connectPtr = strstr(buffer, "CONNECT");
if (connectPtr != NULL) {
char* bodyPtr = strchr(connectPtr, '\n');
if (bodyPtr != NULL) {
bodyPtr++;
char* endPtr = strstr(bodyPtr, "\r\nOK");
if (endPtr == NULL) endPtr = strstr(bodyPtr, "\nOK");
if (endPtr == NULL) endPtr = strstr(bodyPtr, "+QHTTPREAD");
if (endPtr != NULL) {
int len = endPtr - bodyPtr;
body.reserve(len + 1);
for (int i = 0; i < len; i++) {
if (bodyPtr[i] != '\r' && bodyPtr[i] != '\n') {
body += bodyPtr[i];
}
}
} else {
body = String(bodyPtr);
}
}
}
body.trim();
Serial1.print("\n--- Extracted Body (");
Serial1.print(body.length());
Serial1.print(" chars) ---\n[");
Serial1.print(body);
Serial1.println("]");
Serial1.println("--- End Body ---");
return body;
}
String extractNumberFromResponse(String response) {
String result = "";
for (int i = 0; i < response.length(); i++) {
char c = response.charAt(i);
if (c >= '0' && c <= '9') {
result += c;
}
}
return result;
}
inline bool downloadAMRFile(String url) {
Serial1.println("\n--- Downloading AMR File ---");
Serial1.print("URL: ");
Serial1.println(url);
// 1. بررسی اتصال
if (!sendAT("AT", 2000, true)) {
Serial1.println("❌ Modem not responding");
return false;
}
// 2. پاکسازی بافر
while (EC200U.available()) EC200U.read();
// 3. تنظیم URL (روش مستقیم)
Serial1.println("Setting URL...");
EC200U.println("AT+QHTTPURL");
String response = "";
unsigned long start = millis();
bool gotConnect = false;
// منتظر CONNECT
while (millis() - start < 5000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
if (response.indexOf("CONNECT") != -1) {
gotConnect = true;
break;
}
}
if (gotConnect) break;
}
if (!gotConnect) {
Serial1.println("❌ No CONNECT, trying alternative...");
// روش جایگزین: استفاده از طول URL
String cmd = "AT+QHTTPURL=" + String(url.length()) + ",30";
EC200U.println(cmd);
response = "";
start = millis();
while (millis() - start < 5000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
if (c == '\n') {
if (response.indexOf("CONNECT") != -1) {
gotConnect = true;
break;
}
}
}
if (gotConnect) break;
}
}
if (!gotConnect) {
Serial1.println("❌ Could not get CONNECT prompt");
return false;
}
// 4. ارسال URL
Serial1.println("Sending URL...");
EC200U.println(url);
// 5. منتظر OK
response = "";
start = millis();
bool urlAccepted = false;
while (millis() - start < 5000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
if (response.indexOf("OK") != -1) {
urlAccepted = true;
break;
}
if (response.indexOf("ERROR") != -1) {
Serial1.println("❌ URL rejected");
return false;
}
}
if (urlAccepted) break;
}
if (!urlAccepted) {
Serial1.println("❌ URL not accepted (timeout)");
return false;
}
Serial1.println("✅ URL set successfully");
delay(1000);
// 6. ارسال GET request
Serial1.println("Sending GET request...");
EC200U.println("AT+QHTTPGET");
response = "";
start = millis();
bool gotResponse = false;
while (millis() - start < 30000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
if (response.indexOf("+QHTTPGET:") != -1) {
gotResponse = true;
// بررسی کد وضعیت
int idx = response.indexOf("+QHTTPGET:");
String httpResponse = response.substring(idx);
Serial1.print("HTTP Response: ");
Serial1.println(httpResponse);
// استخراج کد HTTP
int comma1 = httpResponse.indexOf(',');
int comma2 = httpResponse.indexOf(',', comma1 + 1);
if (comma1 != -1 && comma2 != -1) {
int httpCode = httpResponse.substring(comma1 + 1, comma2).toInt();
Serial1.print("HTTP Code: ");
Serial1.println(httpCode);
if (httpCode != 200) {
Serial1.println("❌ HTTP error");
return false;
}
}
break;
}
}
if (gotResponse) break;
}
if (!gotResponse) {
Serial1.println("❌ GET request timeout");
return false;
}
Serial1.println("✅ GET successful");
delay(2000);
// 7. ذخیره فایل
Serial1.println("Saving to file...");
EC200U.println("AT+QHTTPREADFILE=\"UFS:output.amr\"");
response = "";
start = millis();
bool fileSaved = false;
while (millis() - start < 60000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
// نمایش پیشرفت
static int dots = 0;
if (c == '\n') {
Serial1.print(".");
dots++;
if (dots % 50 == 0) Serial1.println();
}
if (response.indexOf("+QHTTPREADFILE: 0") != -1) {
fileSaved = true;
break;
}
}
if (fileSaved) break;
}
if (fileSaved) {
Serial1.println("\n✅ File saved successfully");
// بررسی وجود فایل
Serial1.println("Verifying file...");
EC200U.println("AT+QFLST=\"UFS:output.amr\"");
response = "";
start = millis();
while (millis() - start < 3000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
if (response.indexOf("output.amr") != -1) break;
}
if (response.indexOf("output.amr") != -1) {
Serial1.println("✅ File verified");
return true;
} else {
Serial1.println("⚠️ File not found in listing");
return true; // باز هم true برگردان چون ذخیره شد
}
}
Serial1.println("\n❌ Failed to save file");
return false;
}
// ==================== تابع نهایی: تماس با DTMF Tones ====================
// // تابع اصلی که واقعاً باید کار کند
// inline bool makeVoiceCallWithAudio(String phoneNumber) {
// return false;
// }
// ==================== تابع اصلاح شده processServerResponse ====================
inline void processServerResponse(String response) {
if (response.length() == 0) {
Serial1.println("Empty response, no action needed");
return;
}
Serial1.println("\n======== PROCESSING SERVER RESPONSE ========");
Serial1.print("Response: ");
Serial1.println(response);
if (response.startsWith("tt")) {
Serial1.println("Response Type: TT (Send SMS)");
String data = response.substring(2);
int hashIdx = data.indexOf('#');
if (hashIdx != -1) {
String phoneNumber = data.substring(0, hashIdx);
String message = data.substring(hashIdx + 1);
phoneNumber.trim();
message.trim();
Serial1.print(" Phone: ");
Serial1.println(phoneNumber);
Serial1.print(" Message: ");
Serial1.println(message);
if (phoneNumber.length() >= 10 && message.length() > 0) {
if (sendSMS(phoneNumber, message)) {
Serial1.println("✅ SMS sent successfully");
lastMessage = "TT SMS Sent";
} else {
Serial1.println("❌ Failed to send SMS");
lastMessage = "TT SMS Fail";
}
} else {
Serial1.println("❌ Invalid phone or message");
lastMessage = "TT Invalid";
}
} else {
Serial1.println("❌ Invalid TT format (no #)");
lastMessage = "TT Format Err";
}
}
else if (response.startsWith("RST")) {
NVIC_SystemReset();
}
else if (response.startsWith("SHD")) {
HAL_PWR_EnterSTANDBYMode();
}
// else if (response.startsWith("TY")) {
// Serial1.println("Response Type: TY (Voice Call with Audio/DMTF)");
// String data = response.substring(2);
// int hashIdx = data.indexOf('#');
// if (hashIdx != -1) {
// String phoneNumber = data.substring(0, hashIdx);
// String audioUrl = data.substring(hashIdx + 1);
// phoneNumber.trim();
// audioUrl.trim();
// Serial1.print(" Phone: ");
// Serial1.println(phoneNumber);
// Serial1.print(" Audio URL: ");
// Serial1.println(audioUrl);
// if (phoneNumber.length() >= 10) {
// if (makeVoiceCallWithAudio(phoneNumber)) {
// Serial1.println("✅ Voice call with DTMF completed");
// lastMessage = "TY Call Done (DTMF)";
// } else {
// Serial1.println("❌ Voice call failed");
// lastMessage = "TY Call Fail";
// }
// } else {
// Serial1.println("❌ Invalid phone number");
// lastMessage = "TY Invalid";
// }
// } else {
// Serial1.println("❌ Invalid TY format (no #)");
// lastMessage = "TY Format Err";
// }
// }
else {
Serial1.println("Response Type: Numeric or unknown - No action needed");
}
Serial1.println("=============================================\n");
}
// -------------------- ارسال داده به سرور --------------------
inline void uploadData() {
Serial1.println("\n======== DATA UPLOAD ========");
if (!config.verified) {
Serial1.println("❌ Upload skipped: Device not verified");
Serial1.println("==============================\n");
return;
}
if (!networkConnected && config.verified) {
Serial1.println("⚠️ Not connected, trying to reconnect...");
connectToNetwork();
}
if (!networkConnected) {
Serial1.println("⚠️ Not connected, trying to reconnect...");
initEC200U();
if (!networkConnected) {
Serial1.println("❌ Upload skipped: No network connection");
Serial1.println("==============================\n");
return;
}
}
float coToSend = currentData.coPPM;
String data = "deviceId=" + String(config.deviceId) +
"&temperatureC=" + String(currentData.temperature, 1) +
"&humidityPercent=" + String(currentData.humidity, 1) +
"&gasPPM=" + String(coToSend, 0) +
"&lux=" + String(currentData.lightLux, 1) +
"&voltage=" + String(currentData.volage, 1) +
"&power=" + String(currentData.power) +
"&oldPower=" + String(currentData.oldPower) +
"&batteryPercent=" + String(currentData.batteryPercent, 1) +
"&batteryVoltage=" + String(currentData.batteryVoltage, 1);
data.replace(" ", "");
String url = String(config.serverUrl) + "/api/Telemetry/AddData?" + data;
//url = "https://ghback.nabaksoft.ir/My_StaticFiles/calltest.html";
Serial1.println("--- REQUEST INFO ---");
Serial1.print(" Server: ");
Serial1.println(config.serverUrl);
Serial1.print(" Device ID: ");
Serial1.println(config.deviceId);
Serial1.print(" Temp: ");
Serial1.print(currentData.temperature, 1);
Serial1.println(" C");
Serial1.print(" Hum: ");
Serial1.print(currentData.humidity, 1);
Serial1.println(" %");
Serial1.print(" CO (local): ");
Serial1.print(currentData.coPPM, 0);
Serial1.println(" ppm");
Serial1.print(" CO (to server): ");
Serial1.print(coToSend, 0);
Serial1.print(" ppm");
if (!MQ7sensorPreheated) {
Serial1.print(" [CALIBRATING]");
}
Serial1.println("--- FULL URL ---");
Serial1.println(url);
Serial1.print(" URL Length: ");
Serial1.println(url.length());
configureSSL();
String cmd = "AT+QHTTPURL=" + String(url.length()) + ",80";
EC200U.println(cmd);
String response = "";
unsigned long start = millis();
bool gotConnect = false;
while (millis() - start < 5000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
if (response.indexOf("CONNECT") != -1) {
gotConnect = true;
break;
}
if (response.indexOf("ERROR") != -1) {
Serial1.println("\n❌ Step 1 failed: QHTTPURL error");
lastMessage = "URL Err";
Serial1.println("==============================\n");
return;
}
}
if (!gotConnect) {
Serial1.println("❌ Step 1 failed: No CONNECT response");
lastMessage = "URL Err";
Serial1.println("==============================\n");
return;
}
Serial1.println("\n✅ Step 1: Got CONNECT, sending URL...");
EC200U.print(url);
delay(1000);
response = "";
start = millis();
while (millis() - start < 5000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
if (response.indexOf("OK") != -1) break;
}
if (response.indexOf("OK") == -1) {
Serial1.println("\n❌ Step 1 failed: URL not accepted");
lastMessage = "URL Err";
Serial1.println("==============================\n");
return;
}
Serial1.println("\n✅ Step 1: URL set successfully");
delay(500);
Serial1.println("Step 2: Sending HTTP GET (waiting up to 60 sec)...");
EC200U.println("AT+QHTTPGET=60");
response = "";
start = millis();
bool success = false;
bool gotResponse = false;
while (millis() - start < 65000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
if (response.indexOf("+QHTTPGET:") != -1) {
delay(1000);
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
gotResponse = true;
int idx = response.indexOf("+QHTTPGET:");
String httpResult = response.substring(idx);
Serial1.print("\nHTTP Result: ");
Serial1.println(httpResult);
if (httpResult.indexOf(" 0,200") != -1 || httpResult.indexOf(" 0,201") != -1 ||
httpResult.indexOf(":0,200") != -1 || httpResult.indexOf(":0,201") != -1) {
success = true;
} else if (httpResult.indexOf(",200,") != -1 || httpResult.indexOf(",201,") != -1) {
success = true;
}
break;
}
if (response.indexOf("ERROR") != -1) {
Serial1.println("\n❌ HTTP GET command error");
break;
}
}
if (success) {
lastUpload = millis();
lastMessage = "Uploaded";
Serial1.println("\n✅ Step 2: Data uploaded successfully!");
Serial1.println("--- UPLOAD SUCCESS ---");
Serial1.print(" Time: ");
Serial1.print(millis() / 1000);
Serial1.println(" sec since boot");
Serial1.println("----------------------");
delay(500);
String serverResponse = readHttpResponse();
if (serverResponse.length() > 0) {
processServerResponse(serverResponse);
}
} else {
lastMessage = "Upload Err";
if (gotResponse) {
Serial1.println("\n❌ Step 2: Server returned error");
} else {
Serial1.println("\n❌ Step 2: Timeout waiting for response");
}
Serial1.println("--- FULL RESPONSE ---");
Serial1.println(response);
Serial1.println("---------------------");
Serial1.println("Will retry on next interval...");
networkConnected = false;
}
Serial1.println("==============================\n");
}
#endif // EC200U_H