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

1613 lines
45 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
// -------------------- توابع پایه EC200U --------------------
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;
}
// جدول تبدیل کاراکترهای فارسی به UCS2 (بهینه شده)
inline String convertFarsiToUCS2(String text) {
String ucs2 = "";
for (int i = 0; i < text.length(); i++) {
unsigned char c = text.charAt(i);
// تشخیص کاراکترهای فارسی UTF-8 (دو بایتی)
if (c >= 0xD8 && c <= 0xDF && i + 1 < text.length()) {
unsigned char c2 = text.charAt(i + 1);
// محاسبه کد Unicode از UTF-8
uint16_t unicode = ((c - 0xD8) << 6) + (c2 - 0x80) + 0x0600;
// تبدیل به HEX
char hex[5];
sprintf(hex, "%04X", unicode);
ucs2 += hex;
i++; // یک کاراکتر اضافه مصرف شد
}
// کاراکترهای ASCII
else if (c < 0x80) {
char hex[5];
sprintf(hex, "%04X", c);
ucs2 += hex;
}
// سایر کاراکترها
else {
char hex[5];
sprintf(hex, "%04X", c);
ucs2 += hex;
}
}
return ucs2;
}
// تبدیل شماره به UCS2 (اعداد)
inline String convertNumberToUCS2(String number) {
String ucs2 = "";
for (int i = 0; i < number.length(); i++) {
char c = number.charAt(i);
if (c == '+') {
ucs2 += "002B";
} else if (c >= '0' && c <= '9') {
char hex[5];
sprintf(hex, "%04X", c);
ucs2 += hex;
}
}
return ucs2;
}
// تابع اصلی ارسال SMS فارسی
// تابع اصلاح شده برای ارسال SMS فارسی
inline bool sendSMS(String numbers, String messages) {
Serial1.println("\n📱 SENDING SMS - PDU MODE");
// تقسیم شماره‌ها
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;
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();
// --- روش ۱: ابتدا با GSM معمولی امتحان کن ---
sendAT("AT+CMGF=1", 2000, false); // Text mode
sendAT("AT+CSCS=\"GSM\"", 2000, false);
sendAT("AT+CSMP=17,167,0,0", 2000, false);
EC200U.print("AT+CMGS=\"");
EC200U.print(phone);
EC200U.println("\"");
delay(100);
String response = "";
unsigned long start = millis();
bool gotPrompt = false;
while (millis() - start < 5000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
if (response.indexOf(">") != -1) {
gotPrompt = true;
break;
}
}
if (gotPrompt) break;
}
if (!gotPrompt) {
Serial1.println("❌ No prompt");
allSent = false;
continue;
}
// ارسال پیام
EC200U.print(message);
EC200U.write(26);
response = "";
start = millis();
bool gotResponse = false;
bool hasError = false;
while (millis() - start < 10000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
if (response.indexOf("+CMGS:") != -1) {
gotResponse = true;
totalMessagesSent++;
break;
}
if (response.indexOf("ERROR") != -1 || response.indexOf("CMS ERROR") != -1) {
hasError = true;
break;
}
}
if (gotResponse || hasError) break;
}
if (gotResponse) {
Serial1.println("✅ Sent with GSM encoding");
continue; // موفق بود، برو به شماره بعدی
}
if (hasError) {
Serial1.println("⚠️ GSM failed, trying 8-bit encoding...");
// --- روش ۲: 8-bit encoding ---
sendAT("AT+CMGF=1", 2000, false);
sendAT("AT+CSMP=17,167,0,8", 2000, false); // 8-bit data coding
EC200U.print("AT+CMGS=\"");
EC200U.print(phone);
EC200U.println("\"");
delay(100);
response = "";
start = millis();
gotPrompt = false;
while (millis() - start < 5000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
if (response.indexOf(">") != -1) {
gotPrompt = true;
break;
}
}
if (gotPrompt) break;
}
if (!gotPrompt) {
Serial1.println("❌ No prompt for 8-bit");
allSent = false;
continue;
}
EC200U.print(message);
EC200U.write(26);
response = "";
start = millis();
gotResponse = false;
while (millis() - start < 10000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
if (response.indexOf("+CMGS:") != -1) {
gotResponse = true;
totalMessagesSent++;
break;
}
if (response.indexOf("ERROR") != -1) {
break;
}
}
if (gotResponse) break;
}
if (gotResponse) {
Serial1.println("✅ Sent with 8-bit encoding");
} else {
Serial1.println("❌ 8-bit also failed");
allSent = false;
}
}
// تاخیر بین ارسال‌ها
if (i < phoneCount - 1) {
delay(3000);
}
}
Serial1.print("📊 Result: ");
Serial1.print(totalMessagesSent);
Serial1.print("/");
Serial1.print(phoneCount);
Serial1.println(" messages sent");
// بازگشت به تنظیمات عادی
sendAT("AT+CSMP=17,167,0,0", 2000, false);
return (totalMessagesSent > 0);
}
// -------------------- پردازش 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(); // به جای initEC200U() از این تابع استفاده شود
} 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() {
// حذف شرط config.verified - همیشه اجرا شود
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("Modem not responding, powering on...");
Serial1.println(" PWRKEY -> HIGH (MOSFET ON, PWRKEY to GND)");
digitalWrite(PWRKEY_PIN, HIGH);
delay(1500);
Serial1.println(" PWRKEY -> LOW (MOSFET OFF, PWRKEY floating)");
digitalWrite(PWRKEY_PIN, LOW);
*/
Serial1.println("Waiting for modem to boot (8s)...");
delay(8000);
if (!sendAT("AT", 5000, false)) {
Serial1.println("⚠️ First attempt failed, trying again with longer pulse...");
digitalWrite(PWRKEY_PIN, HIGH);
delay(2000);
digitalWrite(PWRKEY_PIN, LOW);
delay(10000);
if (!sendAT("AT", 5000, false)) {
Serial1.println("❌ Modem not responding after power on!");
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 جدید
// فقط اگر 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;
}
// -------------------- توابع دانلود و تماس صوتی --------------------
inline bool downloadAMRFile(String url) {
Serial1.println("\n--- Downloading AMR File ---");
Serial1.print("URL (");
Serial1.print(url.length());
Serial1.print(" chars): [");
Serial1.print(url);
Serial1.println("]");
if (url.length() < 10 || !url.startsWith("http")) {
Serial1.println("❌ Invalid URL!");
return false;
}
sendAT("AT+QFDEL=\"UFS:audio.amr\"", 2000, false);
delay(100);
int urlLen = url.length();
//Serial1.print("Setting URL with length: ");
//Serial1.println(urlLen);
String cmd = "AT+QHTTPURL=" + String(urlLen) + ",80";
//Serial1.print("Command: ");
//Serial1.println(cmd);
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;
}
if (response.indexOf("CONNECT") != -1) {
gotConnect = true;
break;
}
if (response.indexOf("ERROR") != -1) {
Serial1.println("❌ QHTTPURL error");
return false;
}
}
if (!gotConnect) {
Serial1.println("❌ No CONNECT for URL");
return false;
}
EC200U.print(url);
delay(1000);
response = "";
start = millis();
while (millis() - start < 3000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
}
if (response.indexOf("OK") != -1) break;
}
if (response.indexOf("OK") == -1) {
Serial1.println("❌ URL not accepted");
return false;
}
Serial1.println("✅ URL set successfully");
delay(200);
//Serial1.println("Step 1: Sending HTTP GET request...");
EC200U.println("AT+QHTTPGET=60");
response = "";
start = millis();
bool httpSuccess = false;
while (millis() - start < 65000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
int qhttpIdx = response.indexOf("+QHTTPGET:");
if (qhttpIdx != -1) {
String afterQhttp = response.substring(qhttpIdx);
int firstComma = afterQhttp.indexOf(',');
int secondComma = afterQhttp.indexOf(',', firstComma + 1);
if (firstComma != -1 && secondComma != -1) {
int errorCode = afterQhttp.substring(11, firstComma).toInt();
int httpCode = afterQhttp.substring(firstComma + 1, secondComma).toInt();
Serial1.print("\n Error code: ");
Serial1.print(errorCode);
Serial1.print(", HTTP code: ");
Serial1.println(httpCode);
if (errorCode == 0 && httpCode >= 200 && httpCode < 300) {
httpSuccess = true;
}
break;
}
}
if (response.indexOf("ERROR") != -1) {
Serial1.println("\n❌ HTTP GET failed");
return false;
}
}
if (!httpSuccess) {
Serial1.println("\n❌ HTTP GET timeout or failed");
return false;
}
Serial1.println("✅ HTTP GET successful");
delay(500);
while (EC200U.available()) EC200U.read();
Serial1.println("Step 2: Saving response to file...");
EC200U.println("AT+QHTTPREADFILE=\"UFS:audio.amr\",80");
response = "";
start = millis();
bool success = false;
while (millis() - start < 60000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
if (response.indexOf("+QHTTPREADFILE: 0") != -1) {
success = true;
break;
}
if (response.indexOf("ERROR") != -1) {
break;
}
}
if (success) {
Serial1.println("\n✅ AMR file downloaded to RAM");
return true;
} else {
Serial1.println("\n❌ Failed to save AMR file");
return false;
}
}
inline int getCallState(String clccResponse) {
int clccIdx = clccResponse.indexOf("+CLCC:");
if (clccIdx == -1) return -1;
String afterClcc = clccResponse.substring(clccIdx + 7);
int firstComma = afterClcc.indexOf(',');
if (firstComma == -1) return -1;
int secondComma = afterClcc.indexOf(',', firstComma + 1);
if (secondComma == -1) return -1;
int thirdComma = afterClcc.indexOf(',', secondComma + 1);
if (thirdComma == -1) return -1;
String statStr = afterClcc.substring(secondComma + 1, thirdComma);
statStr.trim();
return statStr.toInt();
}
inline bool makeVoiceCallWithAudio(String phoneNumber) {
isInCall = true;
Serial1.println("\n--- Making Voice Call ---");
Serial1.print("Phone: ");
Serial1.println(phoneNumber);
delay(1000);
String dialCmd = "ATD" + phoneNumber + ";";
EC200U.println(dialCmd);
String response = "";
unsigned long start = millis();
bool callAnswered = false;
while (millis() - start < 10000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
if (response.indexOf("OK") != -1) break;
if (response.indexOf("ERROR") != -1 ||
response.indexOf("NO CARRIER") != -1 ||
response.indexOf("BUSY") != -1) {
Serial1.println("❌ Call initiation failed");
isInCall = false;
return false;
}
}
Serial1.println("📞 Call initiated, waiting for answer...");
start = millis();
while (millis() - start < 60000) {
while (EC200U.available()) {
char c = EC200U.read();
Serial1.write(c);
}
EC200U.println("AT+CLCC");
delay(500);
String clccResp = "";
unsigned long clccStart = millis();
while (millis() - clccStart < 2000) {
while (EC200U.available()) {
char c = EC200U.read();
clccResp += c;
Serial1.write(c);
}
if (clccResp.indexOf("OK") != -1) break;
}
int callState = getCallState(clccResp);
Serial1.print(" Call state: ");
Serial1.println(callState);
if (callState == 0) {
callAnswered = true;
Serial1.println("✅ Call answered!");
break;
} else if (callState == 2) {
Serial1.println(" ⏳ Dialing...");
} else if (callState == 3) {
Serial1.println(" 🔔 Ringing...");
} else if (callState == -1) {
if (clccResp.indexOf("NO CARRIER") != -1 ||
clccResp.indexOf("+CLCC:") == -1) {
Serial1.println("❌ Call ended or no answer");
break;
}
}
delay(2000);
}
if (!callAnswered) {
Serial1.println("❌ Call not answered");
sendAT("ATH", 2000, false);
isInCall = false;
return false;
}
Serial1.println("✅ Call connected, playing audio...");
// بارگذاری فایل صوتی در RAM
sendAT("AT+QPSND=0", 1000, false); // تنظیم حالت پخش
sendAT("AT+QHTTPREADFILE=\"UFS:audio.amr\"", 1000, false);
// پخش فایل صوتی
sendAT("AT+QPSND=1,\"UFS:audio.amr\"", 1000, false);
response = "";
start = millis();
bool playStarted = false;
while (millis() - start < 5000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
if (response.indexOf("OK") != -1) {
playStarted = true;
break;
}
if (response.indexOf("ERROR") != -1) {
Serial1.println("❌ Failed to play audio");
break;
}
}
if (playStarted) {
Serial1.println("✅ Audio playing...");
bool playEnded = false;
start = millis();
while (millis() - start < 120000) {
while (EC200U.available()) {
char c = EC200U.read();
response += c;
Serial1.write(c);
}
if (response.indexOf("+QPSND: 0") != -1 ||
response.indexOf("QPSND: END") != -1) {
playEnded = true;
break;
}
if (response.indexOf("NO CARRIER") != -1) {
Serial1.println("Call ended by other party");
break;
}
delay(500);
}
if (playEnded) {
Serial1.println("✅ Audio playback completed");
}
}
delay(500);
Serial1.println("Hanging up...");
sendAT("ATH", 3000, true);
delay(2000);
Serial1.println("✅ Call ended");
isInCall = false;
return true;
}
inline void deleteAMRFile() {
Serial1.println("Deleting AMR file from RAM...");
sendAT("AT+QFDEL=\"UFS:audio.amr\"", 2000, false);
Serial1.println("✅ File deleted");
}
// -------------------- پردازش پاسخ سرور --------------------
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)");
String data = response.substring(2);
Serial1.print("Data after TY removal (");
Serial1.print(data.length());
Serial1.print(" chars): ");
Serial1.println(data);
int hashIdx = data.indexOf('#');
Serial1.print("Hash index: ");
Serial1.println(hashIdx);
if (hashIdx != -1) {
String phoneNumber = data.substring(0, hashIdx);
String audioUrl = data.substring(hashIdx + 1);
phoneNumber.trim();
audioUrl.trim();
Serial1.print("Phone length: ");
Serial1.println(phoneNumber.length());
Serial1.print("URL length: ");
Serial1.println(audioUrl.length());
Serial1.print(" Phone: ");
Serial1.println(phoneNumber);
Serial1.print(" Audio URL: ");
Serial1.println(audioUrl);
if (phoneNumber.length() >= 10 && audioUrl.length() > 0) {
if (downloadAMRFile(audioUrl)) {
if (makeVoiceCallWithAudio(phoneNumber)) {
Serial1.println("✅ Voice call completed");
lastMessage = "TY Call Done";
} else {
Serial1.println("❌ Voice call failed");
lastMessage = "TY Call Fail";
}
deleteAMRFile();
} else {
Serial1.println("❌ Failed to download audio");
lastMessage = "TY DL Fail";
}
} else {
Serial1.println("❌ Invalid phone or URL");
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(7) +
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://farsnews.ir/4512.2232f38.js';
//for test call
//url="http://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 (!calibrationComplete) {
Serial1.print(" [CALIBRATING]");
}
// Serial1.println();
// Serial1.print(" Light: ");
// Serial1.print(currentData.lightLux, 1);
// Serial1.println(" lux");
Serial1.println("--- FULL URL ---");
Serial1.println(url);
Serial1.print(" URL Length: ");
Serial1.println(url.length());
//Serial1.println("--------------------");
configureSSL();
//Serial1.println("Step 1: Setting URL...");
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