چگونه به کمک بلوتوث (BLE) با MQTT Broker ارتباط بگیریم

0
135
چگونه به کمک بلوتوث (BLE) با MQTT Broker ارتباط بگیریم

یک پروژه داریم انجام میدیم که اجازه ندارم جزئیاتشو بگم، اما به صورت کلی بخوام یک تصویری به شما بدم اینجوره که:

یک دستگاه داریم که قراره چیزی رو برای ما تولید کنه، و این دستگاه یک رابط کاربری لمسی داره روی خودش.

این رابط کاربری به جز اینکه روی دستگاه باشه، میتونه روی گوشی موبایل هم باشه و از طریق Wi-Fi، Bluetooth و یا هر راه ارتباطی دیگه هم متصل بشه.

داخل دستگاه 2 تا ماژول داریم، یک ماژولی که کارش تولیده و یک ماژول که کارش ارتباط با ماژول تولیده و اسمشو گذاشتیم Brain.

Production Module <—–(UART)—–> Brain Module <—–> UI

ماژول Brain از طریق سریال با ماژول تولید ارتباط داره و خودش روی لینوکس اجرا میشه، از Flutter برای نوشتن Brain و UI استفاده شده است.

 

چرا پروتکل MQTT؟

چرا پروتکل MQTT؟

برای اینکه راه‌های ارتباطی مختلفی برای Brain و UI قراره تعریف بشه، نیاز به یک پروتکل مناسب برای ارسال و دریافت پیام داشتیم که MQTT رو انتخاب کردیم.

خوب ما به یک MQTT Broker هم نیاز داشتیم که از Mosquitto استفاده کردیم و روی ماژول Brain سوار میشه.

در واقع در حال حاضر Brain و UI با استفاده از MQTT بر TCP/IP Stack با هم ارتباط دارند.

Brain Module <—–(MQTT)—–> Mosquitto <—–(MQTT)—–> UI

خوب علاوه بر UI یک اپلیکیشن دیگه هم داریم به اسم Composer که کارش اینه که کاربر متخصص فرمول تولید رو به دستگاه میده تا ذخیره کنه و مشتری استفاده کنه.

خوب تا اینجا همه چیز خوب پیش رفت، برای ارتباط سریال از flutter_libserialport استفاده کردیم و برای ارتباط MQTT با استفاده از کابل Ethernet یا Wi-Fi از mqtt_client استفاده کردیم.

 

قسمت اپلیکیشن

قسمت اپلیکیشن

 

به ما گفته شد که مشتری نهایی باید بتونه با NFC و Bluetooth با دستگاه ارتباط بگیره و با اپلیکیشن کار کنه و چیزی که میخواد رو سفارش بده…!

چندتا روش به ذهنم رسید که بیشترش به درد نخور بودن و موند 2 تا روش:

  • ایجاد یک Personal Area Network / PAN با استفاده از Bluetooth و کار کردن با TCP/IP
  • ارسال و دریافت پیام های MQTT بر روی BLE به سمت یک Gateway که این دروازه باید با Mosquitto به ازای هر مشتری، پیام ها رو پراکسی بکنه

مشکل روش اول این بود که اولا خیلی از گوشی های اندروید از این قابلیت بلوتوث پشتیبانی نمیکنند، این موضوع برای دستگاه های اپلی هم صادقه، دوما تاکید شد که باید از Bluetooth Low Energy استفاده کنیم و اصلا همچین چیزی برای BLE وجود نداشت.

 

نتیجتا رفتیم سراغ روش دوم…!

یکی از ترس های ما پهنای باند انتقال اطلاعات بود و هست.

روی BLE (Bluetooth Low Energy) خیلی دستمون بستس، به صورت پیشفرض فقط میشه 23 بایت داخل payload گذاشت که فقط 20 بایتش قابل استفاده برای خودمونه.

UI و Gateway زمان اتصال تلاش می کنند پهنای باند یا واحد بشینیه انتقال (MTU) بیشتری درخواست کنند، اما روی دستگاه های اندرویدی تا 512 بایت و روی دستگاه های اپلی تا 185 بایت بیشتر قابل درخواست نیست.

 

حذف دغدغه کار با پروتکل

موضوع بعدی اینه که من میخواستم این ارتباط سمت فلاتر Transparent باشه، یعنی برنامه نویس مستقیما با MQTT کار کنه و دغدغه ای در رابطه با پروتکل ارتباطی نداشته باشه.

برای همین mqtt_client رو توسعه دادم تا در کنار TCP از BLE هم پشتیبانی بکنه.

برای تست نیاز داشتم که یک GATT Server ایجاد بکنم، از لپتاپتم که بلوتوث داره استفاده کردم.

این GATT مشخص کننده نحوه ارتباطی بین دو تا دستگاه بلوتوثیه، GATT Server نقش یک Peripheral یا یک دستگاه جانبی رو داره که در این سناریو UI قراره بهش متصل بشه و نقش Central رو داره.

این Central وظیفش اینه که Scan کنه و Peripheral مناسب رو پیدا بکنه و بهش متصل بشه و ادامه ماجرا.

GATT Server Advertises its Presence
Central Scans to find the Peripheral
Central Connects to the GATT Server(Peripheral)

من اول بار Peripheral رو با Python ساختم. از کتابخانه python-bluezero استفاده کردم و کار باهاش خیلی راحت بود.

حالا باید یجوری به GATT Server میفهموندم که باید متصل بشی به Mosquitto و پیام های دریافتی و ارسالی رو Proxy بکنی.

هر دستگاه BLE میتونه چندین Service داشته باشه و هر سرویس میتونه چندتا Characteristic داشته باشه و هر مشخصه میتونه چندین Descriptor داشته باشه.

در واقع ارسال و دریافت اطلاعات باید از طریق Characteristic های یک سرویس انجام بشه.

من از پروتکل Nordic UART Service استفاده کردم، نمونه مثالش داخل پوشه examples کتابخانه python-bluezero موجوده.

خوب 2 تا مشخصه داریم یکی TX و یکی RX – از روی RX اطلاعاتو از UI دریافت میکنیم و روی TX اطلاعاتو مینویسیم.

بعد از اتصال UI باید یک درخواست Notify با مقدار true روی TX بفرسته تا اینجوری سرور بفهمه باید متصل بشه به بروکر و الباقی ماجرا از حوصله این مقاله خارجه.

 

تست عملی!

من اولین تست رو با گوشی موبایل اندرویدی زدم، Xiaomi POCO X3، خوب تستای اولیه خیلی کدام احمقانه بود تا اومدم یاد بگیرم چی به چیه بارها connect و disconnect شدم، 2-3 مرتبه برام پیش اومد و دیدم که دیگه Scanner نمیتونه Gateway رو پیدا بکنه… با خاموش روشن کردن بلوتوث هم درست نمیشد! مجبور میشدم گوشی رو کامل ریستارت کنم!!!

یکمی که سرچ کردم ببینم بقیه ازین مشکلا داشتن یا نه به مقالات شرکت Fitbit بخورد کردم که گجت های پوشیدنی هوشمند تولید میکنه.
اونها تو مقالاتشون توضیح دادن که چقدر با دستگاهای اندرویدی چالشای عجیب و غریب داشتند و برای رفع اون مشکلا چکارایی کردن.
مقاله اول
مقاله دوم
خروجی کارشون 2 تا کتابخانه باحاله که میتونین تو پروژه های جدید استفاده کنین.

 

خب از پیام بازرگانی بیایم بیرون.?

مشکل پایتون اینه که حافظه زیادی برای اجرا میخواد و دنگ و فنگ بیشتری داره برای اجرا روی لینوکسی که روی ماژول Brain داریم.

برای همین Qt رو به این علت که پشتیبانی خیلی خوبی داره انتخاب کردیم برای بازنویسی GATT Server – ممکنه بپرسین این تناقض نداره با انتخاب فلاتر؟ خودم هم جوابشو نمیدونم!!!

علاوه بر کتابخانه هایی که در اون 2 تا مقاله معرفی کرده، یک سری کتابخانه دیگه هم فرستادم برای بررسی، اما کارفرما نهایتا بیشتر دلش با Qt بود.

لینکاشونو میذارم اینجا شما هم ببینید:

برای کسایی هم که با ESP32 کار میکنن یک Gateway BLE2MQTT وجود داره که لینکش کردم.

واقعا مستندات Qt افتضاحه، شایدم توی بلوتوث اینجوریه! من در ارسال و دریافت داده های حجیم به مشکل خوردم.

از سمت اندروید 10 کیلوبایت (برای BLE حجیم حساب میشه!) داده ارسال کردم، روی Broker دریافت میشد و وقتی Relay میکرد و GATT Server میخواست داده ها رو بفرسته برای اندروید، خطا میداد و پکت ها دراپ میشد!!!

من این مشکل رو توی پایتون نداشتم، چرا این اتفاق میافتاد؟

انقدر گیج و گم سرچ کردم تا فهمیدم ای بابا، برای Qt قابل اطمینان بودن ارسال اطلاعات اصلا مهم نیست! یعنی اگه نتونه چیزی رو ارسال کنه به راحتی DROP میکنه!

سورسشم اینجاست ببینید: سورس

 

سرانجام!

با تعجب بسیار زیاد، گفتم حتما راهی هست و قبلا کسی این مشکلو حل کرده؟ هرچی سرچ کردم باز نتیجه نگرفتم.

رفتم توی استک اورفلو و انجمن های کیوت سوال پرسیدم و داخل دیسکورد هم گروهشونو پیدا کردم و اونجا هم پرسیدم!

اما دریغ از یک کامنت و راهنمایی!

هر چی هم سورسشو بالا پایین کردم چیزی پیدا نکردم برای حل این مشکل…!

نهایتا دیدم اگه پکتی رو دراپ بکنه، ی وارنینگ میده… ی لاگ هندلر داخل کدم نوشتم که هرجا لاگی اومد بتونم داشته باشمش.

داخل لاگ هندلرم وارنینگ ها رو بررسی کردم، اگه همون وارنینگ بخصوص بود با یک سری ساز و کاری مجدد تلاش میکردم برای ارسال!

اینجوری مشکل قابل اعتماد نبودنش حل شد!…

 

بعد نوبت رسید به تست روی آیفون.

روی ماشین مجازی مک که داشتم پروژه رو سوار کردم و اجراش کردم روی آیفونم.

متوجه شدم بر خلاف اندروید که باید بعد از اتصال MTU مذاکره بشه، آیفون زمان اتصال این کار رو خودش انجام میده.

رفتم سراغ تست ارسال و دریافت داده حجیم!

واقعا شگفت انگیز بود!

خطاهای اندروید توی ارسال و دریافت اطلاعات رو نداشتم دیگه…

در سخت افزار BLE واقعا اپل چندین سال از اندرویدیا جلوتره!

 

اگه این مقاله براتون جالب بود، لطفا به اشتراک بذاریدش!

اگه در مورد موضوعی خواستید با من ارتباط بگیرید، میتونید از طریق اینستاگرام اقدام کنید: aliep_ir

 

 

منبع:سیسوگ

 

 

مطلب قبلیبرد متن باز برای RP2040 و آموزش کار با این میکروکنترلر – قسمت اول
مطلب بعدیآشنایی با رگولاتور ها – قسمت اول – مقدمه

پاسخ دهید

لطفا نظر خود را وارد کنید!
لطفا نام خود را در اینجا وارد کنید