در این مقاله قراره دست به کد بشیم و فرض رو بر این میذاریم که دو مقالهی قبلی که شامل فعال سازی VoLTE در ماژول Quectel EC25-EUX رو خوندید و UAC و VoLTE رو فعال کردید.
در این مقاله قراره اول یک اسکریپت سادهی پایتونی داشته باشیم که ماژول رو مدیریت کنه، شماره تماسها و پیامکهای دریافتی رو با کمک ORM داخل دیتابیس SQLite ذخیره کنه و در نهایت هم مسیر صوتی بین ماژول و سیستم رو برقرار کنیم تا بتونیم واقعاً با ماژول صحبت کنیم.
جالب شد، نه؟ 🙂
البته این تازه اول کاره و قراره جلوتر کارهای جالبتری هم انجام بدیم. این آموزش رو روی لینوکس جلو میبرم، ولی این به این معنی نیست که فقط روی لینوکس کار میکنه. با چند تغییر جزئی میتونید همین کد رو روی سیستمعامل خودتون، از جمله ویندوز و مک، هم اجرا کنید.
برای شروع به Python 3.10 یا بالاتر نیاز داریم.
و یک نکتهی مهم: سادهترین راه برای حل مشکلات احتمالی هم استفاده از هوش مصنوعیه! 🙂
در قدم اول، ریپازیتوری این آموزش رو با دستور زیر از GitHub کلون کنید:
git clone https://github.com/mthri/sisoog-ec25.git
cd sisoog-ec25/01-call-and-sms
حالا یک محیط مجازی پایتون میسازیم:
python3 -m venv .venv
و با دستور زیر فعالش میکنیم:
source .venv/bin/activate
بعد کتابخانههای موردنیاز رو نصب میکنیم:
pip install pyserial sounddevice numpy peewee
اگر به هر دلیلی نتونستید این کتابخانهها رو از مخازن رسمی PyPI نصب کنید، میتونید از Mirrorهای زیر استفاده کنید:
کتابخانهی اول، یعنی PySerial، برای مدیریت ارتباط سریال استفاده میشه. SoundDevice و NumPy برای بخش صوتی پروژه به کار میرن و Peewee هم ORM مورد استفاده برای ذخیرهسازی اطلاعات داخل دیتابیس SQLite هست.
حالا بیاید ببینیم لینوکس ماژول رو چطور شناسایی کرده.
وقتی دستور زیر رو اجرا میکنم:
ls /dev/ttyUSB*
این خروجی رو میبینم:
توی مقالهی اول توضیح دادیم که هر کدوم از این پورتها چه کاربردی دارن. در حال حاضر با ttyUSB2 کار داریم که همون پورتیه که برای ارسال AT Command ها استفاده میشه.
برای اینکه مطمئن بشیم پورت درست رو انتخاب کردیم، این دستور رو اجرا میکنیم:
udevadm info -q property -n /dev/ttyUSB2 | grep ID_USB_INTERFACE_NUM
و خروجی زیر رو میبینیم:
ID_USB_INTERFACE_NUM=02
حالا که پورت مورد نظر رو پیدا کردیم، بهتره کاری کنیم برای دسترسی به پورتهای سریال هر بار مجبور نباشیم از sudo استفاده کنیم.
کاربر فعلی رو به گروه dialout اضافه میکنیم:
sudo usermod -aG dialout $USER
و برای اعمال این تغییر در همین نشست:
newgrp dialout
حالا بریم سراغ بخش صوتی. برای اینکه مطمئن بشیم اینترفیس صوتی ماژول توسط هستهی لینوکس شناسایی شده، دستور زیر رو اجرا میکنیم:
aplay -l | grep EC25EUX
که برای من خروجی زیر رو برمیگردونه:
card 2: EC25EUX [EC25-EUX], device 0: USB Audio [USB Audio]
این یعنی خروجی صدای ما، یعنی Playback، با موفقیت توسط سیستم شناسایی شده. برای بررسی ورودی صدا یا Capture هم:
arecord -l | grep EC25EUX
و خروجی:
card 2: EC25EUX [EC25-EUX], device 0: USB Audio [USB Audio]
این هم یعنی ورودی صدای ماژول با موفقیت شناسایی شده. در این نقطه، از نظر سختافزاری و نرمافزاری تقریباً همهچیز آماده است و میتونیم وارد مرحلهی کدنویسی بشیم. توی هر دو نسخهی برنامه، به محض اجرا شدن، یک خلاصه از وضعیت فعلی ماژول نمایش داده میشه؛ مثلاً به چه شبکهای رجیستر شده، نوع شبکه چیه و قدرت آنتن در چه وضعیتی قرار داره.
در نسخهی دوم علاوه بر این موارد، وضعیت Audio Bridge هم نمایش داده میشه؛ یعنی اینکه آیا تونستیم مسیر صوتی بین ماژول و سیستم رو با موفقیت برقرار کنیم یا نه، که جلوتر دقیقاً بهش میرسیم. یک ثابت هم داریم به اسم PORT که باید آدرس پورت AT ماژول روی سیستم رو داخلش قرار بدیم. همونطور که بالاتر دیدید، برای من این پورت ttyUSB2 هست.
در نسخهی اول که اسم فایلش main_v1.py هست، برنامه فعلاً کاری با میکروفون و اسپیکر نداره. ممکنه مثلاً سیستم شما اصلاً ورودی یا خروجی صوتی نداشته باشه، بنابراین در این نسخه فقط میتونید پیامک ارسال و دریافت کنید و تماس برقرار یا دریافت کنید. البته وقتی تماس رو پاسخ میدید، صدای تماس از سیستم پخش نمیشه و صدای میکروفون سیستم هم به ماژول منتقل نمیشه.
در نسخهی دوم که فایلش main_v2.py هست، در واقع یک Audio Bridge ایجاد میکنیم.
یعنی چی؟ یعنی صدای ورودی ماژول رو از طریق سیستم دریافت میکنیم و به خروجی صدای سیستم میفرستیم. از طرف دیگه، صدای میکروفون سیستم رو هم دریافت میکنیم و به ورودی صوتی ماژول میفرستیم.
در نتیجه، مسیر صدا به این شکل میشه:
ماژول → اسپیکر سیستم
میکروفون سیستم → ماژول
این کد بهصورت خودکار ورودی و خروجی صوتی مناسب رو پیدا میکنه و Bridge صوتی بین ماژول و سیستم ایجاد میکنه.
علاوه بر این دو فایل، یک فایل سوم به اسم models.py هم داریم. این فایل در واقع ساختار دادههایی رو مشخص میکنه که قراره داخل دیتابیس ذخیره کنیم؛ مثلاً اطلاعات تماسها و پیامکها.
برای این کار از Peewee بهعنوان ORM استفاده کردیم و دیتابیس پیشفرض پروژه هم SQLite هست. اگر بخواید از دیتابیس دیگهای مثل MySQL یا PostgreSQL استفاده کنید، ساختار ORM تا حد زیادی بدون تغییر باقی میمونه و میتونید Database Backend رو تغییر بدید.
خب، این قسمت هم اینجا به پایان میرسه. مقالهی بعدی کاملاً نرمافزاریه و دیگه کاری به خود ماژول نداریم. قراره بهصورت محلی مدلهای مختلف STT، TTS و LLM رو اجرا و تست کنیم و در نهایت یک Pipeline ساده بسازیم.
فکر کنم کمکم متوجه شدید که قراره در نهایت چه اتفاقی بیفته، نه؟ 🙂 با من همراه باشید.
این داستان ادامه داره…
سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.