#ifndef EC200U_AUDIOCALL_H #define EC200U_AUDIOCALL_H #include // -------------------- تعریف USART3 -------------------- HardwareSerial EC200U(USART3); // -------------------- تنظیمات -------------------- const char* AUDIO_FILE_PATH = "UFS:output.amr"; String APN = "mcinet"; // اگر نیاز است تنظیم شود // -------------------- تابع ارسال AT -------------------- String sendATCommand(String cmd, uint16_t timeout = 5000, bool showCmd = false, bool showResponse = false) { if (showCmd) { Serial1.print(">> "); Serial1.println(cmd); } EC200U.println(cmd); String response = ""; unsigned long start = millis(); bool gotOk = false; bool gotError = false; while (millis() - start < timeout) { while (EC200U.available()) { char c = EC200U.read(); response += c; if (showResponse) Serial1.write(c); } if (response.indexOf("OK") != -1) gotOk = true; if (response.indexOf("ERROR") != -1) gotError = true; // برای دستورات خاص، منتظر نشانه‌های دیگر هم باشیم if (response.indexOf("CONNECT") != -1) break; if (response.indexOf("+QHTTPGET:") != -1) break; if (response.indexOf("+QHTTPREADFILE:") != -1) break; if (gotOk || gotError) break; } return response; } // -------------------- راه‌اندازی اینترنت -------------------- bool setupInternet() { Serial1.println("\n🌐 راه‌اندازی اتصال اینترنت"); Serial1.println("=========================="); // 1. تنظیم APN (اگر نیاز است) if (APN.length() > 0) { Serial1.print("[1] تنظیم APN... "); String cmd = "AT+QICSGP=1,1,\"" + APN + "\",\"\",\"\",1"; if (sendATCommand(cmd, 5000, false).indexOf("OK") == -1) { Serial1.println("FAIL"); return false; } Serial1.println("OK"); } // 2. فعال‌سازی زمینه PDP Serial1.print("[2] فعال‌سازی PDP... "); if (sendATCommand("AT+QIACT=1", 30000, false).indexOf("OK") == -1) { Serial1.println("FAIL - سعی می‌کنیم از حالت فعلی استفاده کنیم"); } else { Serial1.println("OK"); } // 3. بررسی وضعیت اتصال Serial1.print("[3] بررسی اتصال... "); String resp = sendATCommand("AT+QIACT?", 2000, false); if (resp.indexOf("+QIACT:") != -1) { Serial1.println("CONNECTED"); return true; } else { Serial1.println("NO CONNECTION"); return false; } } // -------------------- دانلود فایل صوتی از URL -------------------- // -------------------- دانلود فایل صوتی از URL -------------------- bool downloadAudioFile(String url) { Serial1.println("\n📥 دانلود فایل صوتی"); Serial1.println("==================="); // 1. پاک کردن فایل قدیمی اگر وجود دارد Serial1.print("[1] پاک کردن فایل قدیمی... "); sendATCommand("AT+QFDEL=\"UFS:audio.amr\"", 2000, false); Serial1.println("OK"); delay(100); // 2. تنظیم URL Serial1.print("[2] تنظیم URL... "); int urlLen = url.length(); String cmd = "AT+QHTTPURL=" + String(urlLen) + ",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; } if (response.indexOf("CONNECT") != -1) { gotConnect = true; break; } if (response.indexOf("ERROR") != -1) { Serial1.println("FAIL - خطای QHTTPURL"); return false; } } if (!gotConnect) { Serial1.println("FAIL - CONNECT دریافت نشد"); return false; } // ارسال URL 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("FAIL - URL پذیرفته نشد"); return false; } Serial1.println("OK"); // 3. دانلود فایل Serial1.print("[3] دانلود فایل... "); EC200U.println("AT+QHTTPGET=60"); // 60 ثانیه تایم‌اوت response = ""; start = millis(); bool httpSuccess = false; int httpCode = 0; 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(); httpCode = afterQhttp.substring(firstComma + 1, secondComma).toInt(); Serial1.print("کد خطا: "); Serial1.print(errorCode); Serial1.print(", کد HTTP: "); Serial1.print(httpCode); if (errorCode == 0 && httpCode >= 200 && httpCode < 300) { httpSuccess = true; } break; } } if (response.indexOf("ERROR") != -1) { Serial1.println("\n❌ HTTP GET ناموفق"); return false; } } if (!httpSuccess) { Serial1.println("FAIL"); Serial1.print(" کد HTTP: "); Serial1.println(httpCode); return false; } Serial1.println("OK"); delay(500); // پاک کردن بافر while (EC200U.available()) EC200U.read(); // 4. ذخیره فایل Serial1.print("[4] ذخیره فایل... "); EC200U.println("AT+QHTTPREADFILE=\"UFS:audio.amr\",80"); response = ""; start = millis(); bool saveSuccess = false; while (millis() - start < 60000) { while (EC200U.available()) { char c = EC200U.read(); response += c; Serial1.write(c); } if (response.indexOf("+QHTTPREADFILE: 0") != -1) { saveSuccess = true; break; } if (response.indexOf("ERROR") != -1) { break; } } if (saveSuccess) { Serial1.println("OK"); Serial1.println("✅ فایل صوتی دانلود و ذخیره شد"); return true; } else { Serial1.println("FAIL"); Serial1.println("❌ ذخیره فایل ناموفق"); return false; } } // -------------------- بررسی وضعیت تماس -------------------- int getCallState() { EC200U.println("AT+CLCC"); delay(300); String response = ""; unsigned long start = millis(); while (millis() - start < 2000) { while (EC200U.available()) { char c = EC200U.read(); response += c; } } if (response.indexOf("+CLCC: 0,0,0,0,0") != -1) return 0; // Active if (response.indexOf("+CLCC: 0,0,2,0,0") != -1) return 2; // Dialing if (response.indexOf("+CLCC: 0,0,3,0,0") != -1) return 3; // Ringing if (response.indexOf("NO CARRIER") != -1) return -2; // Disconnected if (response.indexOf("BUSY") != -1) return -3; // Busy return -1; // Unknown } // -------------------- تابع اصلی تماس و پخش -------------------- bool callAndPlayAudio(String phoneNumber) { Serial1.println("\n📞 تماس و پخش فایل صوتی"); Serial1.println("========================"); // 1. برقراری تماس Serial1.print("[1] برقراری تماس... "); String dialCmd = "ATD" + phoneNumber + ";"; String resp = sendATCommand(dialCmd, 10000, false, true); if (resp.indexOf("OK") == -1 && resp.indexOf("ERROR") != -1) { Serial1.println("FAIL"); return false; } Serial1.println("OK"); // 2. منتظر پاسخ Serial1.print("[2] منتظر پاسخ تماس... "); unsigned long start = millis(); bool callConnected = false; while (millis() - start < 45000) { // 45 ثانیه منتظر بمان int callState = getCallState(); switch (callState) { case 0: // Active callConnected = true; Serial1.println("CONNECTED"); break; case 2: // Dialing Serial1.print("."); break; case 3: // Ringing Serial1.print("R"); break; case -2: // Disconnected Serial1.println("DISCONNECTED"); return false; case -3: // Busy Serial1.println("BUSY"); return false; } if (callConnected) break; delay(2000); } if (!callConnected) { Serial1.println("NO ANSWER"); sendATCommand("ATH", 2000, false); return false; } delay(1000); // کمی صبر بعد از اتصال // 3. پخش فایل صوتی Serial1.print("[3] شروع پخش صدا... "); // ابتدا حالت پخش را تنظیم کن resp = sendATCommand("AT+QVTCMD=1,0,\"UFS:output.amr\"", 5000, false, true); if (resp.indexOf("OK") == -1) { Serial1.println("FAIL - تنظیم پخش"); Serial1.println(" پاسخ: " + resp); sendATCommand("ATH", 2000, false); return false; } // شروع پخش resp = sendATCommand("AT+QVTCMD=3,0", 3000, false, true); if (resp.indexOf("OK") == -1) { Serial1.println("FAIL - شروع پخش"); sendATCommand("ATH", 2000, false); return false; } Serial1.println("OK"); // 4. منتظر اتمام پخش Serial1.println("[4] در حال پخش... "); bool playbackComplete = false; start = millis(); while (millis() - start < 120000) { // حداکثر 2 دقیقه // بررسی وضعیت پخش EC200U.println("AT+QVTSTAT?"); delay(500); String statusResp = ""; unsigned long statusStart = millis(); while (millis() - statusStart < 2000) { while (EC200U.available()) { char c = EC200U.read(); statusResp += c; } } // اگر پخش تمام شده if (statusResp.indexOf("+QVTSTAT: 0,0") != -1) { playbackComplete = true; break; } // بررسی وضعیت تماس if (getCallState() != 0) { Serial1.println(" تماس قطع شد"); break; } Serial1.print("."); delay(1000); } if (playbackComplete) { Serial1.println(" COMPLETE"); } else { Serial1.println(" INCOMPLETE"); } // 5. قطع تماس Serial1.print("[5] پایان تماس... "); resp = sendATCommand("ATH", 3000, false, true); if (resp.indexOf("OK") != -1) { Serial1.println("OK"); Serial1.println("✅ عملیات کامل شد"); return true; } else { Serial1.println("FAIL"); return false; } } // -------------------- تابع اصلی یکپارچه -------------------- bool downloadAndCall(String phoneNumber, String audioUrl) { Serial1.println("\n🎯 شروع عملیات کامل"); Serial1.println("===================="); Serial1.println("📞 شماره: " + phoneNumber); Serial1.println("🔗 URL: " + audioUrl); // 1. راه‌اندازی اینترنت if (!setupInternet()) { Serial1.println("❌ اتصال اینترنت ناموفق"); return false; } // 2. دانلود فایل صوتی if (!downloadAudioFile(audioUrl)) { Serial1.println("❌ دانلود فایل ناموفق"); return false; } delay(2000); // 3. تماس و پخش return callAndPlayAudio(phoneNumber); } // -------------------- تابع تست سریع -------------------- void testAudioCall() { Serial1.println("\n🧪 تست سریع عملیات تماس صوتی"); Serial1.println("=============================="); // اطلاعات تست (تغییر دهید) String testPhone = "09192530212"; String testUrl = "http://ghback.nabaksoft.ir/My_staticFiles/output.amr"; // URL فایل صوتی AMR Serial1.println("⚠️ توجه: لطفاً اطلاعات زیر را تنظیم کنید:"); Serial1.println(" 1. شماره تلفن: " + testPhone); Serial1.println(" 2. URL فایل صوتی: " + testUrl); Serial1.println(" 3. APN (اگر نیاز است) در کد تنظیم شود"); // در اینجا می‌توانید تست را فعال کنید // bool result = downloadAndCall(testPhone, testUrl); Serial1.println("\n📋 دستورات تست دستی:"); Serial1.println(" 1. initModule() - راه‌اندازی ماژول"); Serial1.println(" 2. setupInternet() - اتصال اینترنت"); Serial1.println(" 3. downloadAudioFile(\"URL\") - دانلود فایل"); Serial1.println(" 4. callAndPlayAudio(\"PHONE\") - تماس و پخش"); } // -------------------- راه‌اندازی اولیه ماژول -------------------- void initModule() { Serial1.begin(115200); EC200U.begin(115200); delay(3000); Serial1.println("\n🔧 راه‌اندازی ماژول EC200U"); Serial1.println("=========================="); // تست AT Serial1.print("AT... "); if (sendATCommand("AT", 2000, false).indexOf("OK") != -1) { Serial1.println("OK"); } else { Serial1.println("FAIL"); return; } // غیرفعال کردن اکو sendATCommand("ATE0", 1000, false); // تنظیمات صدا sendATCommand("AT+CLVL=5", 1000, false); // سطح صدا sendATCommand("AT+CMUT=0", 1000, false); // غیرفعال کردن mute Serial1.println("✅ ماژول آماده است"); } #endif // EC200U_AUDIOCALL_H