Zephyr OS کے ساتھ بلوٹوتھ ایپلی کیشنز کیسے بنائیں: ایک ڈویلپر کی ہینڈ بک

وائرلیس ایئربڈز سے منسلک ایک فون، ایک اسمارٹ واچ نے صحت کے ڈیٹا کو ایپ سے ہم آہنگ کیا، اور عمارت میں کہیں موجود ایک سینسر نے گیٹ وے کو درجہ حرارت کی اطلاع دی۔ یہ تمام تعاملات بلوٹوتھ لو انرجی (BLE) پر ہوئے۔ اور تیزی سے، ان آلات کا فرم ویئر Zephyr OS پر بنایا گیا ہے۔

یہ ہینڈ بک آپ کو سکھاتی ہے کہ شروع سے Zephyr پر بلوٹوتھ ایپلی کیشن کیسے بنایا جائے۔ ہم BLE کی بنیادی باتوں سے شروع کریں گے (GAP، GATT، خدمات اور خصوصیات کا اصل مطلب کیا ہے) اور پھر اصل Zephyr فرم ویئر لکھنے کی طرف بڑھیں گے، بشمول ڈیوائس کی تشہیر، کسٹم سروسز بنانا، کنکشنز کو ہینڈل کرنا، BLE پر سینسر ڈیٹا پڑھنا، اور ایک مکمل BLE پیریفیرل بنانا جو فون کے ساتھ بات چیت کر سکے۔

ہر تصور ورکنگ کوڈ کے ساتھ آتا ہے، اور ہر کوڈ بلاک اس کی وضاحت کے ساتھ آتا ہے کہ یہ کیا کرتا ہے اور یہ کیوں ضروری ہے۔

یہ ایک طویل اور تفصیلی گائیڈ ہے۔ بلوٹوتھ میں بہت سارے متحرک حصے ہیں، اور زیادہ تر ٹیوٹوریلز ان پرزوں پر چمکتے ہیں جو لوگوں کو حقیقی پروجیکٹس میں الجھا دیتے ہیں۔

ایسا نہیں ہے۔ ترتیب وار کام کرنے اور آپ کے جاتے ہوئے کوڈ بنانے سے، آپ بالآخر وہ علم حاصل کر لیں گے جو آپ کو Zephyr پر پروڈکشن BLE ڈیوائس بنانے کے لیے درکار ہے۔

انڈیکس

شرطیں

اس ٹیوٹوریل پر عمل کرنے کے لیے، آپ کو C کوڈ پڑھنے اور لکھنے میں ماہر ہونا چاہیے۔ پوائنٹرز، ڈھانچے، فنکشن پوائنٹرز، اور کال بیکس بیرونی تصورات نہیں ہونے چاہئیں۔ آپ کو C پروجیکٹس اور کمانڈ لائن ٹرمینل بنانے کے بارے میں بنیادی معلومات کی ضرورت ہوگی۔ بلوٹوتھ کے پہلے تجربے کی ضرورت نہیں ہے۔ یہ مضمون شروع سے BLE تصورات کی وضاحت کرتا ہے۔

ہارڈ ویئر کے لیے، Nordic Semiconductor nRF52840 DK پیروی کرنے کے لیے ایک مثالی بورڈ ہے۔ نورڈک کی چپ میں Zephyr میں بہترین تعاون یافتہ بلوٹوتھ اسٹیک ہے، اور nRF52840 DK سستا ہے (تقریباً $40)، وسیع پیمانے پر دستیاب ہے، اور اس میں ایک آن بورڈ ڈیبگر بھی شامل ہے۔

یہ اس صورت میں بھی کام کرے گا اگر آپ کے پاس بلوٹوتھ (nRF52832 DK، nRF5340 DK، یا BLE- فعال ریڈیو والا بورڈ) والا دوسرا Zephyr- قابل بورڈ ہے۔

BLE سائیڈ کو جانچنے کے لیے، آپ کو BLE سکینر ایپ والے فون کی ضرورت ہوگی (موبائل کے لیے nRF کنیکٹ iOS اور Android دونوں کے لیے بہترین اور مفت ہے)۔

آپ کو لینکس (Ubuntu 22.04 یا اس کے بعد کے)، macOS، یا WSL2 کے ساتھ ونڈوز چلانے والے کمپیوٹر کی بھی ضرورت ہوگی۔

Zephyr OS کیا ہے اور میں اسے بلوٹوتھ کے لیے کیوں استعمال کروں گا؟

Zephyr OS ایک کمپیکٹ، اوپن سورس، ریئل ٹائم آپریٹنگ سسٹم ہے جو وسائل سے محدود ایمبیڈڈ ڈیوائسز کے لیے بنایا گیا ہے۔ اس کی میزبانی لینکس فاؤنڈیشن کرتی ہے، اپاچی 2.0 لائسنس یافتہ ہے، اور 8KB RAM کے ساتھ مائیکرو کنٹرولر پر چلتا ہے۔ ARM، RISC-V، x86، Xtensa، اور دیگر فن تعمیر میں 600 سے زیادہ بورڈز کو سپورٹ کرتا ہے۔

لیکن چونکہ یہ مضمون بلوٹوتھ کے بارے میں ہے، اس لیے یہاں Zephyr خاص طور پر BLE کی ترقی کے لیے اہم کیوں ہے:

Zephyr میں ایک مکمل بلوٹوتھ SIG مصدقہ BLE اسٹیک شامل ہے۔ اس کا مطلب یہ ہے کہ اسٹیک سرکاری بلوٹوتھ سرٹیفیکیشن کے عمل سے گزر چکا ہے اور وضاحتی ضروریات کو پورا کرتا ہے۔ یہ شوق کے نفاذ پر نہیں بنایا گیا ہے۔ ہم ایک اسٹیک پر تعمیر کر رہے ہیں جس نے کنفارمنس ٹیسٹ پاس کر لیا ہے۔

اسٹیک میں دونوں میزبان (GAP, GATT, SMP, L2CAP, ATT) اور کنٹرولرز (Link Layer, HCI) شامل ہیں۔ معاون ریڈیوز (بنیادی طور پر نورڈک این آر ایف سیریز) کے لیے، Zephyr اپنا اوپن سورس کنٹرولر نفاذ فراہم کرتا ہے۔ اس کا مطلب ہے کہ پورا بلوٹوتھ اسٹیک، ایپلیکیشن کوڈ سے لے کر ریڈیو رجسٹر تک، اوپن سورس ہے۔ کوئی بائنری بلاب نہیں ہیں۔ کوئی بند سورس لائبریریاں نہیں ہیں۔ آپ ہر لائن کو پڑھ سکتے ہیں، ڈیبگ کر سکتے ہیں اور اس میں ترمیم کر سکتے ہیں۔

نورڈک سیمی کنڈکٹر، جس کی چپس BLE مارکیٹ پر حاوی ہے، نے Zephyr کی بنیاد پر اپنا nRF Connect SDK بنایا۔ نورڈک انجینئرز BLE فرم ویئر لکھتے وقت Zephyr کا استعمال کرتے ہیں۔ یہ مضبوط حمایت ہے۔

Zephyr بلوٹوتھ اسٹیک بلوٹوتھ 5.x خصوصیات (2M PHY، طویل رینج کے لیے کوڈڈ PHY، توسیعی اشتہارات)، بلوٹوتھ میش (ریلے، پراکسی، بڈی، اور کم پاور نوڈ)، LE آڈیو (ایل سی 3 کوڈیک کے ساتھ جدید ترین بلوٹوتھ آڈیو اسٹینڈرڈ، براڈکاسٹ، اور ہیئرنگ ایڈل سپورٹ کی مدد کرتا ہے)۔ انڈور پوزیشننگ)، اور پروڈکٹ ڈویلپمنٹ کے لیے درکار تمام معیاری BLE پروفائلز اور خدمات۔

سیدھے الفاظ میں، اگر آپ ان دنوں BLE پروڈکٹ بنا رہے ہیں، Zephyr وہاں کے بہترین پلیٹ فارمز میں سے ایک ہے۔ Google اسے اپنی Chromebooks میں استعمال کرتا ہے، Nordic اسے اپنے پورے SDK میں استعمال کرتا ہے، اور سینکڑوں کمپنیاں اس کے اوپر بنے ہوئے پروڈکٹس بھیجتی ہیں۔

بلوٹوتھ کم توانائی کی بنیادی باتیں

کوڈ لکھنے سے پہلے، آپ کو ایک ذہنی ماڈل کی ضرورت ہے کہ BLE کیسے کام کرتا ہے۔ اگر آپ BLE سے پہلے ہی واقف ہیں تو اس سیکشن کو چھوڑ دیں۔ اگر نہیں تو غور سے پڑھیں۔ کیونکہ اس کے بعد آنے والی ہر چیز ان تصورات پر مبنی ہے۔

BLE "کلاسک” بلوٹوتھ جیسا نہیں ہے (ایل ای آڈیو سے پہلے اسپیکر پر آڈیو چلانے کے لیے استعمال ہونے والی قسم)۔ کلاسک بلوٹوتھ (BR/EDR) کو مسلسل، ہائی تھرو پٹ ڈیٹا اسٹریمنگ کے لیے ڈیزائن کیا گیا ہے۔ BLE وقفے وقفے سے، کم طاقت والے مواصلات کے لیے ڈیزائن کیا گیا ہے۔

ایک BLE سینسر فی منٹ میں ایک بار جاگ سکتا ہے، 20 بائٹس ڈیٹا بھیج سکتا ہے، اور پھر واپس سو سکتا ہے۔ یہ تعاملات مائیکرو واٹ توانائی استعمال کرتے ہیں۔ یہ بنیادی ڈیزائن فرق BLE ڈیوائسز کو کوائن سیل بیٹریوں پر برسوں تک کام کرنے دیتا ہے۔

BLE کمیونیکیشن دو اہم پرتوں پر مشتمل ہوتی ہے جن کے ساتھ ہم بطور ڈویلپر بات چیت کرتے ہیں: GAP اور GATT۔

عام رسائی پروفائل (GAP) کنٹرول کرتا ہے کہ آلات کس طرح ایک دوسرے کو دریافت کرتے ہیں اور کنکشن قائم کرتے ہیں۔ GAP کو "پارٹیوں میں لوگوں سے ملنے” کی پرت کے طور پر سوچیں۔

ایک آلہ کئی GAP کرداروں میں سے ایک سے تعلق رکھتا ہے۔ کوئی راستہ نہیں فریم (جسے مشتہرین بھی کہا جاتا ہے) وقتاً فوقتاً اعداد و شمار کے چھوٹے پیکٹ اپنی موجودگی اور بنیادی معلومات کا اعلان کرنے کے لیے نشر کرتے ہیں۔ کوئی راستہ نہیں ہیڈکوارٹر (اسے اسکینر بھی کہا جاتا ہے) ان نشریات کو سن سکتا ہے اور کنکشن شروع کر سکتا ہے۔ آپ کا فون عام طور پر مرکزی آلہ ہوتا ہے۔ سینسر، ایئربڈز، اور سمارٹ واچز عام طور پر پیری فیرلز ہوتے ہیں۔

GATT (عام وصف پروفائل) کنٹرول کرتا ہے کہ دو آلات کے منسلک ہونے کے بعد ڈیٹا کا تبادلہ کیسے ہوتا ہے۔ GATT کو "بات کرنے والی” پرت کے طور پر سوچیں۔

GATT ایک درجہ بندی کے اعداد و شمار کے ڈھانچے کی وضاحت کرتا ہے۔ اعلی ترین سطح پر، ایک آلہ ایک یا زیادہ ہوتا ہے۔ سروس. سروسز گروپ سے متعلقہ ڈیٹا ایک ساتھ۔

مثال کے طور پر، دل کی شرح مانیٹر میں دل کی شرح کی خدمت ہو سکتی ہے۔ ہر سروس کے اندر ایک یا زیادہ خدمات ہیں۔ خصوصیات. ایک خصوصیت ایک واحد ڈیٹا پوائنٹ ہے جس میں ایک قدر اور میٹا ڈیٹا ہوتا ہے۔ دل کی شرح کی خدمت میں دل کی شرح کی پیمائش کی خصوصیت (حقیقی بی پی ایم قدر) اور جسم کے سینسر کے مقام کی خصوصیت (جہاں سینسر پہنا جاتا ہے) ہو سکتا ہے۔

ہر ایک کی خصوصیت ہوتی ہے۔ وصف یہ وضاحت کرتا ہے کہ آپ اس کے ساتھ کیا کر سکتے ہیں۔ ایک خصوصیت پڑھنے کے قابل ہو سکتی ہے (ایک قدر مرکز سے طلب کی جا سکتی ہے)، قابل تحریر (ایک قدر مرکز کی طرف سے سیٹ کی جا سکتی ہے)، قابل اطلاع (پیری فیرلز اس کی درخواست کیے بغیر اپ ڈیٹ کو مرکز تک پہنچا سکتے ہیں)، یا مرئی (یعنی، ایک اطلاع کی طرح، لیکن اعتراف کے ساتھ)۔ ایک خاصیت میں متعدد خصوصیات ہوسکتی ہیں۔

تمام خدمات اور خصوصیات UUID. بلوٹوتھ SIG عام خدمات اور خصوصیات (دل کی دھڑکن کے لیے 0x180D، بیٹری کی خدمات کے لیے 0x180F، وغیرہ) کے لیے معیاری 16 بٹ UUIDs کی وضاحت کرتا ہے۔ حسب ضرورت فنکشنز کے لیے، اپنے 128 بٹ UUID کی وضاحت کریں۔

یہاں ایک ٹھوس ذہنی ماڈل ہے۔ درجہ حرارت سینسر ڈیوائس کا تصور کریں۔

Device: "My Temp Sensor"
  |
  +-- Environmental Sensing Service (UUID: 0x181A)
  |     |
  |     +-- Temperature characteristic (UUID: 0x2A6E)
  |     |     Properties: Read, Notify
  |     |     Value: 23.5 (degrees C)
  |     |
  |     +-- Humidity characteristic (UUID: 0x2A6F)
  |           Properties: Read, Notify
  |           Value: 65.2 (percent)
  |
  +-- Battery Service (UUID: 0x180F)
        |
        +-- Battery Level characteristic (UUID: 0x2A19)
              Properties: Read, Notify
              Value: 87 (percent)

یہ خاکہ ایک آلہ دکھاتا ہے جس میں دو خدمات اور تین خصوصیات ہیں۔ منسلک فون درجہ حرارت کو پڑھ سکتے ہیں، نمی کی اطلاعات کو سبسکرائب کر سکتے ہیں، اور بیٹری کی سطح کو چیک کر سکتے ہیں۔ خدمات اور خصوصیات BLE آلات کے APIs ہیں۔

اس اچھی طرح سے ڈیزائن کرنا ایک اچھا REST API ڈیزائن کرنے جیسا ہے۔ اس بارے میں سوچیں کہ آلہ کس ڈیٹا کو ظاہر کرتا ہے اور کلائنٹ اس ڈیٹا کے ساتھ کیسے تعامل کرتے ہیں۔

ایک اور تصور: اشتہاری ڈیٹا. جب کوئی پیریفرل اشتہار دیتا ہے، تو یہ چھوٹے پیکٹ نشر کرتا ہے (روایتی اشتہارات کے لیے 31 بائٹس تک، توسیعی اشتہارات کے لیے بڑے)۔ ان پیکٹوں میں سٹرکچرڈ ڈیٹا ہوتا ہے جیسے ڈیوائس کا نام، معاون خدمات، مینوفیکچرر کے لیے مخصوص ڈیٹا، اور جھنڈے۔ ایڈورٹائزنگ ڈیٹا وہ ہے جو اسکینر کنیکٹ کرنے سے پہلے دیکھتا ہے۔ یہ آپ کے آلے کا "بزنس کارڈ” ہے۔

GAP ٹائر: ایڈورٹائزنگ اور کنیکٹیویٹی

GAP وہ پہلی پرت ہے جس سے آپ BLE ڈیوائس بناتے وقت تعامل کرتے ہیں۔ آپ کو کچھ اور ہونے سے پہلے ایک پردیی کی موجودگی کو معلوم کرنے کی ضرورت ہے۔

اشتہارات اس طرح کام کرتے ہیں: پیریفرل کا ریڈیو باقاعدہ وقفوں ("اشتہاری وقفے”) پر جاگتا ہے، تین اشتہاری چینلز (چینلز 37، 38، اور 39) میں سے ایک پر مختصر پیکٹ منتقل کرتا ہے، اور پھر واپس سو جاتا ہے۔ اس چینل کو مرکزی طور پر اسکین کرتے ہوئے، یہ پیکٹ اٹھاتا ہے اور ڈیوائس کے بارے میں سیکھتا ہے۔

اشتھاراتی وقفہ کاری ایک تجارت ہے۔ مختصر وقفے (مثلاً 20 ms) آلات کو تلاش کرنا آسان بناتے ہیں، لیکن زیادہ طاقت استعمال کرتے ہیں۔ لمبے وقفے (مثلاً 1000 ms) بجلی بچاتے ہیں لیکن تلاش کی رفتار کم کرتے ہیں۔ زیادہ تر ایپلی کیشنز کے لیے، 100 سے 500 ms ایک معقول حد ہے۔

ایڈورٹائزنگ پیکٹ میں سٹرکچرڈ فیلڈز ہوتے ہیں جنہیں ایڈورٹائزنگ ڈیٹا (AD) اسٹرکچر کہتے ہیں۔ ہر AD ڈھانچے میں لمبائی بائٹ، ایک قسم بائٹ، اور ڈیٹا بائٹ ہوتا ہے۔ عام اقسام میں جھنڈے (دریافت اور BR/EDR سپورٹ کی نشاندہی کرتے ہوئے)، مکمل یا مختصر مقامی نام، سروس UUIDs کی فہرست، TX پاور لیولز، اور مینوفیکچرر کے لیے مخصوص ڈیٹا شامل ہیں۔

لیگیسی اشتہارات (بلوٹوتھ 4.x) کے لیے، کل پے لوڈ 31 بائٹس تک محدود ہے، اس لیے آپ زیادہ فٹ نہیں ہو سکتے۔ اکثر آپ کو ڈیوائس کے نام اور سروس UUID کے درمیان انتخاب کرنے کی ضرورت ہوگی۔ کیونکہ دونوں مناسب نہیں ہو سکتے۔

بلوٹوتھ 5.0 نے توسیعی اشتہارات متعارف کرائے ہیں، جو 254 بائٹس تک کے اشتہارات کے پے لوڈز کی اجازت دیتا ہے (جو بڑے پے لوڈز میں جڑے ہوئے ہیں)، تمام 40 BLE چینلز (صرف تین اشتہاری چینلز نہیں)، اور متعدد بیک وقت اشتہاری سیٹوں پر اشتہارات۔ Zephyr توسیع شدہ اشتہارات کی حمایت کرتا ہے اگر آپ کا ہارڈویئر اور کنٹرولر اس کی حمایت کرتے ہیں۔

ایک بار جب مرکزی آلہ جڑنے کا فیصلہ کر لیتا ہے، تو یہ پردیی آلات کو کنکشن کی درخواست بھیجتا ہے۔ دونوں آلات کنکشن کے پیرامیٹرز پر بات چیت کرتے ہیں۔ کنکشن وقفہ (مواصلات کی فریکوئنسی، عام طور پر 7.5 ایم ایس سے 4 سیکنڈ) پیریفرل انکیوبیشن کا دورانیہ (کنکشن کے واقعات کی تعداد جو پردیی بجلی بچانے کے لیے چھوڑ سکتے ہیں) نگرانی کا وقت ختم (کنکشن کھو جانے پر غور کرنے سے پہلے کتنا انتظار کرنا ہے)

یہ پیرامیٹرز ڈیٹا تھرو پٹ اور بجلی کی کھپت دونوں کو متاثر کرتے ہیں۔ مختصر کنکشن وقفے تیزی سے ڈیٹا کی منتقلی کی اجازت دیتے ہیں، لیکن زیادہ بجلی خرچ ہوتی ہے۔ ہائی پرفیرل لیٹینسی پاور بچاتی ہے لیکن ڈیٹا ایکسچینج میں تاخیر کا اضافہ کرتی ہے۔

GATT پرتیں: خدمات اور خصوصیات

ایک بار کنکشن قائم ہو جانے کے بعد، GATT اپنی ذمہ داری سنبھال لیتا ہے۔ منسلک آلات پہلے بیان کردہ سروس/شخصیت کی پرت کے ذریعے ڈیٹا کا تبادلہ کرتے ہیں۔

پیری فیرلز GATT ڈیٹا بیس کی وضاحت کرتے ہیں، ڈیوائس کے ذریعے سامنے آنے والی خدمات اور خصوصیات کی فہرست۔ مرکزی طرف سروس دریافت کرتا ہے۔ یعنی، یہ دستیاب خدمات اور خصوصیات کے لیے قریبی آلات سے استفسار کرتا ہے۔

GATT ڈیٹا بیس میں ہر خصوصیت کے کئی اجزاء ہوتے ہیں۔ کہ قدر یہ اصل ڈیٹا ہے (بائٹس کی صف)۔ کہ وصف اجازت یافتہ آپریشن کی تعریفیں: پڑھیں (0x02)، جواب کے بغیر لکھیں (0x04)، لکھیں (0x08)، مطلع کریں (0x10)، اور ڈسپلے (0x20) سب سے عام ہیں۔ کہ اتھارٹی حفاظتی تقاضوں میں یہ شامل ہے کہ آیا پڑھنے/لکھنے کے لیے خفیہ کاری، تصدیق، یا اجازت درکار ہے۔

اطلاعات اور اشارے کے لیے، خصوصیات میں شامل ہیں۔ کلائنٹ کریکٹرسٹک کنفیگریشن ڈسکرپٹر (CCCD). یہ ایک خاص 2 بائٹ ویلیو ہے جسے مرکزی ڈیوائس نے نوٹیفیکیشن/اشاروں کو فعال یا غیر فعال کرنے کے لیے لکھا ہے۔ اطلاع اس وقت چالو ہوتی ہے جب مرکزی آلہ CCCD پر 0x0001 لکھتا ہے۔ 0x0000 لکھنا اسے غیر فعال کر دیتا ہے۔ Zephyr خود بخود CCCD کو ہینڈل کرتا ہے جب خصوصیات کو اطلاع کی خصوصیات کے طور پر بیان کیا جاتا ہے۔

GATT کے آپریشنز مندرجہ ذیل ہیں:

  • پڑھنے کے لیے: مرکزی آلہ پڑھنے کی درخواست بھیجتا ہے اور پیریفرل ڈیوائس ایک خصوصیت کے ساتھ جواب دیتا ہے۔

  • تحریروں کے لیے: مرکزی آلہ ایک نئی قدر کے ساتھ تحریری درخواست بھیجتا ہے، پیریفرل ڈیوائس قدر کو اپ ڈیٹ کرتا ہے اور جواب بھیجتا ہے۔

  • اطلاعات کے لیے: پیری فیرلز مرکز سے پوچھے بغیر مرکز کو اقدار بھیجتے ہیں۔ مرکزی طور پر، آپ کے پاس اس وصف کے لیے پہلے سے فعال اطلاعات ہونی چاہئیں۔

اس درخواست/جواب کے ماڈل کا مطلب ہے کہ BLE اسٹریمنگ پروٹوکول نہیں ہے۔ یہ ایک پیغام پاس کرنے والا پروٹوکول ہے۔ اگر آپ کو مسلسل سینسر ڈیٹا بھیجنے کی ضرورت ہے تو، مقررہ وقفوں پر اطلاعات کا استعمال کریں۔ اگر آپ کو ڈیوائس کو کنفیگر کرنے کی ضرورت ہے تو اسے پراپرٹیز پر لکھیں۔ یہ اس بات کا تعین کرتا ہے کہ آپ اپنی BLE ایپلیکیشن کو کس طرح ڈیزائن کرتے ہیں۔

Zephyr ترقی کے ماحول کو قائم کرنا

یہ سیکشن پورے ماحول کو ترتیب دینے میں آپ کی رہنمائی کرتا ہے۔ اگر آپ کے پاس پہلے سے ہی Zephyr ماحول ہے، تو اگلے حصے پر جائیں۔

سسٹم انحصار انسٹال کریں (اوبنٹو):

sudo apt update
sudo apt install --no-install-recommends git cmake ninja-build gperf \
  ccache dfu-util device-tree-compiler wget python3-dev python3-pip \
  python3-setuptools python3-tk python3-wheel xz-utils file \
  make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1

یہ پیکیجز کمپائلر ٹول چین، بلڈ سسٹم، اور Zephyr کی تعمیر کے عمل کے لیے درکار افادیت فراہم کرتے ہیں۔

ڈیوائس ٹری کمپائلر (device-tree-compiler) خاص طور پر Zephyr کے لیے اہم ہے کیونکہ یہ ہارڈ ویئر کی تفصیل کی فائل کو ہینڈل کرتا ہے، جو بورڈ کے پیری فیرلز اور پن اسائنمنٹس کے بارے میں بلڈ سسٹم کو بتاتا ہے۔

ویسٹ انسٹال کریں، Zephyr کمانڈ لائن ٹول۔

pip3 install west

ویسٹ Zephyr کے ذریعے استعمال ہونے والے ملٹی ریپوزٹری ورک اسپیس کا انتظام کرتا ہے اور فرم ویئر کو بنانے، چمکانے اور ڈیبگ کرنے کے لیے کمانڈ فراہم کرتا ہے۔ یہ واحد ٹول ہے جس کے ساتھ آپ سب سے زیادہ تعامل کرتے ہیں۔

اپنے ورک اسپیس کو شروع اور اپ ڈیٹ کریں۔

west init ~/zephyrproject
cd ~/zephyrproject
west update

کہ west init کمانڈ ایک ورک اسپیس بناتی ہے اور پہلے سے طے شدہ Zephyr ذخیرہ کو کلون کرتی ہے۔ کہ west update کمانڈ پھر تمام ماڈیول انحصار درآمد کرتی ہے، بشمول وینڈر لو لیول چپ سپورٹ پیکجز (HALs)، کرپٹوگرافک لائبریریاں، بلوٹوتھ کنٹرولر کوڈ، اور دیگر اجزاء۔ اس میں کچھ وقت لگے گا کیونکہ یہ کئی گیگا بائٹس ڈاؤن لوڈ کرے گا۔

ازگر کی ضروریات کو انسٹال کریں۔

pip3 install -r ~/zephyrproject/zephyr/scripts/requirements.txt

یہ Python پیکجز کو انسٹال کرتا ہے جن پر Zephyr کی تعمیر اسکرپٹس اور ویسٹ ایکسٹینشنز انحصار کرتی ہیں، بشمول ڈیوائس ٹری پروسیسنگ ٹول، Kconfig فرنٹ اینڈ، اور مختلف کوڈ جنریشن یوٹیلیٹیز۔ تقاضے فائلیں مخصوص ورژنوں کو پن کرتی ہیں تاکہ تولیدی صلاحیت کو یقینی بنایا جا سکے۔

Zephyr SDK انسٹال کریں (تمام معاون آرکیٹیکچرز کے لیے کراس کمپائلیشن ٹول چین فراہم کرتا ہے)۔

cd ~
wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.8/zephyr-sdk-0.16.8_linux-x86_64.tar.xz
tar xvf zephyr-sdk-0.16.8_linux-x86_64.tar.xz
cd zephyr-sdk-0.16.8
./setup.sh

SDK میں ARM، RISC-V، x86، Xtensa، اور مزید کے لیے GCC پر مبنی ٹول چینز شامل ہیں۔ کہ setup.sh اسکرپٹ اسے CMake کے ساتھ رجسٹر کرتی ہے۔ تازہ ترین SDK ورژن نمبرز کے لیے Zephyr ریلیز کا صفحہ چیک کریں۔ یہ کتابچہ لکھے جانے کے بعد سے اپ ڈیٹ ہو سکتا ہے۔

ماحولیاتی متغیرات کی ترتیب (یہ ~/.bashrc یا ~/.zshrc):

export ZEPHYR_BASE=~/zephyrproject/zephyr
source ~/zephyrproject/zephyr/zephyr-env.sh

کہ ZEPHYR_BASE متغیر بلڈ سسٹم کو بتاتا ہے کہ Zephyr سورس ٹری کہاں ہے۔ کہ zephyr-env.sh اسکرپٹ اضافی راستے مرتب کرتی ہے۔ دونوں کو ترتیب دینا آپ کو کسی بھی ڈائرکٹری سے کسی بھی معاون بورڈ کے لیے تعمیر کرنے کی اجازت دیتا ہے۔

پہلی BLE ایپلیکیشن: ایک سادہ بیکن

آئیے سب سے آسان BLE ایپلیکیشن کے ساتھ شروع کریں۔ ایسا آلہ جو صرف تشہیر کرتا ہے اور کچھ نہیں کرتا۔ کوئی کنکشن، کوئی سروس، کوئی ڈیٹا ایکسچینج نہیں ہے۔ یہ صرف ایک اشارہ ہے جو آپ کی موجودگی کا اعلان کرتا ہے۔

پروجیکٹ کا ڈھانچہ بنائیں۔

mkdir -p ~/my_ble_apps/beacon/src

یہ ایک معیاری Zephyr ایپلیکیشن ڈائرکٹری لے آؤٹ بناتا ہے۔ تمام Zephyr ایپلی کیشنز ان کی اپنی ڈائرکٹری میں موجود ہیں: src/ سی سورس فائلوں کے لیے سب ڈائرکٹری۔ پروجیکٹ روٹ میں بلڈ کنفیگریشن فائلیں ہوتی ہیں۔

بنانا ~/my_ble_apps/beacon/CMakeLists.txt:

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(ble_beacon)
target_sources(app PRIVATE src/main.c)

کہ find_package(Zephyr) لائن پورے Zephyr بلڈ سسٹم کو لوڈ کرتی ہے۔ کہ target_sources لائن سورس فائلوں کو نامزد بلڈ ٹارگٹ میں شامل کرتی ہے۔ appیہ Zephyr ایپلی کیشنز کے لیے معیاری ہدف کا نام ہے۔

بنانا ~/my_ble_apps/beacon/prj.conf:

CONFIG_BT=y
CONFIG_BT_BROADCASTER=y

دو ترتیب لائنیں: CONFIG_BT=y بلوٹوتھ سب سسٹم کو ہوسٹ اسٹیک، HCI پرت، اور (تعاون یافتہ بورڈز کے لیے) کنٹرولر لانے کے قابل بناتا ہے۔ CONFIG_BT_BROADCASTER=y براڈکاسٹر کے کردار کو فعال کرتا ہے، جو ان آلات کے لیے کم سے کم کردار ہے جو صرف تشہیر کرتے ہیں۔ یہ بیکن کنکشن کو قبول نہیں کرتا ہے، اس لیے ابھی تک کسی پردیی کردار کی ضرورت نہیں ہے۔

بنانا ~/my_ble_apps/beacon/src/main.c:

#include 
#include 

static const struct bt_data ad[] = {
    BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),
    BT_DATA_BYTES(BT_DATA_NAME_COMPLETE,
                  'M', 'y', 'B', 'e', 'a', 'c', 'o', 'n'),
};

int main(void)
{
    int err;

    printk("Starting BLE Beacon\n");

    err = bt_enable(NULL);
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
        return 0;
    }

    printk("Bluetooth initialized\n");

    err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad), NULL, 0);
    if (err) {
        printk("Advertising failed to start (err %d)\n", err);
        return 0;
    }

    printk("Beacon is advertising\n");

    return 0;
}

آئیے ایک ایک کرکے اس کوڈ پر ایک نظر ڈالتے ہیں۔

کہ ad صف اشتہار کے ڈیٹا کی وضاحت کرتی ہے۔ یہ دو AD ڈھانچے پر مشتمل ہے۔

پہلا فلیگ فیلڈ ہے، جو BLE ایڈورٹائزنگ میں درکار ہے۔ BT_LE_AD_GENERAL اس کا مطلب یہ ہے کہ آلہ عام قابل دریافت موڈ میں ہے (تمام سکینرز کو نظر آتا ہے)۔ BT_LE_AD_NO_BREDR اشارہ کرتا ہے کہ آلہ کلاسک بلوٹوتھ (BR/EDR) کو سپورٹ نہیں کرتا، بلکہ صرف BLE کو سپورٹ کرتا ہے۔

دوسرا AD ڈھانچہ مکمل مقامی نام ہے جو حرف بہ حرف لکھا جاتا ہے۔ کہ BT_DATA_BYTES میکرو اسے صحیح AD ڈھانچے کی شکل میں کمپریس کرتا ہے۔

کہ bt_enable(NULL) کال پورے بلوٹوتھ سب سسٹم کو شروع کرتی ہے۔ یہ HCI ٹرانسپورٹ کو ترتیب دیتا ہے، کنٹرولر کو شروع کرتا ہے (اگر جہاز پر ریڈیو استعمال کر رہا ہو)، اور میزبان اسٹیک تیار کرتا ہے۔ کہ NULL arguments کا مطلب ہے کہ یہ ایک ہم وقت ساز کال ہے۔ ابتداء مکمل ہونے تک یہ بلاک رہے گا۔ آپ کال بیک فنکشن پاس کرکے اسے غیر مطابقت پذیر بنا سکتے ہیں۔

کہ bt_le_adv_start کال کا اشتہار شروع ہوتا ہے۔ پہلا دعویٰ یہ ہے کہ BT_LE_ADV_NCONNبتاتا ہے کہ کن اشتہارات تک نہیں پہنچ سکتا۔ اس کا مطلب ہے کہ سکینر بیکن کو دیکھ سکتا ہے، لیکن اس سے رابطہ نہیں کر سکتا۔ کہ ad ترتیب اور سائز (ARRAY_SIZE(ad)) اشتہاری ڈیٹا فراہم کرتا ہے۔ آخری دو دلائل (NULL, 0) اسکین جوابی ڈیٹا کے لیے ہے، جو کہ اضافی ڈیٹا بھیجا جاتا ہے جب اسکینر فعال طور پر اسکین کر رہا ہو (اسکین کی درخواست بھیجنا)۔ یہ سادہ مثال اسکین جوابی ڈیٹا استعمال نہیں کرتی ہے۔

بعد میں main() واپس آنے پر، Zephyr مین تھریڈ ختم ہو جاتا ہے، لیکن سسٹم چلتا رہتا ہے۔ بلوٹوتھ سب سسٹم کنٹرولر اور بلوٹوتھ ہوسٹ تھریڈز کے ذریعے چلایا جاتا ہے اور پس منظر میں تشہیر کرنا جاری رکھتا ہے۔

تعمیر اور فلیش:

cd ~/zephyrproject
west build -b nrf52840dk/nrf52840 ~/my_ble_apps/beacon
west flash

کہ west build کمانڈ nRF52840 DK کے لیے ایپلیکیشن کو مرتب کرتی ہے، جو درج ذیل جگہوں پر ایک ELF بائنری اور HEX فائل تیار کرتی ہے۔ build/ ڈائریکٹری کہ west flash آن بورڈ J-Link ڈیبگر خود بخود منسلک بورڈز کا پتہ لگاتا ہے اور بورڈ میں بائنریز شامل کرنے کے لیے کمانڈ پروگرام کے ساتھ درست پروگرامنگ پروٹوکول کا استعمال کرتا ہے۔

اپنے فون پر nRF Connect ایپ کھولیں اور اسکین کرنا شروع کریں، اور آپ کو دریافت شدہ آلات کی فہرست میں "MyBeacon” نظر آئے گا۔ یہ وہ فرم ویئر ہے جو بورڈ پر چلتا ہے اور اس کی تشہیر BLE پر کی جاتی ہے۔

اپنی مرضی کے مطابق خدمات کے ساتھ BLE پیری فیرلز بنانا

براڈکاسٹنگ بیکنز کچھ ایپلی کیشنز (iBeacon، Eddystone، asset tracking) کے لیے مفید ہیں۔ تاہم، زیادہ تر BLE آلات کو GATT سروسز کے ذریعے ڈیٹا کو جوڑنے اور ظاہر کرنے کے قابل ہونا چاہیے۔ اب آئیے اپنی کسٹم سروس کا استعمال کرتے ہوئے پیریفرل بنانا شروع کریں۔

ایک "ایل ای ڈی سروس” بنائیں جو فون کو بورڈ پر ایل ای ڈی کو کنٹرول کرنے اور بٹن کی حالتوں کو پڑھنے کی اجازت دیتی ہے۔ یہ ایک کلاسک BLE ڈیمو ہے جو آپ کو کسی بھی BLE پروجیکٹ میں استعمال کرنے کے نمونے سکھاتا ہے۔

ایک پروجیکٹ بنائیں:

mkdir -p ~/my_ble_apps/led_service/src

بیکن کے طور پر ایک ہی پروجیکٹ لے آؤٹ: تعمیر کنفیگریشن کے لیے روٹ ڈائرکٹری اور src/ سورس کوڈ کے لیے ڈائرکٹری۔ یہ علیحدگی یقینی بناتی ہے کہ تعمیراتی نمونے ماخذ فائلوں سے الگ تھلگ رہیں۔

بنانا ~/my_ble_apps/led_service/prj.conf:

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Zephyr LED"
CONFIG_BT_DEVICE_APPEARANCE=0
CONFIG_GPIO=y
CONFIG_BT_GATT_DYNAMIC_DB=y

CONFIG_BT_PERIPHERAL=y براڈکاسٹر رول اور پیریفرل رول کو فعال کرتا ہے، جس میں کنکشن قبولیت کا فنکشن شامل ہے۔ CONFIG_BT_DEVICE_NAME ڈیفالٹ ڈیوائس کا نام اور GAP ڈیوائس کے نام کے انتسابات جو اشتہارات میں استعمال ہوتے ہیں سیٹ کریں۔ CONFIG_GPIO=y GPIO ڈرائیور کو فعال کرنے سے آپ کو LEDs کو کنٹرول کرنے اور بٹن پڑھنے کی اجازت ملے گی۔

بنانا ~/my_ble_apps/led_service/CMakeLists.txt:

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(ble_led_service)
target_sources(app PRIVATE src/main.c)

یہ بیکن پروجیکٹ کا وہی سی میک بوائلر پلیٹ ہے۔ صرف تبدیلی پروجیکٹ کا نام ہے (ble_led_service)۔ کہ find_package(Zephyr) کال پورے Zephyr بلڈ سسٹم کو لوڈ کرتی ہے۔ target_sources درخواست کے ماخذ فائلوں کو رجسٹر کریں۔

بنانا ~/my_ble_apps/led_service/src/main.c:

#include 
#include 
#include 
#include 
#include 

/* Custom service UUID: 00001234-0000-1000-8000-00805f9b34fb */
#define BT_UUID_LED_SERVICE_VAL \
    BT_UUID_128_ENCODE(0x00001234, 0x0000, 0x1000, 0x8000, 0x00805f9b34fb)
#define BT_UUID_LED_SERVICE BT_UUID_DECLARE_128(BT_UUID_LED_SERVICE_VAL)

/* LED characteristic UUID */
#define BT_UUID_LED_CHAR_VAL \
    BT_UUID_128_ENCODE(0x00001235, 0x0000, 0x1000, 0x8000, 0x00805f9b34fb)
#define BT_UUID_LED_CHAR BT_UUID_DECLARE_128(BT_UUID_LED_CHAR_VAL)

/* Button characteristic UUID */
#define BT_UUID_BUTTON_CHAR_VAL \
    BT_UUID_128_ENCODE(0x00001236, 0x0000, 0x1000, 0x8000, 0x00805f9b34fb)
#define BT_UUID_BUTTON_CHAR BT_UUID_DECLARE_128(BT_UUID_BUTTON_CHAR_VAL)

#define LED0_NODE DT_ALIAS(led0)
#define SW0_NODE  DT_ALIAS(sw0)

static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);

static uint8_t led_state;
static uint8_t button_state;

static ssize_t read_led(struct bt_conn *conn,
                        const struct bt_gatt_attr *attr,
                        void *buf, uint16_t len, uint16_t offset)
{
    return bt_gatt_attr_read(conn, attr, buf, len, offset,
                             &led_state, sizeof(led_state));
}

static ssize_t write_led(struct bt_conn *conn,
                         const struct bt_gatt_attr *attr,
                         const void *buf, uint16_t len,
                         uint16_t offset, uint8_t flags)
{
    if (len != 1) {
        return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
    }

    led_state = *((const uint8_t *)buf);
    gpio_pin_set_dt(&led, led_state ? 1 : 0);

    printk("LED %s\n", led_state ? "ON" : "OFF");

    return len;
}

static ssize_t read_button(struct bt_conn *conn,
                           const struct bt_gatt_attr *attr,
                           void *buf, uint16_t len, uint16_t offset)
{
    button_state = gpio_pin_get_dt(&button);
    return bt_gatt_attr_read(conn, attr, buf, len, offset,
                             &button_state, sizeof(button_state));
}

BT_GATT_SERVICE_DEFINE(led_service,
    BT_GATT_PRIMARY_SERVICE(BT_UUID_LED_SERVICE),

    BT_GATT_CHARACTERISTIC(BT_UUID_LED_CHAR,
        BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
        BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
        read_led, write_led, NULL),

    BT_GATT_CHARACTERISTIC(BT_UUID_BUTTON_CHAR,
        BT_GATT_CHRC_READ,
        BT_GATT_PERM_READ,
        read_button, NULL, NULL),
);

static const struct bt_data ad[] = {
    BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),
    BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME,
            sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};

static const struct bt_data sd[] = {
    BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_LED_SERVICE_VAL),
};

int main(void)
{
    int err;

    if (!gpio_is_ready_dt(&led) || !gpio_is_ready_dt(&button)) {
        printk("GPIO devices not ready\n");
        return 0;
    }

    gpio_pin_configure_dt(&led, GPIO_OUTPUT_INACTIVE);
    gpio_pin_configure_dt(&button, GPIO_INPUT);

    err = bt_enable(NULL);
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
        return 0;
    }

    printk("Bluetooth initialized\n");

    err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
                          sd, ARRAY_SIZE(sd));
    if (err) {
        printk("Advertising failed to start (err %d)\n", err);
        return 0;
    }

    printk("Advertising as '%s'\n", CONFIG_BT_DEVICE_NAME);

    return 0;
}

یہ بہت تھوڑا سا کوڈ ہے، تو آئیے اس کو سیکشن کے لحاظ سے دیکھیں۔

اوپر دی گئی UUID تعریف سروس اور اس کی دو خصوصیات کے لیے ایک حسب ضرورت 128 بٹ UUID تیار کرتی ہے۔ اپنی مرضی کے مطابق BLE ڈیوائس بناتے وقت، معیاری بلوٹوتھ SIG UUID استعمال کرنے کے بجائے اپنا UUID بنائیں (جب تک کہ آپ ایک معیاری پروفائل جیسے دل کی دھڑکن کو نافذ نہ کر رہے ہوں)۔

پیداوار میں، ہم بے ترتیب 128 بٹ UUIDs بنانے کے لیے درج ذیل ٹولز کا استعمال کرتے ہیں: uuidgen. یہاں UUID پڑھنے کے قابل ہے۔ کہ BT_UUID_128_ENCODE میکرو UUID کو بائٹ آرڈر میں فارمیٹ کرتا ہے جس کی بلوٹوتھ اسٹیک کی توقع ہے۔ BT_UUID_DECLARE_128 نسل struct bt_uuid_128 انکوڈ شدہ قدر سے

کہ led اور button GPIO تفصیلات ڈیوائس ٹری عرفی ناموں کا استعمال کرتی ہیں۔ led0 اور sw0زیادہ تر زیفیر بورڈز یہی بیان کرتے ہیں۔ کہ GPIO_DT_SPEC_GET آپ کے کوڈ کو تمام بورڈز پر پورٹیبل رکھتے ہوئے، میکروس آلہ کے درخت سے براہ راست پن نمبرز، GPIO کنٹرولرز، اور جھنڈے کھینچتے ہیں۔

کہ read_led کال بیک اس وقت بلایا جاتا ہے جب منسلک مرکزی آلہ LED کی خصوصیات کو پڑھتا ہے۔ یہ استعمال کرتا ہے bt_gatt_attr_readآفسیٹ اور لمبائی کو درست طریقے سے ہینڈل کرنے کے لیے مددگار فنکشن (اگر قدر MTU سے زیادہ ہے تو GATT ریڈز جزوی ہو سکتے ہیں)۔ یہ فنکشن موجودہ LED حالت کو ایک بائٹ کے طور پر لوٹاتا ہے۔

کہ write_led کال بیک اس وقت کہا جاتا ہے جب مرکزی طور پر ایل ای ڈی فیچر پر لکھا جاتا ہے۔ تصدیق کریں کہ بالکل 1 بائٹ لکھا گیا تھا۔ led_state متغیرات اور کالز gpio_pin_set_dt جسمانی طور پر ایل ای ڈی کو سوئچ کرتا ہے۔ استعمال شدہ بائٹس کی تعداد لوٹاتا ہے (len) یا اگر لمبائی غلط ہے تو آپ کو GATT کی خرابی ملے گی۔ کہ BT_GATT_ERR میکرو ATT ایرر کوڈ کو اسٹیک سے متوقع واپسی کی قیمت میں لپیٹ دیتا ہے۔

کہ read_button کال بیک پڑھنے کی درخواست کے وقت موجودہ فزیکل بٹن کی حالت کو پڑھتا ہے۔ یہ کال کرتا ہے gpio_pin_get_dt پن کے نمونے، نتائج کو ذخیرہ کرتا ہے، اور واپسی کرتا ہے۔

کہ BT_GATT_SERVICE_DEFINE میکرو وہ جگہ ہے جہاں کمپائل کے وقت GATT ڈیٹا بیس بنایا جاتا ہے۔ پہلی دلیل سروس متغیر کے نام کی وضاحت کرتی ہے۔ BT_GATT_PRIMARY_SERVICE اپنی مرضی کے مطابق UUID کے ساتھ ڈیفالٹ سروس کا اعلان کریں۔ ہر ایک BT_GATT_CHARACTERISTIC اعلامیہ میں اوصاف UUID، خصوصیات (LEDs کے لیے پڑھنا + لکھنا، بٹنوں کے لیے صرف پڑھنے)، اجازت (جو پڑھ/لکھ سکتا ہے)، ریڈ کال بیک، رائٹ کال بیک، اور صارف کے ڈیٹا کی طرف اشارہ (یہاں دونوں صورتوں میں NULL) شامل ہیں۔

کہ ad صف میں اشتہاری ڈیٹا (جھنڈے اور ڈیوائس کا نام) شامل ہے۔ کہ sd صف میں 128 بٹ سروس UUID ہے، جو کہ اسکین جوابی ڈیٹا ہے۔

سخت 31 بائٹ اشتہاری پیکٹ کی حد کی وجہ سے، ڈیٹا کو اشتہارات اور اسکین جوابات کے درمیان تقسیم کرنا عام ہے۔ چونکہ سروس UUID اکیلے 16 بائٹس ہے، اس لیے مرکزی اشتہار کے پیکٹ میں دیگر ڈیٹا کے لیے بہت کم گنجائش باقی ہے۔ اسکین کے جواب میں UUID ڈالنے سے اشتہاری پیکٹ چھوٹا رہتا ہے اور UUID صرف اس صورت میں شامل ہوتا ہے جب اسکینر کی طرف سے واضح طور پر درخواست کی جائے۔

کہ bt_le_adv_start کرنسی کا مقصد BT_LE_ADV_CONN اس کے بجائے BT_LE_ADV_NCONN. یہ آپ کو اپنے اشتہارات کو لنک کرنے کی اجازت دے گا۔ سکینر اب آپ کے آلے سے جڑ سکتا ہے۔ کہ sd اور ARRAY_SIZE(sd) دلیل اسکین جوابی ڈیٹا فراہم کرتی ہے، جو بیکن مثال میں NULL تھا۔

تعمیر، فلیش اور ٹیسٹ:

cd ~/zephyrproject
west build -b nrf52840dk/nrf52840 ~/my_ble_apps/led_service
west flash

بلڈ کمانڈ پورے بلوٹوتھ اسٹیک، GPIO ڈرائیور، اور GATT ڈیٹا بیس کو ایک ہی بائنری میں مربوط کرکے ایک ایپلیکیشن مرتب کرتی ہے۔ فلیش کمانڈ اسے بورڈ میں پروگرام کرتی ہے۔ کیونکہ CONFIG_BT_PERIPHERAL چالو ہونے پر، بائنری ایک بیکن سے بہت بڑی ہوتی ہے (اس میں تمام قابل رسائی اشتہارات، GATT سرورز، اور ATT پروٹوکول کی پرتیں ہوتی ہیں)۔

اپنے فون پر nRF کنیکٹ کھولیں اور "Zepyr LED” تلاش کرنے کے لیے اسکین کریں۔ جڑیں پر ٹیپ کریں۔ جب آپ جڑیں گے، آپ کو GATT سروسز نظر آئیں گی۔ اپنی کسٹم سروس تلاش کریں (00001234 سے شروع ہونے والا UUID)۔ دو خصوصیات دیکھی جا سکتی ہیں۔ بٹن کی حالت دیکھنے کے لیے، بٹن کی خصوصیات پڑھیں۔ اگر آپ LED کی خصوصیت میں 0x01 لکھتے ہیں، تو LED آن ہو جاتی ہے، اور اگر آپ 0x00 لکھتے ہیں، تو یہ بند ہو جاتا ہے۔ میں نے ابھی اپنے فون سے بلوٹوتھ کے ذریعے ہارڈ ویئر کو کنٹرول کیا۔

کنکشن اور کنکشن کال بیکس کو ہینڈل کرنا

حقیقی دنیا کی ایپلی کیشنز میں، آپ کو یہ جاننے کی ضرورت ہے کہ ڈیوائسز کب منسلک اور منقطع ہوتی ہیں۔ آپ اشتہارات کو بند کر سکتے ہیں جب کوئی آلہ منسلک ہوتا ہے (بجلی بچانے کے لیے)، منقطع ہونے پر اشتہارات دوبارہ شروع کر سکتے ہیں (دوبارہ کنکشن کی اجازت دینے کے لیے)، یا کنکشن کی حیثیت کی نشاندہی کرنے کے لیے اسٹیٹس LED کو اپ ڈیٹ کر سکتے ہیں۔

Zephyr رجسٹریشن میکانزم کے ذریعے کنکشن کال بیکس فراہم کرتا ہے۔

#include 

static void connected(struct bt_conn *conn, uint8_t err)
{
    if (err) {
        printk("Connection failed (err %u)\n", err);
        return;
    }

    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    printk("Connected: %s\n", addr);
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    printk("Disconnected: %s (reason %u)\n", addr, reason);

    /* Restart advertising after disconnect */
    bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
                    sd, ARRAY_SIZE(sd));
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
    .connected = connected,
    .disconnected = disconnected,
};

کہ BT_CONN_CB_DEFINE میکرو مستحکم طور پر کنکشن کال بیکس کی ایک سیریز کو رجسٹر کرتا ہے۔ کہ .connected کنکشن قائم ہوجانے کے بعد کال بیک کو عمل میں لایا جاتا ہے۔ کہ err پیرامیٹر بتاتا ہے کہ کنکشن کامیاب تھا یا نہیں۔ 0 کا مطلب ہے کامیابی۔ کہ .disconnected کنکشن بند ہونے پر کال بیک کی جاتی ہے۔ کہ reason پیرامیٹر HCI منقطع ہونے کی وجہ کوڈ ہے (0x13 "ریموٹ یوزر کنکشن ختم” ہے، یعنی عام منقطع ہونا)۔

پر connected کال بیک میں، کوڈ ریموٹ ڈیوائس کے بلوٹوتھ ایڈریس کو استعمال کرتے ہوئے بازیافت کرتا ہے: bt_conn_get_dst اور اسے پرنٹ ایبل سٹرنگ میں تبدیل کریں۔ یہ لاگنگ اور ڈیبگنگ کے لیے مفید ہے۔

پر disconnected جب آپ واپس کال کریں گے تو آپ کا کوڈ دوبارہ تشہیر شروع کر دے گا۔ پہلے سے طے شدہ طور پر، کنکشن قائم ہونے کے بعد Zephyr اشتہارات بند کر دیتا ہے (چونکہ کنکشن اب وائرلیس استعمال کرتا ہے)۔ اگر کنکشن کھو جاتا ہے، تو یہ عام طور پر اشتہار کو دوبارہ شروع کرنے کی کوشش کرے گا تاکہ یہ آلہ کو دوبارہ دریافت کر سکے۔

کہ bt_conn ایک پوائنٹر کنکشن کی نشاندہی کرتا ہے۔ آپ اسے کنکشن کے پیرامیٹرز سے استفسار کرنے، پیرامیٹر اپ ڈیٹس کی درخواست کرنے، اور جوڑا بنانے یا پروگرام کے مطابق کنکشن کو منقطع کرنے کے لیے استعمال کر سکتے ہیں۔ اس کا حوالہ رکھیں (استعمال کریں۔ bt_conn_ref) اگر آپ کو اسے کال بیک کے باہر استعمال کرنے کی ضرورت ہے۔ حوالہ جاری کریں (استعمال کریں۔ bt_conn_unrefایک بار مکمل

تحریری معاونت شامل کی گئی: فون سے ڈیٹا وصول کریں۔

ایل ای ڈی سروس میں پہلے سے ہی تحریری وصف موجود ہے، لیکن آئیے رائٹ کال بیک پیٹرن اور یہ مزید پیچیدہ ڈیٹا کو کیسے ہینڈل کرتی ہے اس پر گہری نظر ڈالیں۔

ایک ایسے منظر نامے پر غور کریں جہاں فون کسی ڈیوائس کو کنفیگریشن ڈھانچہ بھیجتا ہے۔

struct device_config {
    uint8_t mode;
    uint16_t interval_ms;
    uint8_t threshold;
} __packed;

static struct device_config current_config = {
    .mode = 0,
    .interval_ms = 1000,
    .threshold = 50,
};

static ssize_t write_config(struct bt_conn *conn,
                            const struct bt_gatt_attr *attr,
                            const void *buf, uint16_t len,
                            uint16_t offset, uint8_t flags)
{
    if (offset != 0) {
        return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
    }

    if (len != sizeof(struct device_config)) {
        return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
    }

    memcpy(¤t_config, buf, len);

    printk("Config updated: mode=%u, interval=%u ms, threshold=%u\n",
           current_config.mode,
           current_config.interval_ms,
           current_config.threshold);

    return len;
}

static ssize_t read_config(struct bt_conn *conn,
                           const struct bt_gatt_attr *attr,
                           void *buf, uint16_t len, uint16_t offset)
{
    return bt_gatt_attr_read(conn, attr, buf, len, offset,
                             ¤t_config, sizeof(current_config));
}

کہ __packed ڈھانچے کی خصوصیات اس بات کو یقینی بناتی ہیں کہ فیلڈز کے درمیان کوئی پیڈنگ نہیں ہے، لہذا بائٹ لے آؤٹ اس سے میل کھاتا ہے جو فون بھیج رہا ہے۔ بغیر __packedکمپائلر درمیان میں پیڈنگ بائٹس ڈال سکتا ہے۔ mode اور interval_ms چھانٹنے کے لیے ڈیٹا مماثل نہیں ہے۔

رائٹ کال بیک دو چیزوں کی تصدیق کرتا ہے: پہلے ہم چیک کرتے ہیں کہ آیا آفسیٹ 0 ہے (اس سادہ کیس میں کوئی جزوی تحریر نہیں ہے)۔ دوسرا، چیک کریں کہ لمبائی متوقع ساخت کے سائز سے ملتی ہے۔ اگر یا تو چیک ناکام ہو جاتا ہے، تو مرکزی آلہ ایک GATT ایرر کوڈ واپس کرتا ہے، جو اسے تحریری جواب کی غلطی کے طور پر موصول ہوتا ہے۔

BLE ایپلیکیشنز میں ان پٹ کی توثیق بہت اہم ہے کیونکہ مرکزی ڈیوائس خام بائٹس کو وائرلیس طریقے سے منتقل کرتی ہے۔ خراب ڈیٹا کو مسترد کر دینا چاہیے، آنکھ بند کر کے قبول نہیں کرنا چاہیے۔

کہ memcpy تصدیق شدہ ڈیٹا کو کنفیگریشن ڈھانچے میں کاپی کریں۔ حقیقی دنیا کی ایپلی کیشنز میں، اس بات کا امکان ہے کہ نئی کنفیگریشنز ڈیوائس کے رویے پر لاگو ہوں گی (سینسر پولنگ کے وقفوں کو تبدیل کرنا، آپریٹنگ طریقوں کو تبدیل کرنا، وغیرہ)۔

کہ flags رائٹ کال بیک کے پیرامیٹرز اس بات کی نشاندہی کرتے ہیں کہ آیا یہ جواب کے ساتھ تحریر ہے (مرکزی اعتراف کی توقع ہے) یا جواب کے بغیر تحریر ہے (فائر اینڈ فرجٹ)۔ آپ چیک کر سکتے ہیں۔ flags & BT_GATT_WRITE_FLAG_CMD دونوں میں فرق کرنا۔ کنفیگریشن ڈیٹا کے لیے، آپ عام طور پر اسے جواب میں لکھنا چاہتے ہیں تاکہ مرکزی طور پر آپ جان سکیں کہ تحریر کامیاب تھی۔

نوٹیفیکیشنز: ڈیٹا کو منسلک آلات پر دھکیلیں۔

ڈیمانڈ پر ڈیٹا پر کارروائیوں کو پڑھیں اور لکھیں۔ تاہم، بہت سے BLE ایپلیکیشنز کو ڈیٹا کو فعال طور پر مرکز تک پہنچانے کے لیے پیری فیرلز کی ضرورت ہوتی ہے۔ دل کی شرح مانیٹر آپ کے فون کا ہر سیکنڈ میں آپ کے دل کی دھڑکن کی درخواست کرنے کا انتظار نہیں کرتا ہے۔ اطلاعات کے ذریعے اقدار کو آگے بڑھائیں۔

کسی خاصیت میں نوٹیفکیشن سپورٹ شامل کرنے کا طریقہ یہاں ہے:

static uint8_t sensor_value;
static bool notifications_enabled;

static void sensor_ccc_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
    notifications_enabled = (value == BT_GATT_CCC_NOTIFY);
    printk("Notifications %s\n", notifications_enabled ? "enabled" : "disabled");
}

static ssize_t read_sensor(struct bt_conn *conn,
                           const struct bt_gatt_attr *attr,
                           void *buf, uint16_t len, uint16_t offset)
{
    return bt_gatt_attr_read(conn, attr, buf, len, offset,
                             &sensor_value, sizeof(sensor_value));
}

BT_GATT_SERVICE_DEFINE(sensor_service,
    BT_GATT_PRIMARY_SERVICE(BT_UUID_LED_SERVICE),

    BT_GATT_CHARACTERISTIC(BT_UUID_LED_CHAR,
        BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
        BT_GATT_PERM_READ,
        read_sensor, NULL, &sensor_value),

    BT_GATT_CCC(sensor_ccc_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
);

موجودہ خصوصیت ہے BT_GATT_CHRC_NOTIFY ایک پراپرٹی جو منسلک مرکزی کو بتاتی ہے کہ یہ پراپرٹی اطلاعات کو سپورٹ کرتی ہے۔

کہ BT_GATT_CCC میکرو ایک کلائنٹ انتساب کنفیگریشن ڈسکرپٹر (CCCD) شامل کرتا ہے۔ کہ sensor_ccc_changed کال بیک اس وقت بلایا جاتا ہے جب CCCD کو مرکزی طور پر لکھ کر کوئی اطلاع فعال یا غیر فعال کر دی جاتی ہے۔ کہ value پیرامیٹرز ہیں۔ BT_GATT_CCC_NOTIFY یہ (0x0001) ہے اگر اطلاع فعال ہے، یا 0 اگر یہ غیر فعال ہے۔

اصل میں ایک اطلاع بھیجنے کے لیے:

void send_sensor_notification(void)
{
    if (!notifications_enabled) {
        return;
    }

    sensor_value = read_actual_sensor();

    int err = bt_gatt_notify(NULL, &sensor_service.attrs[1],
                             &sensor_value, sizeof(sensor_value));
    if (err) {
        printk("Notify failed (err %d)\n", err);
    }
}

کہ bt_gatt_notify یہ خصوصیت ان تمام منسلک مرکزی آلات کو اطلاعات بھیجتی ہے جنہوں نے اس خصوصیت کے لیے اطلاعات کو فعال کیا ہے۔

پہلی دلیل یہ ہے۔ NULL تمام کنکشنز کو مطلع کرنے کے لیے (مخصوص bt_conn صرف ایک کی طرف اشارہ)۔ دوسری دلیل GATT ٹیبل میں ایک خصوصیت کی طرف اشارہ کرتی ہے۔ کہ &sensor_service.attrs[1] پہلی انتساب ویلیو پراپرٹی کی طرف اشارہ کرتا ہے (انڈیکس 0 سروس ڈیکلریشن ہے، انڈیکس 1 انتساب کا اعلان ہے، اس کے بعد ویلیو)۔ تیسرے اور چوتھے دلائل ڈیٹا اور اس کی لمبائی ہیں۔

ایک عام نمونہ یہ ہے کہ اس فنکشن کو ٹائمر یا ٹاسک کیو سے باقاعدہ وقفوں پر کال کرنا ہے۔

void sensor_work_handler(struct k_work *work)
{
    send_sensor_notification();
}

K_WORK_DELAYABLE_DEFINE(sensor_work, sensor_work_handler);

/* In main(), after Bluetooth is initialized and advertising: */
k_work_schedule(&sensor_work, K_SECONDS(1));

/* In the work handler, reschedule for periodic execution: */
void sensor_work_handler(struct k_work *work)
{
    send_sensor_notification();
    k_work_schedule(&sensor_work, K_SECONDS(1));
}

یہ نقطہ نظر موخر کام کی اشیاء کا استعمال کرتا ہے جو ہر سیکنڈ میں دوبارہ ترتیب دی جاتی ہیں۔ ہر بار جب یہ چلتا ہے، یہ سینسر کی اقدار کو پڑھتا ہے اور ایک اطلاع بھیجتا ہے (اگر اطلاعات فعال ہیں)۔ کام کے آئٹمز کال کرنے کے لیے محفوظ ہیں کیونکہ وہ کسی رکاوٹ کے سیاق و سباق کے بجائے سسٹم ورک کیو تھریڈ پر چلتے ہیں۔ bt_gatt_notify اور دیگر بلوٹوتھ APIs۔

ایک مکمل BLE سینسر نوڈ بنانا

اب آئیے ہر چیز کو ایک مکمل ایپلی کیشن میں بنڈل کریں۔ یہ ایک BLE ماحولیاتی سینسر ہے جو درجہ حرارت (نقلی) کو پڑھتا ہے اور اسے پڑھنے اور نوٹیفکیشن سپورٹ کے ساتھ حسب ضرورت GATT سروس کے ذریعے ظاہر کرتا ہے، کنیکٹ اور منقطع کو ہینڈل کرتا ہے، اور اشتہارات کا انتظام کرتا ہے۔

بنانا ~/my_ble_apps/sensor_node/src/main.c:

#include 
#include 
#include 
#include 
#include 
#include 

/* UUIDs */
#define BT_UUID_ENV_SERVICE_VAL \
    BT_UUID_128_ENCODE(0xaabbccdd, 0x0000, 0x1000, 0x8000, 0x00805f9b34fb)
#define BT_UUID_ENV_SERVICE BT_UUID_DECLARE_128(BT_UUID_ENV_SERVICE_VAL)

#define BT_UUID_TEMP_CHAR_VAL \
    BT_UUID_128_ENCODE(0xaabbccdd, 0x0001, 0x1000, 0x8000, 0x00805f9b34fb)
#define BT_UUID_TEMP_CHAR BT_UUID_DECLARE_128(BT_UUID_TEMP_CHAR_VAL)

#define BT_UUID_INTERVAL_CHAR_VAL \
    BT_UUID_128_ENCODE(0xaabbccdd, 0x0002, 0x1000, 0x8000, 0x00805f9b34fb)
#define BT_UUID_INTERVAL_CHAR BT_UUID_DECLARE_128(BT_UUID_INTERVAL_CHAR_VAL)

/* LED for connection status */
#define LED0_NODE DT_ALIAS(led0)
static const struct gpio_dt_spec status_led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

/* Sensor state */
static int16_t temperature_value = 2250;
static uint16_t notify_interval_ms = 1000;
static bool temp_notifications_enabled;
static struct bt_conn *current_conn;

/* Forward declaration */
static void sensor_work_handler(struct k_work *work);
K_WORK_DELAYABLE_DEFINE(sensor_work, sensor_work_handler);

static int16_t simulate_temperature(void)
{
    static int16_t base = 2250;
    base += (k_uptime_get_32() % 11) - 5;
    if (base > 3500) base = 3500;
    if (base < 1000) base = 1000;
    return base;
}

/* GATT callbacks */
static ssize_t read_temperature(struct bt_conn *conn,
                                const struct bt_gatt_attr *attr,
                                void *buf, uint16_t len, uint16_t offset)
{
    temperature_value = simulate_temperature();
    return bt_gatt_attr_read(conn, attr, buf, len, offset,
                             &temperature_value, sizeof(temperature_value));
}

static void temp_ccc_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
    temp_notifications_enabled = (value == BT_GATT_CCC_NOTIFY);
    printk("Temperature notifications %s\n",
           temp_notifications_enabled ? "enabled" : "disabled");

    if (temp_notifications_enabled) {
        k_work_schedule(&sensor_work, K_MSEC(notify_interval_ms));
    } else {
        k_work_cancel_delayable(&sensor_work);
    }
}

static ssize_t read_interval(struct bt_conn *conn,
                             const struct bt_gatt_attr *attr,
                             void *buf, uint16_t len, uint16_t offset)
{
    return bt_gatt_attr_read(conn, attr, buf, len, offset,
                             &notify_interval_ms, sizeof(notify_interval_ms));
}

static ssize_t write_interval(struct bt_conn *conn,
                              const struct bt_gatt_attr *attr,
                              const void *buf, uint16_t len,
                              uint16_t offset, uint8_t flags)
{
    if (len != sizeof(uint16_t)) {
        return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
    }

    uint16_t new_interval = *((const uint16_t *)buf);

    if (new_interval < 100 || new_interval > 60000) {
        return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
    }

    notify_interval_ms = new_interval;
    printk("Notification interval changed to %u ms\n", notify_interval_ms);

    if (temp_notifications_enabled) {
        k_work_cancel_delayable(&sensor_work);
        k_work_schedule(&sensor_work, K_MSEC(notify_interval_ms));
    }

    return len;
}

/* GATT service definition */
BT_GATT_SERVICE_DEFINE(env_service,
    BT_GATT_PRIMARY_SERVICE(BT_UUID_ENV_SERVICE),

    BT_GATT_CHARACTERISTIC(BT_UUID_TEMP_CHAR,
        BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
        BT_GATT_PERM_READ,
        read_temperature, NULL, NULL),
    BT_GATT_CCC(temp_ccc_changed,
        BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),

    BT_GATT_CHARACTERISTIC(BT_UUID_INTERVAL_CHAR,
        BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
        BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
        read_interval, write_interval, NULL),
);

/* Notification sender */
static void sensor_work_handler(struct k_work *work)
{
    temperature_value = simulate_temperature();

    if (temp_notifications_enabled) {
        int err = bt_gatt_notify(NULL, &env_service.attrs[2],
                                 &temperature_value,
                                 sizeof(temperature_value));
        if (err && err != -ENOTCONN) {
            printk("Notify error: %d\n", err);
        }

        k_work_schedule(&sensor_work, K_MSEC(notify_interval_ms));
    }
}

/* Advertising data */
static const struct bt_data ad[] = {
    BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),
    BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME,
            sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};

static const struct bt_data sd[] = {
    BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_ENV_SERVICE_VAL),
};

/* Connection callbacks */
static void connected(struct bt_conn *conn, uint8_t err)
{
    if (err) {
        printk("Connection failed (err %u)\n", err);
        return;
    }

    current_conn = bt_conn_ref(conn);
    gpio_pin_set_dt(&status_led, 1);

    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    printk("Connected: %s\n", addr);
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    printk("Disconnected: %s (reason %u)\n", addr, reason);

    if (current_conn) {
        bt_conn_unref(current_conn);
        current_conn = NULL;
    }

    temp_notifications_enabled = false;
    k_work_cancel_delayable(&sensor_work);
    gpio_pin_set_dt(&status_led, 0);

    bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
    .connected = connected,
    .disconnected = disconnected,
};

int main(void)
{
    int err;

    if (!gpio_is_ready_dt(&status_led)) {
        printk("LED not ready\n");
        return 0;
    }
    gpio_pin_configure_dt(&status_led, GPIO_OUTPUT_INACTIVE);

    err = bt_enable(NULL);
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
        return 0;
    }

    printk("Bluetooth initialized\n");

    err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
                          sd, ARRAY_SIZE(sd));
    if (err) {
        printk("Advertising failed (err %d)\n", err);
        return 0;
    }

    printk("Environmental sensor ready. Advertising as '%s'\n",
           CONFIG_BT_DEVICE_NAME);

    return 0;
}

کہ prj.conf اس درخواست کے لیے:

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Zephyr Sensor"
CONFIG_BT_GATT_DYNAMIC_DB=y
CONFIG_GPIO=y
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

یہ ایپلیکیشن BLE سینسر ڈیوائس کا مکمل لائف سائیکل دکھاتی ہے، لہذا ڈیزائن کا بغور مطالعہ کریں۔

یہ سروس دو خصوصیات کو ظاہر کرتی ہے: درجہ حرارت کی خصوصیات پڑھنے اور اطلاع دینے میں معاونت کرتی ہیں۔ جب مرکزی آلہ اسے پڑھتا ہے، تو اسے تازہ ترین نقلی درجہ حرارت ملتا ہے۔ ایک بار جب آپ سنٹرل ڈیوائس پر نوٹیفیکیشنز کو فعال کر دیتے ہیں، تو ڈیوائس قابل ترتیب وقفوں پر درجہ حرارت کی اپ ڈیٹس کو آگے بڑھانا شروع کر دے گی۔

وقفہ کا وصف مرکزی طور پر 100ms اور 60000ms کے درمیان نوٹیفکیشن کے وقفوں کو پڑھنے اور لکھنے کی اجازت دیتا ہے۔ تصدیق ہے۔ write_interval اس حد سے باہر کی اقدار کو مسترد کرتا ہے۔ BT_ATT_ERR_VALUE_NOT_ALLOWEDمرکزی سرور اسے غلطی کے جواب کے طور پر وصول کرتا ہے۔

درجہ حرارت کی قدریں درج ذیل ہیں: int16_t ڈگری سیلسیس کا سوواں حصہ (2250 = 22.50C)۔ یہ فکسڈ پوائنٹ کی نمائندگی بغیر کسی FPU کے مائیکرو کنٹرولرز میں مہنگے فلوٹنگ پوائنٹ آپریشنز سے گریز کرتی ہے اور دو بائٹ ویلیوز کے ساتھ 0.01 ڈگری ریزولوشن فراہم کرتی ہے۔

کنکشن کال بیکس پورے کنکشن لائف سائیکل کا نظم کرتی ہیں۔ منسلک ہونے پر، کوڈ کنکشن آبجیکٹ پر واپس آجاتا ہے (bt_conn_ref) سٹیٹس ایل ای ڈی روشن ہو جاتی ہے۔ اگر کنکشن ختم ہو جائے تو دیکھیں (bt_conn_unref) کسی بھی زیر التواء اطلاعاتی کارروائیوں کو منسوخ کریں، ایل ای ڈی کو بند کریں، اور اشتہارات دوبارہ شروع کریں۔

حوالہ شمار کیوں ضروری ہے۔ bt_conn ایک پوائنٹر صرف اس وقت تک درست ہے جب تک کہ اس کا حوالہ ہو۔ ڈیریفرنس کے بعد اس کا استعمال غیر متعینہ سلوک کا نتیجہ ہوگا۔

نوٹیفکیشن ورک آئٹمز کو ترتیب شدہ وقفوں پر ری شیڈول کیا جاتا ہے، ایک متواتر لوپ بناتا ہے۔ اگر کوئی اطلاع غیر فعال ہے (یا تو واضح طور پر مرکزی کی طرف سے یا واضح طور پر منقطع ہونے سے)، آپریشن منسوخ کر دیا جاتا ہے۔ یہ سی پی یو سائیکل (اور بیٹری) کو ضائع ہونے سے بچائے گا جب کوئی نہیں سن رہا ہے۔

جوڑا بنانا اور سیکیورٹی

پروڈکشن BLE ڈیوائسز کو تقریبا ہمیشہ سیکیورٹی کی ضرورت ہوتی ہے۔ جوڑا بنائے بغیر، وائرلیس رینج میں کوئی بھی ڈیوائس GATT سروس سے منسلک اور اس کے ساتھ تعامل کر سکتی ہے۔ جوڑا بنانا ایک انکرپٹڈ لنک قائم کرتا ہے اور اختیاری طور پر آلات کو ایک دوسرے سے تصدیق کرتا ہے۔

BLE جوڑا بنانے کے کئی طریقوں کی حمایت کرتا ہے۔ "جسٹ ورکس” انکرپشن فراہم کرتا ہے لیکن کوئی تصدیق نہیں۔ یہ غیر فعال قیاس آرائیوں سے بچاتا ہے، لیکن درمیان میں ہونے والے متحرک حملوں سے نہیں۔ "Enter Passkey” کے لیے صارف کو تصدیق کے لیے 6 ہندسوں کا کوڈ درج کرنے کی ضرورت ہوتی ہے۔ "نمبروں کا موازنہ کریں” دونوں آلات پر نمبر دکھاتا ہے اور صارف یہ دیکھنے کے لیے چیک کرتا ہے کہ آیا نمبر مماثل ہیں۔ "آؤٹ آف بینڈ” جوڑی کی معلومات کے تبادلے کے لیے بیرونی چینلز (جیسے NFC) کا استعمال کرتا ہے۔

اپنی سیکیورٹی کو فعال کریں۔ prj.conf:

CONFIG_BT_SMP=y
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y

CONFIG_BT_SMP=y سیکیورٹی مینیجر پروٹوکول کو فعال کرتا ہے جو جوڑا بنانے کا انتظام کرتا ہے۔ سیٹنگز، فلیش، اور NVS آپشنز مستقل اسٹوریج کو فعال کرتے ہیں تاکہ بائنڈنگ انفارمیشن (جوڑی بنانے کے دوران کیز کا تبادلہ) ریبوٹس پر برقرار رہے۔ مستقل اسٹوریج کے بغیر، آلات کو ہر بار سائیکل چلانے پر دوبارہ جوڑا بنانا پڑے گا، جو کہ صارف کا ایک خوفناک تجربہ ہے۔

انتساب کے لیے خفیہ کاری کی ضرورت کے لیے اس کی اجازتوں کو تبدیل کریں۔

BT_GATT_CHARACTERISTIC(BT_UUID_TEMP_CHAR,
    BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
    BT_GATT_PERM_READ_ENCRYPT,
    read_temperature, NULL, NULL),

BT_GATT_PERM_READ_ENCRYPT اس کا مطلب ہے کہ پراپرٹیز کو صرف ایک انکرپٹڈ کنکشن پر پڑھا جا سکتا ہے۔ اگر کوئی مرکزی آلہ پہلے جوڑا بنائے بغیر پڑھنے کی کوشش کرتا ہے، تو اسٹیک خود بخود جوڑی کو متحرک کرتا ہے۔ آپ بھی استعمال کر سکتے ہیں BT_GATT_PERM_READ_AUTHEN تصدیق شدہ جوڑی کی ضرورت ہے (خفیہ چابیاں یا نمبروں کا موازنہ کرنا، نہ کہ صرف کام کرتا ہے)۔

خفیہ کلید کو ظاہر کرنے یا داخل کرنے کے لیے ایک تصدیقی کال بیک کو رجسٹر کریں۔

static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
{
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    printk("Passkey for %s: %06u\n", addr, passkey);
}

static void auth_cancel(struct bt_conn *conn)
{
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    printk("Pairing cancelled: %s\n", addr);
}

static struct bt_conn_auth_cb auth_callbacks = {
    .passkey_display = auth_passkey_display,
    .cancel = auth_cancel,
};

/* In main(), after bt_enable(): */
bt_conn_auth_cb_register(&auth_callbacks);

کہ passkey_display کال بیک اس وقت انجام پاتا ہے جب اسٹیک ایک پاسکی تیار کرتا ہے جسے صارف کو مرکزی طور پر (فون پر) داخل کرنا ہوگا۔ ڈسپلے والے آلات پر، پاس کی سکرین پر ظاہر ہوتی ہے۔ ڈسپلے کے بغیر ڈیوائسز کے لیے (مثلاً سینسر)، آپ ڈیولپمنٹ کے دوران سیریل کنسول پر پرنٹ کرسکتے ہیں یا پروڈکشن میں Just Works پیئرنگ کا استعمال کرسکتے ہیں۔

کہ bt_conn_auth_cb_register فنکشن ان کال بیکس کو اسٹیک پر رجسٹر کرتا ہے۔ ایک وقت میں کال بیکس کا صرف ایک سیٹ فعال ہو سکتا ہے۔

معیاری BLE پروفائل (دل کی شرح) کا نفاذ

اب تک کی مثالوں میں حسب ضرورت 128 بٹ UUID استعمال کیا گیا ہے۔ پیداوار میں، بہت سے BLE آلات بلوٹوتھ SIG کے ذریعہ بیان کردہ معیاری پروفائل کو نافذ کرتے ہیں۔ معیاری پروفائل 16 بٹ UUID استعمال کرتا ہے، اس لیے یہ اشتہاری جگہ کم استعمال کرتا ہے اور عام ایپس (جیسے nRF کنیکٹ) کو ڈیٹا کا خود بخود تجزیہ کرنے اور اسے انسانی پڑھنے کے قابل فارمیٹ میں ڈسپلے کرنے کی اجازت دیتا ہے۔ دل کی شرح کا پروفائل سب سے عام پروفائلز میں سے ایک ہے اور یہ ظاہر کرتا ہے کہ Zephyr میں معیاری پروفائل کیسے کام کرتا ہے۔

دل کی شرح کی خدمت (UUID 0x180D) میں دل کی شرح کی پیمائش کی خصوصیت (UUID 0x2A37) شامل ہے جو اطلاعات کا استعمال کرتے ہوئے دل کی شرح کے ڈیٹا کو آگے بڑھاتی ہے۔ پیمائش کی خصوصیات میں بلوٹوتھ SIG کے ذریعہ بیان کردہ ایک مخصوص بائٹ فارمیٹ ہوتا ہے۔ پہلا بائٹ فلیگ فیلڈ ہے اور بقیہ بائٹس میں ہارٹ ریٹ ویلیو اور اختیاری فیلڈز جیسے کہ توانائی کی کھپت اور RR وقفہ ہوتا ہے۔

#include 
#include 
#include 
#include 
#include 

static uint8_t heart_rate_bpm = 72;
static bool hr_notifications_enabled;

static void hr_ccc_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
    hr_notifications_enabled = (value == BT_GATT_CCC_NOTIFY);
}

static ssize_t read_body_sensor_location(struct bt_conn *conn,
                                         const struct bt_gatt_attr *attr,
                                         void *buf, uint16_t len,
                                         uint16_t offset)
{
    uint8_t location = 0x01; /* Chest */
    return bt_gatt_attr_read(conn, attr, buf, len, offset,
                             &location, sizeof(location));
}

BT_GATT_SERVICE_DEFINE(hr_service,
    BT_GATT_PRIMARY_SERVICE(BT_UUID_HRS),

    BT_GATT_CHARACTERISTIC(BT_UUID_HRS_MEASUREMENT,
        BT_GATT_CHRC_NOTIFY,
        BT_GATT_PERM_NONE,
        NULL, NULL, NULL),
    BT_GATT_CCC(hr_ccc_changed,
        BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),

    BT_GATT_CHARACTERISTIC(BT_UUID_HRS_BODY_SENSOR,
        BT_GATT_CHRC_READ,
        BT_GATT_PERM_READ,
        read_body_sensor_location, NULL, NULL),
);

static void send_heart_rate(void)
{
    if (!hr_notifications_enabled) {
        return;
    }

    uint8_t hr_data[2];
    hr_data[0] = 0x00; /* Flags: uint8 format, no extra fields */
    hr_data[1] = heart_rate_bpm;

    bt_gatt_notify(NULL, &hr_service.attrs[1], hr_data, sizeof(hr_data));
}

یہ کوڈ Zephyr کے پہلے سے طے شدہ UUID میکرو (BT_UUID_HRS، BT_UUID_HRS_MEASUREMENT، BT_UUID_HRS_BODY_SENSOR) اس کے بجائے، حسب ضرورت 128 بٹ UUID استعمال کریں۔ Zephyr تمام معیاری بلوٹوتھ SIG خدمات اور خصوصیات کے لیے میکرو کی وضاحت کرتا ہے۔ zephyr/bluetooth/uuid.h. ان معیاری UUIDs کے استعمال کا مطلب یہ ہے کہ آپ کے فون پر کوئی بھی BLE ہارٹ ریٹ ایپ حسب ضرورت ایپ ڈیولپمنٹ کی ضرورت کے بغیر آپ کے آلے سے ڈیٹا کو خود بخود دریافت، کنیکٹ اور ڈسپلے کر سکتی ہے۔

دل کی شرح کی پیمائش کی خصوصیات میں شامل ہیں: BT_GATT_PERM_NONE اجازت درکار ہے کیونکہ یہ صرف اطلاعات کے لیے ہے۔ پڑھنے یا لکھنے تک رسائی کی اجازت نہیں ہے۔ ڈیٹا صرف اطلاعات کے ذریعے بہتا ہے۔

نوٹیفکیشن پے لوڈ کا پہلا بائٹ (hr_data[0]) ایک فلیگ فیلڈ ہے جس کی وضاحت SIG تفصیلات میں کی گئی ہے۔ 0x00 کی قدر کا مطلب ہے کہ دل کی دھڑکن uint8 فارمیٹ میں ہے (قدریں 0 سے 255 BPM) بغیر کسی سلیکشن فیلڈ کے۔ اگر دل کی دھڑکن 255 سے زیادہ ہو جائے تو بٹ 0 سیٹ کرنا uint16 فارمیٹ میں بدل جاتا ہے۔ کسی دوسرے بٹ کو سیٹ کرنا استعمال شدہ توانائی یا RR وقفہ ڈیٹا کی موجودگی کی نشاندہی کرتا ہے۔

باڈی سینسر لوکیشن انتساب ایک سادہ صرف پڑھنے کی قدر ہے۔ قدر 0x01 کا مطلب ہے "چھاتی”۔ دیگر متعین اقدار میں 0x00 (دیگر)، 0x02 (کلائی)، 0x03 (انگلی)، 0x04 (ہاتھ)، 0x05 (پیارا)، اور 0x06 (پاؤں) شامل ہیں۔

کہ prj.conf معیاری پروفائل ایپلی کیشنز کے لیے، بنیادی بلوٹوتھ پیریفرل سیٹنگز سے آگے کسی خاص ترتیب کی ضرورت نہیں ہے۔

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Zephyr HR"

معیاری UUIDs کو ہمیشہ درج ذیل صورتوں میں استعمال کیا جا سکتا ہے: CONFIG_BT=y یہ مقرر ہے. SIG سے متعین خدمات اور انتساب UUIDs کو استعمال کرنے کے لیے کسی اضافی Kconfig اختیارات کی ضرورت نہیں ہے۔

معیاری پروفائل ڈیوائسز کے لیے اشتہاری ڈیٹا میں عام طور پر اشتہاری پیکٹ میں 16 بٹ سروس UUID شامل ہوتا ہے۔ یہ آپ کے فون کو سروس کی قسم کے لحاظ سے تلاش کو فلٹر کرنے کی اجازت دیتا ہے۔

static const struct bt_data ad[] = {
    BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),
    BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(0x180D)),
    BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME,
            sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};

کہ BT_DATA_UUID16_ALL type 16-bit سروس UUIDs کی مکمل فہرست کا اشتہار دیتا ہے۔ کہ BT_UUID_16_ENCODE(0x180D) میکرو ہارٹ ریٹ سروس UUID کو لٹل اینڈین بائٹ آرڈر میں انکوڈ کرتا ہے۔ ایک 16-بٹ UUID اشتہاری پیکٹ میں صرف 2 بائٹس کا استعمال کرتا ہے (128-بٹ UUID کے لیے 16 بائٹس)، دوسرے اشتہاری ڈیٹا کے لیے بہت زیادہ گنجائش چھوڑتا ہے۔ معیاری پروفائلز استعمال کرنے کا یہ ایک اہم فائدہ ہے۔

BLE سینٹرل کی عمارت

اب تک کی تمام مثالوں نے ایک پیریفرل ڈیوائس (ایک ایسا آلہ جو کنکشن کی تشہیر اور قبول کرتا ہے) بنایا ہے۔ BLE کنکشن کا دوسرا رخ مرکز ہے۔ ایک ایسا آلہ جو قریبی آلات کو دریافت کرتا ہے، کنکشن شروع کرتا ہے، اور ان کی خصوصیات کو پڑھتا اور لکھتا ہے۔ گیٹ ویز، حب، اور ڈیٹا اکٹھا کرنے والے عام طور پر مرکزی ہوتے ہیں۔

Zephyr پر سنٹرل بنانے کے لیے دوسرے بورڈ کی ضرورت ہوتی ہے، لیکن ایک مکمل BLE سسٹم بنانے کے لیے مرکزی کردار کو سمجھنا ضروری ہے۔

کہ prj.conf مرکزی ایپلی کیشنز کے لیے:

CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_SCAN=y
CONFIG_BT_DEVICE_NAME="Zephyr Central"

CONFIG_BT_CENTRAL=y مرکزی کردار کو چالو کرتا ہے (اسکین اور کنکشن شروع کرنا)۔ CONFIG_BT_GATT_CLIENT=y سروس کی دریافت، پڑھنے، لکھنے اور سبسکرائب کرنے کے لیے GATT کلائنٹ API کو فعال کرتا ہے۔ CONFIG_BT_SCAN=y فلٹرنگ اسکین ماڈیولز کو قابل بناتا ہے جو اعلی سطحی اسکیننگ APIs فراہم کرتے ہیں۔

BLE سنٹرل قریبی آلات کی تلاش سے شروع ہوتا ہے۔

#include 
#include 
#include 
#include 
#include 

static struct bt_conn *default_conn;

static void device_found(const bt_addr_le_t *addr, int8_t rssi,
                          uint8_t type, struct net_buf_simple *ad)
{
    char addr_str[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));

    if (rssi < -70) {
        return; /* Skip distant devices */
    }

    printk("Found device: %s (RSSI %d)\n", addr_str, rssi);

    /* Stop scanning before connecting */
    bt_le_scan_stop();

    int err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
                                BT_LE_CONN_PARAM_DEFAULT,
                                &default_conn);
    if (err) {
        printk("Connection failed (err %d)\n", err);
        bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
    }
}

int main(void)
{
    int err;

    err = bt_enable(NULL);
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
        return 0;
    }

    printk("Starting BLE scan...\n");

    err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
    if (err) {
        printk("Scan failed (err %d)\n", err);
        return 0;
    }

    return 0;
}

کہ bt_le_scan_start فنکشن BLE اشتہارات کی تلاش شروع کرتا ہے۔ پہلا دعویٰ یہ ہے کہ BT_LE_SCAN_ACTIVEفعال اسکیننگ کو فعال کریں۔ یعنی، سکینر تلاش کے جواب کا ڈیٹا حاصل کرنے کے لیے مشتہر کو تلاش کی درخواست کا پیکٹ بھیجتا ہے (اسے صرف دستی تلاشیں ملتی ہیں)۔ دوسری دلیل ایک کال بیک فنکشن ہے جسے موصول ہونے والے ہر اشتہاری پیکٹ کے لیے بلایا جائے گا۔

کہ device_found کال بیک مشتہر کا پتہ، RSSI (dBm میں سگنل کی طاقت)، اشتہار کی قسم، اور خام اشتہاری ڈیٹا وصول کرتا ہے۔

اس مثال میں، کوڈ RSSI کے ذریعے فلٹر کرتا ہے، دور دراز کے آلات کو نظر انداز کرتا ہے، اور پھر اسے ملنے والے پہلے آلے سے جڑنے کی کوشش کرتا ہے۔ کہ bt_le_scan_stop ریڈیو ایک ہی وقت میں اسکین اور کنیکٹ نہیں ہو سکتا، اس لیے کنکشن شروع ہونے سے پہلے ایک کال درکار ہے۔

کہ bt_conn_le_create فنکشن کنکشن شروع کرتا ہے۔ منزل کا پتہ، تخلیق کے پیرامیٹرز (جو کنکشن سیٹ اپ کے دوران استعمال ہونے والے سرچ بار کو کنٹرول کرتے ہیں)، کنکشن پیرامیٹرز (وقفہ، انتظار کا وقت، ٹائم آؤٹ)، اور کنکشن کا حوالہ ذخیرہ کرنے کے لیے ایک پوائنٹر کی ضرورت ہوتی ہے۔ BT_LE_CONN_PARAM_DEFAULT ڈیفالٹ کنکشن پیرامیٹرز استعمال کریں جو زیادہ تر ایپلیکیشنز کے لیے موزوں ہوں۔

حقیقی دنیا کی ایپلی کیشنز میں، اسکین کے نتائج کو زیادہ احتیاط سے فلٹر کیا جاتا ہے، عام طور پر مشتہر سروس UUID یا ڈیوائس کا نام چیک کرکے۔ منسلک ہونے کے بعد، یہ GATT سروس کی دریافت کرتا ہے اور پھر صفات کو پڑھتا/لکھتا/سبسکرائب کرتا ہے۔

static uint8_t discover_func(struct bt_conn *conn,
                              const struct bt_gatt_attr *attr,
                              struct bt_gatt_discover_params *params)
{
    if (!attr) {
        printk("Discovery complete\n");
        return BT_GATT_ITER_STOP;
    }

    char uuid_str[BT_UUID_STR_LEN];
    bt_uuid_to_str(params->uuid, uuid_str, sizeof(uuid_str));
    printk("Discovered attribute: handle %u, UUID %s\n",
           attr->handle, uuid_str);

    return BT_GATT_ITER_CONTINUE;
}

static struct bt_gatt_discover_params discover_params;

static void start_discovery(struct bt_conn *conn)
{
    discover_params.uuid = NULL; /* Discover all services */
    discover_params.func = discover_func;
    discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
    discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
    discover_params.type = BT_GATT_DISCOVER_PRIMARY;

    int err = bt_gatt_discover(conn, &discover_params);
    if (err) {
        printk("Discovery failed (err %d)\n", err);
    }
}

کہ bt_gatt_discover فنکشن منسلک پیری فیرلز پر GATT خدمات کی تلاش شروع کرتا ہے۔ کہ discover_params ساخت کنٹرول کرتی ہے جو آپ تلاش کرتے ہیں: ترتیبات uuid NULL پر سیٹ ہونے پر، تمام ڈیفالٹ سروسز کو تلاش کیا جائے گا۔ ماحول type کو BT_GATT_DISCOVER_PRIMARY کلیدی خدمات دریافت کریں۔ آپ اسے اس پر بھی سیٹ کر سکتے ہیں: BT_GATT_DISCOVER_CHARACTERISTIC سروس کے اندر خصوصیات دریافت کریں؛ BT_GATT_DISCOVER_DESCRIPTOR خصوصیات کے اندر وضاحت کنندگان کو دریافت کریں۔

کال بیک تلاش کریں (discover_func) پائی جانے والی ہر جائیداد کے لیے ایک بار کہا جاتا ہے اور ایک بار مزید درج ذیل کے طور پر: attr تلاش مکمل ہونے پر NULL پر سیٹ کریں۔ واپسی کے راستے میں BT_GATT_ITER_CONTINUE اسٹیک کو تلاش جاری رکھنے کو کہتا ہے۔ واپسی کے راستے میں BT_GATT_ITER_STOP تلاش جلد بند کرو۔

سروس اور خصوصیت کی شناخت کے بعد، خصوصیت کی قدر کو استعمال کرتے ہوئے پڑھیں: bt_gatt_read یہ استعمال کرتے ہوئے اطلاعات کو سبسکرائب کریں: bt_gatt_subscribe. سبسکرپشن فنکشن ہے۔ bt_gatt_subscribe_params ایک ایسا ڈھانچہ جو پراپرٹی ہینڈل، نوٹیفکیشن کال بیک فنکشن، اور لکھنے کے لیے CCC ویلیو (BT_GATT_CCC_NOTIFY) کی وضاحت کرتا ہے۔

MTU مذاکرات اور ڈیٹا تھرو پٹ

پہلے سے طے شدہ BLE ATT MTU (زیادہ سے زیادہ ٹرانسمیشن یونٹ) 23 بائٹس ہے۔ اے ٹی ٹی پروٹوکول اوور ہیڈ سے 3 بائٹس کو گھٹانے سے فی GATT آپریشن کے اصل پے لوڈ کے 20 بائٹس رہ جاتے ہیں۔ ایک درجہ حرارت پڑھنے کے لیے، 20 بائٹس کافی ہیں۔ اگر آپ فرم ویئر امیجز یا بڑے سینسر ڈیٹا بفرز کو منتقل کر رہے ہیں تو 20 بائٹس فی آپریشن بہت سست ہے۔

MTU مذاکرات دو منسلک آلات کو 517 بائٹس (BLE زیادہ سے زیادہ) کے بڑے MTU پر متفق ہونے کی اجازت دیتا ہے۔ ایک بڑے MTU کا مطلب ہے فی پیکٹ زیادہ ڈیٹا، کم راؤنڈ ٹرپس، اور زیادہ تھرو پٹ۔ 2M PHY کے ساتھ nRF52840 پر، 23-بائٹ MTU اور 247-byte MTU کے درمیان فرق تھرو پٹ بہتری میں 5x سے 10x تک ہو سکتا ہے۔

ایک بڑا MTU فعال کریں۔ prj.conf:

CONFIG_BT_L2CAP_TX_MTU=247
CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251

CONFIG_BT_L2CAP_TX_MTU=247 زیادہ سے زیادہ ATT MTU سیٹ کرتا ہے جو آلہ گفت و شنید کے دوران درخواست کرے گا۔ قدر 247 عام طور پر استعمال ہوتی ہے کیونکہ یہ زیادہ سے زیادہ سنگل پیکٹ ڈیٹا کی لمبائی سے میل کھاتی ہے (لنک لیئر میں 251 بائٹس L2CAP ہیڈر میں مائنس 4 بائٹس)۔

CONFIG_BT_BUF_ACL_RX_SIZE اور CONFIG_BT_BUF_ACL_TX_SIZE بڑے پیکٹوں کو ایڈجسٹ کرنے کے لیے ACL بفر کا سائز سیٹ کریں۔ CONFIG_BT_CTLR_DATA_LENGTH_MAX کنٹرولر لیول پر ڈیٹا لینتھ ایکسٹینشنز (DLE) کو فعال کریں تاکہ لنک لیئر کو لمبے پیکٹ بھیجنے کی بجائے انہیں 27 بائٹ کے ٹکڑوں میں تقسیم کر سکے۔

کنکشن قائم ہونے کے بعد MTU بات چیت خود بخود ہوتی ہے۔ اگر کنفیگر شدہ MTU ڈیفالٹ سے بڑا ہے تو Zephyr اسٹیک کنکشن پر MTU کی تبادلہ شروع کرتا ہے۔ آپ اسے واضح طور پر بھی متحرک کرسکتے ہیں۔

static void exchange_func(struct bt_conn *conn, uint8_t att_err,
                           struct bt_gatt_exchange_params *params)
{
    if (att_err) {
        printk("MTU exchange failed (err %u)\n", att_err);
        return;
    }

    uint16_t mtu = bt_gatt_get_mtu(conn);
    printk("MTU exchanged: %u bytes\n", mtu);
}

static struct bt_gatt_exchange_params exchange_params = {
    .func = exchange_func,
};

static void connected(struct bt_conn *conn, uint8_t err)
{
    if (err) {
        return;
    }

    bt_gatt_exchange_mtu(conn, &exchange_params);
}

کہ bt_gatt_exchange_mtu فنکشن ریموٹ ڈیوائس پر MTU ایکسچینج کی درخواست بھیجتا ہے۔ کال بیک کو نتیجہ ملتا ہے۔ کامیاب تبادلے کے بعد، bt_gatt_get_mtu بات چیت شدہ MTU لوٹاتا ہے، جو کہ دونوں آلات کے ذریعے تعاون یافتہ کم از کم MTU قدر ہے۔ مؤثر پے لوڈ فی اطلاع یا تحریری آپریشن ATT ہیڈر کا گفت و شنید MTU مائنس 3 بائٹس ہے۔

اطلاعات کے ذریعے بڑی مقدار میں ڈیٹا منتقل کرتے وقت، مؤثر تھرو پٹ تین عوامل پر منحصر ہوتا ہے: MTU (بڑے کا مطلب کم پیکٹ)، کنکشن کا وقفہ (کم کا مطلب ہے ترسیل کے زیادہ مواقع)، اور PHY (2M PHY خام ڈیٹا کی شرح کو 1M PHY کے مقابلے میں دوگنا کرتا ہے)۔

247-بائٹ MTU، 7.5ms لنک وقفہ، اور 2M PHY کے ساتھ، 800kbps سے 1400kbps تک کے تھرو پٹ کو مخصوص کنٹرولر اور ریڈیو حالات کے لحاظ سے حاصل کیا جا سکتا ہے۔

ایک عملی غور: iOS اور Android MTU مذاکرات کو مختلف طریقے سے ہینڈل کرتے ہیں۔ جب کہ اینڈرائیڈ آپ کو ایپ لیئر کے ذریعے ایک مخصوص MTU کی درخواست کرنے کی اجازت دیتا ہے، iOS خود بخود زیادہ سے زیادہ تعاون یافتہ MTU (عام طور پر 185 بائٹس یا 251 بائٹس iOS ورژن پر منحصر ہے) ایپ کی مداخلت کے بغیر بات چیت کرتا ہے۔ فرم ویئر کو کسی خاص قدر کو ماننے کے بجائے ہمیشہ تمام گفت و شنید والے MTUs کو ہینڈل کرنا چاہیے۔

رینج اور رفتار کے لیے PHY کا انتخاب

بلوٹوتھ 5.0 اصل 1M PHY کے علاوہ دو نئی فزیکل لیئر (PHY) آپشنز متعارف کرایا ہے۔ صحیح PHY بیلنس رینج، تھرو پٹ، اور بجلی کی کھپت کا انتخاب کرنا۔

1M PHY یہ پہلے سے طے شدہ اور واحد PHY ہے جو بلوٹوتھ 4.x میں دستیاب ہے۔ معیاری رینج میں 1 میگا بٹ فی سیکنڈ پر منتقل ہوتا ہے۔ تمام BLE آلات 1M PHY کو سپورٹ کرتے ہیں۔

2M PHY ڈیٹا کی رفتار کو 2 میگا بٹس فی سیکنڈ تک دگنا کرتا ہے۔ ہر پیکٹ کی ترسیل میں آدھا وقت لگتا ہے، یعنی ریڈیو کم وقت کے لیے فعال رہتا ہے۔ یہ تھرو پٹ (فی یونٹ وقت میں زیادہ ڈیٹا) اور بجلی کی کھپت (وائرلیس آپریشن کا کم وقت) دونوں کو بہتر بناتا ہے۔ 1M PHY کے مقابلے میں رینج میں معمولی کمی ہے کیونکہ وصول کنندہ کو ہر ایک بٹ کو مربوط کرنے میں کم وقت لگتا ہے۔ 2M PHY استعمال کریں جب مرکزی اور پیریفرل ڈیوائسز ایک دوسرے کے قریب ہوں (چند میٹر کے اندر) اور تھرو پٹ اہم ہو۔

کوڈ شدہ PHY 1M PHY کے مقابلے میں تقریباً 2x سے 4x، حد کو نمایاں طور پر بڑھانے کے لیے فارورڈ غلطی کی اصلاح کا استعمال کیا جاتا ہے۔ یہ بے کار کوڈنگ (S=2 2x رینج کے لیے، S=8 4x رینج کے لیے) کا استعمال کرتے ہوئے ہر بٹ کو منتقل کرکے حاصل کیا جاتا ہے۔ لاگت تھرو پٹ کم ہوتی ہے۔ کوڈڈ PHY S=8 میں 125 kbps کی مؤثر ڈیٹا کی شرح ہے، جو 1M PHY سے 8 گنا کم ہے۔ ایسی ایپلی کیشنز کے لیے کوڈ شدہ PHYs کا استعمال کریں جن کے لیے لمبی دوری کی ضرورت ہوتی ہے (بیرونی اثاثہ جات سے باخبر رہنا، بلڈنگ وائڈ سینسر نیٹ ورک) اور کم ڈیٹا ریٹ برداشت کر سکتے ہیں۔

PHY سپورٹ کو فعال کریں۔ prj.conf:

CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_CTLR_PHY_2M=y
CONFIG_BT_CTLR_PHY_CODED=y

CONFIG_BT_USER_PHY_UPDATE=y کنکشن قائم ہونے کے بعد ایپلیکیشنز کو PHY اپ ڈیٹس کی درخواست کرنے کی اجازت دیتا ہے۔ CONFIG_BT_CTLR_PHY_2M اور CONFIG_BT_CTLR_PHY_CODED کنٹرولر میں ہر PHY کے لیے سپورٹ کو فعال کرتا ہے۔

منسلک ہونے کے بعد، یہ PHY اپ ڈیٹ کی درخواست کرے گا۔

static void connected(struct bt_conn *conn, uint8_t err)
{
    if (err) {
        return;
    }

    /* Request 2M PHY for higher throughput */
    struct bt_conn_le_phy_param phy_param = {
        .options = BT_CONN_LE_PHY_OPT_NONE,
        .pref_tx_phy = BT_GAP_LE_PHY_2M,
        .pref_rx_phy = BT_GAP_LE_PHY_2M,
    };

    int phy_err = bt_conn_le_phy_update(conn, &phy_param);
    if (phy_err) {
        printk("PHY update request failed (err %d)\n", phy_err);
    }
}

کہ bt_conn_le_phy_update فنکشن ریموٹ ڈیوائس کو PHY اپ ڈیٹ کی درخواست بھیجتا ہے۔ کہ pref_tx_phy اور pref_rx_phy فیلڈز بالترتیب ڈیٹا منتقل کرنے اور وصول کرنے کے لیے ترجیحی PHY کی نشاندہی کرتے ہیں۔ ریموٹ ڈیوائس متبادل کو قبول یا تجویز کر سکتی ہے۔ اپ ڈیٹ کے کامیاب ہونے کے لیے، دونوں آلات کو مطلوبہ PHY کو سپورٹ کرنا چاہیے۔

PHY تبدیلیوں کی نگرانی کے لیے کال بیک رجسٹر کریں۔

static void phy_updated(struct bt_conn *conn,
                         struct bt_conn_le_phy_info *param)
{
    printk("PHY updated: TX PHY %u, RX PHY %u\n",
           param->tx_phy, param->rx_phy);
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
    .connected = connected,
    .disconnected = disconnected,
    .le_phy_updated = phy_updated,
};

کہ le_phy_updated جب بھی کنکشن پر PHY تبدیل ہوتا ہے تو کال بیک عمل میں لایا جاتا ہے۔ کہ tx_phy اور rx_phy فیلڈ ہر سمت کے لیے فعال PHY کی رپورٹ کرتا ہے۔ 1 کی قدر کا مطلب ہے 1M PHY، 2 کا مطلب ہے 2M PHY، اور 4 کا مطلب ہے کوڈڈ PHY۔ TX اور RX PHY مختلف ہو سکتے ہیں (غیر متناسب PHY)، لیکن زیادہ تر ایپلی کیشنز دونوں سمتوں میں ایک ہی PHY استعمال کرتی ہیں۔

S=8 انکوڈنگ (زیادہ سے زیادہ رینج) کا استعمال کرتے ہوئے کوڈ شدہ PHY کے لیے، اختیارات کا فیلڈ سیٹ کریں۔

struct bt_conn_le_phy_param phy_param = {
    .options = BT_CONN_LE_PHY_OPT_CODED_S8,
    .pref_tx_phy = BT_GAP_LE_PHY_CODED,
    .pref_rx_phy = BT_GAP_LE_PHY_CODED,
};

کہ BT_CONN_LE_PHY_OPT_CODED_S8 اختیار منتخب کریں S=8 کوڈنگ۔ یہ سب سے کم تھرو پٹ کے ساتھ زیادہ سے زیادہ رینج ایکسٹینشن فراہم کرتا ہے۔ اس اختیار کو چھوڑ دیں یا BT_CONN_LE_PHY_OPT_CODED_S2) S=2 کوڈنگ کا انتخاب کرتا ہے، جو بہتر تھرو پٹ کے ساتھ درمیانی رینج اسکیلنگ فراہم کرتا ہے۔

BLE کے ذریعے فرم ویئر اپ ڈیٹ

کسی بھی پروڈکشن BLE پروڈکٹ کے لیے فیلڈ میں موجود آلات میں فرم ویئر اپ ڈیٹس کی تقسیم ایک اہم کام ہے۔ بگ فکسز اور نئی خصوصیات حاصل کرنے کے لیے صارفین کو USB کیبل لگانے یا سروس سینٹر جانے کی ضرورت نہیں ہے۔

Zephyr ایک محفوظ اوپن سورس بوٹ لوڈر MCUboot کے ساتھ انضمام کے ذریعے BLE پر ڈیوائس فرم ویئر اپ ڈیٹ (DFU) کو سپورٹ کرتا ہے۔

DFU فن تعمیر کے دو اجزاء ہیں: MCUboot ایک بوٹ لوڈر ہے جو ایپلیکیشن سے پہلے چلتا ہے۔ یہ دو فرم ویئر سلاٹس کا انتظام کرتا ہے: فعال سلاٹ (چل رہا فرم ویئر) اور اپ گریڈ سلاٹ (نئے فرم ویئر لاگو ہونے کا انتظار کر رہے ہیں)۔ جب نیا فرم ویئر اپ گریڈ سلاٹ پر لکھا جاتا ہے، MCUboot کرپٹوگرافک دستخط کی تصدیق کرتا ہے، سلاٹ کو تبدیل کرتا ہے، اور نئے فرم ویئر کو بوٹ کرتا ہے۔ اگر نیا فرم ویئر خود تصدیق کرنے میں ناکام ہوجاتا ہے (خود کو درست کے طور پر نشان زد کرتا ہے)، MCUboot خود بخود اگلے ریبوٹ پر پچھلے ورژن پر واپس آجاتا ہے۔

DFU کے لیے BLE ٹرانسپورٹ GATT سروسز پر سادہ مینجمنٹ پروٹوکول (SMP) کا استعمال کرتی ہے۔ mcumgr لائبریری SMP کو نافذ کرتی ہے اور Zephyr میں BLE SMP ٹرانسپورٹ شامل ہے جو SMP GATT سروس کو ظاہر کرتی ہے۔ ایک فون ایپ جیسے nRF Connect یا mcumgr CLI اس سروس سے جڑتی ہے اور نئی فرم ویئر امیجز کو ٹکڑوں میں اپ لوڈ کرتی ہے۔

DFU کو چالو کریں۔ prj.conf:

CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_MCUMGR=y
CONFIG_MCUMGR_TRANSPORT_BT=y
CONFIG_MCUMGR_GRP_IMG=y
CONFIG_MCUMGR_GRP_OS=y
CONFIG_IMG_MANAGER=y
CONFIG_STREAM_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH=y

CONFIG_BOOTLOADER_MCUBOOT=y بلڈ سسٹم کو مطلع کرتا ہے کہ یہ ایپلیکیشن MCUboot کے تحت چلتی ہے، جو لنکر اسکرپٹ اور امیج فارمیٹ کو تبدیل کرتی ہے۔ CONFIG_MCUMGR=y mcumgr مینجمنٹ لائبریری کو چالو کرتا ہے۔ CONFIG_MCUMGR_TRANSPORT_BT=y BLE SMP ٹرانسپورٹ کو فعال کریں، جو ایک GATT سروس بناتا ہے جس سے فون فرم ویئر اپ لوڈ کرنے کے لیے جڑتا ہے۔ CONFIG_MCUMGR_GRP_IMG=y امیج مینجمنٹ کمانڈز کے ایک گروپ کو فعال کرتا ہے (اپ لوڈ، تصدیق، حذف)۔ CONFIG_MCUMGR_GRP_OS=y OS مینجمنٹ گروپ کو فعال کریں (ری سیٹ، ایکو)۔

اپنی درخواست میں BLE SMP ٹرانسمیشن کو رجسٹر کریں۔

#include 

int main(void)
{
    int err;

    err = bt_enable(NULL);
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
        return 0;
    }

    /* Start SMP BLE transport for DFU */
    smp_bt_register();

    /* Start advertising (include SMP service UUID) */
    bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0);

    printk("DFU-capable device ready\n");
    return 0;
}

کہ smp_bt_register() کال بلوٹوتھ اسٹیک کے ساتھ SMP GATT سروس کو رجسٹر کرتی ہے۔ اس کے بعد، کوئی بھی منسلک BLE سنٹرل SMP سروس کو دریافت کرنے اور فرم ویئر اپ لوڈ کرنے کے لیے mcumgr پروٹوکول کا استعمال کر سکتا ہے۔

MCUboot استعمال کرکے بنانے کے لیے، آپ کو پہلے بوٹ لوڈر کو فلیش کرنا ہوگا۔ MCUboot الگ سے بنایا گیا ہے اور فلیش میں بوٹ پارٹیشن میں پروگرام کیا گیا ہے۔

west build -b nrf52840dk/nrf52840 bootloader/mcuboot/boot/zephyr \
    -d build_mcuboot
west flash -d build_mcuboot

west build -b nrf52840dk/nrf52840 my_dfu_app
west flash

پہلی دو کمانڈز MCUboot کی تعمیر اور فلیش کرتی ہیں۔ دوسری دو کمانڈز ایپلی کیشن کو بناتی اور فلیش کرتی ہیں۔ MCUboot فلیش کا پہلا حصہ لیتا ہے اور پرائمری سلاٹ سے ایپلیکیشن کو بوٹ کرتا ہے۔

DFU کو ایپلیکیشن کا نیا ورژن بنانے کی ضرورت ہے۔ zephyr.signed.bin یہ فائل بلڈ ڈائرکٹری میں واقع ہے۔ nRF Connect موبائل ایپ (بٹ ان DFU سپورٹ کے ساتھ) یا mcumgr کمانڈ لائن ٹول کا استعمال کرتے ہوئے فائل کو اپنے آلے پر اپ لوڈ کریں۔ اپ لوڈز BLE SMP کنکشن پر ہوتے ہیں۔ اپ لوڈ مکمل ہونے کے بعد، ڈیوائس دوبارہ شروع ہو جاتی ہے اور MCUboot نئی تصویر کی تصدیق کرتا ہے اور اسے فعال سلاٹ سے بدل دیتا ہے۔

MCUboot کئی پیداواری اہم حفاظتی خصوصیات کو سپورٹ کرتا ہے۔ تصویری دستخط آپ کو صرف فرم ویئر انسٹال کرنے کی اجازت دیتا ہے جس پر آپ کی نجی کلید کے ساتھ دستخط کیے گئے ہیں۔ تصویری خفیہ کاری ٹرانسمیشن کے دوران فرم ویئر امیجز کی ریورس انجینئرنگ کو روکتی ہے۔ اگر نیا ورژن کامیابی سے بوٹ نہیں ہوتا ہے تو، رول بیک پروٹیکشن پچھلے فرم ویئر پر واپس آجاتا ہے۔ ان خصوصیات کے لیے اضافی کنفیگریشن کی ضرورت ہوتی ہے، لیکن یہ کسی بھی پروڈکٹ کے لیے ضروری ہیں جو اوور دی ایئر اپ ڈیٹس کی اجازت دیتی ہے۔

Zephyr’s بلوٹوتھ میش

BLE پوائنٹ ٹو پوائنٹ کنکشن ان آلات کے لیے موزوں ہیں جو فون یا گیٹ وے سے براہ راست بات چیت کرتے ہیں۔ لیکن جب آپ کو کسی عمارت میں سینکڑوں لائٹ بلب کو کنٹرول کرنا پڑتا ہے تو وہ ٹوٹ جاتے ہیں۔ آپ ہر ایک سے انفرادی طور پر جڑ نہیں سکتے۔ بلوٹوتھ میش اس مسئلے کو حل کرتا ہے۔

بلوٹوتھ میش نیٹ ورکنگ کا ایک کئی سے زیادہ معیار ہے جو BLE کے اوپر چلتا ہے۔ میش نیٹ ورک میں موجود آلات ایک دوسرے کو پیغامات بھیجتے ہیں، حد کو ایک BLE کنکشن سے کہیں زیادہ بڑھاتے ہیں۔ لائٹ آن کرنے کا حکم ایک ڈیوائس سے نکل سکتا ہے، متعدد ریلے نوڈس سے گزر کر عمارت میں موجود ہر لائٹ بلب تک پہنچ سکتا ہے۔

Zephyr میں بلوٹوتھ میش کا مکمل نفاذ شامل ہے۔ تصوراتی فن تعمیر اس طرح ہے:

میش آلات کا ایک کردار ہے۔ کوئی راستہ نہیں ریلے نوڈ دوسرے آلات سے پیغامات آگے بھیج کر نیٹ ورک کوریج کو بڑھاتا ہے۔ کوئی راستہ نہیں پراکسی نوڈ یہ GATT سے منسلک آلات (موبائل فونز) اور میش نیٹ ورک کے درمیان پل بناتا ہے، غیر میش سپورٹڈ فونز کو پراکسی کے ذریعے میش ڈیوائسز کو کنٹرول کرنے کی اجازت دیتا ہے۔ کوئی راستہ نہیں دوست نوڈ یہ قریبی کم طاقت والے نوڈس کے لیے پیغامات اسٹور کرتا ہے جو اپنا زیادہ تر وقت سونے میں گزارتے ہیں۔ کوئی راستہ نہیں کم طاقت نوڈ یہ وقتا فوقتا جاگتا ہے اور آپ کے دوستوں سے پوچھتا ہے کہ کیا ان کے پاس آپ کے لیے کوئی محفوظ کردہ پیغامات ہیں۔

میش کمیونیکیشن پبلش/سبسکرائب ماڈل کا استعمال کرتی ہے۔ ایک آلہ کسی ایڈریس پر پیغام بھیجتا ہے، اور اس ایڈریس پر سبسکرائب کیے گئے آلات پیغام وصول کرتے ہیں۔ لائٹ سوئچ گروپ ایڈریس پر ‘آن’ کر دیتا ہے۔ اس گروپ ایڈریس پر سبسکرائب کیے گئے تمام لائٹ بلب آن ہو جائیں گے۔

میش میں ڈیٹا کو استعمال کرتے ہوئے بنایا گیا ہے: ماڈل. ایک ماڈل پیغامات کے سیٹ کی وضاحت کرتا ہے جو آلہ بھیج اور وصول کر سکتا ہے۔ بلوٹوتھ SIG عام استعمال کے معاملات کے لیے معیاری ماڈلز کی وضاحت کرتا ہے۔ جنرل آن آف (آن/آف سوئچ اور لائٹنگ)، جنرل لیول (دھیما)، سینسر (سینسر ڈیٹا) اور لائٹنگ (رنگ کا درجہ حرارت، چمک، ٹنٹ)۔ آپ اپنی مرضی کے ماڈل کی بھی وضاحت کر سکتے ہیں۔

ذیل میں کم سے کم میش نوڈ کنفیگریشن ہے: prj.conf:

CONFIG_BT=y
CONFIG_BT_MESH=y
CONFIG_BT_MESH_RELAY=y
CONFIG_BT_MESH_PB_ADV=y
CONFIG_BT_MESH_PB_GATT=y
CONFIG_BT_MESH_GATT_PROXY=y
CONFIG_BT_MESH_CFG_CLI=y
CONFIG_BT_MESH_HEALTH_SRV=y

CONFIG_BT_MESH=y میش اسٹیک کو چالو کریں۔ CONFIG_BT_MESH_RELAY=y اس نوڈ کو دوسرے نوڈس کے لیے پیغامات بھیجنے کی اجازت دیتا ہے۔ CONFIG_BT_MESH_PB_ADV=y اور CONFIG_BT_MESH_PB_GATT=y اشتہارات اور GATT کنکشن دونوں کے ذریعے فراہمی (میش نیٹ ورک میں آلات کو شامل کرنے کا عمل) کو قابل بناتا ہے۔ CONFIG_BT_MESH_GATT_PROXY=y فون کنکشنز کے لیے پراکسی رول کو فعال کریں۔

ایک مکمل میش ایپلی کیشن میں کنفیگریشن ڈیٹا کی وضاحت کرنا (ڈیوائس کے ذریعے تعاون یافتہ ماڈلز)، ماڈل ہینڈلرز کو نافذ کرنا، اور پروویژننگ ترتیب دینا شامل ہے۔ زیفیر کے نمونوں کی ڈائرکٹری (samples/bluetooth/mesh/) میں کئی مکمل مثالیں شامل ہیں، بشمول ایک لائٹ بلب، لائٹ سوئچ، اور ایک سینسر سرور جو مجموعی پیٹرن کو ظاہر کرتا ہے۔

LE آڈیو: بلوٹوتھ آڈیو کی اگلی نسل

LE آڈیو سالوں میں بلوٹوتھ تفصیلات میں سب سے اہم اضافہ ہے۔ یہ A2DP (کلاسک بلوٹوتھ آڈیو پروفائل) کو BLE پر مبنی ایک نئے سسٹم سے بدل دیتا ہے۔ Zephyr کا LE آڈیو نفاذ کسی بھی اوپن سورس اسٹیک میں سب سے مکمل ہے۔

LE آڈیو کا بنیادی حصہ LC3 (کم کمپلیکسٹی کمیونیکیشن کوڈیک) ہے۔ LC3 کلاسک بلوٹوتھ آڈیو میں استعمال ہونے والے SBC کوڈیک کے مقابلے نصف بٹ ریٹ پر بہتر آڈیو کوالٹی فراہم کرتا ہے۔ اس کا مطلب ہے بہتر آواز کا معیار اور کم بجلی کی کھپت۔

LE آڈیو نے دو مواصلاتی طریقوں کو متعارف کرایا ہے: متصل آئسوکرونس سٹریم (CIS) ایک پوائنٹ ٹو پوائنٹ آڈیو کنکشن کلاسک بلوٹوتھ آڈیو جیسا لیکن زیادہ موثر۔ CIS کا استعمال سیل فون سے ایئربڈ کنکشن، سماعت کے آلات، اور دوسرے جوڑے ہوئے آڈیو منظرناموں کے لیے کیا جاتا ہے۔

براڈکاسٹ آئسوکرونس اسٹریم (BIS) یہ ایک سے زیادہ نشریات ہے۔ ایک واحد ذریعہ آڈیو کو لامحدود تعداد میں ریسیورز پر نشر کر سکتا ہے۔ Auracast کے پیچھے یہ بنیادی ٹیکنالوجی ہے، جو عوامی جگہوں پر آڈیو نشر کرنے کا تصور کرتی ہے جسے کسی بھی مطابقت پذیر ڈیوائس کے ذریعے ٹیون کیا جا سکتا ہے (جیسے ہوائی اڈوں میں خاموش ٹی وی، تھیٹرز میں سماعت کے آلات، کانفرنس رومز میں کثیر لسانی نشریات وغیرہ)۔

Zephyr مکمل LE آڈیو پروفائل اسٹیک کو نافذ کرتا ہے، بشمول بنیادی آڈیو پروفائل (BAP)، شائع شدہ آڈیو کیپبلٹیز (PACS)، آڈیو اسٹریم کنٹرول (ASCS)، والیوم کنٹرول (VCP)، میڈیا کنٹرول (MCP)، کال کنٹرول (CCP)، ٹیلی فون اور میڈیا آڈیو پروفائل (TMAP)، اور کامن آڈیو پروفائل (CAP)۔

کہ prj.conf LE آڈیو پروجیکٹس میں شامل ہیں:

CONFIG_BT=y
CONFIG_BT_AUDIO=y
CONFIG_BT_BAP_UNICAST_SERVER=y
CONFIG_BT_PACS=y
CONFIG_BT_ASCS=y
CONFIG_BT_ISO=y
CONFIG_BT_PAC_SNK=y
CONFIG_BT_PAC_SRC=y

LE آڈیو ڈویلپمنٹ بنیادی BLE پیریفرل ڈویلپمنٹ سے کہیں زیادہ پیچیدہ ہے۔ اس میں isochronous چینلز کا انتظام، کوڈیک پیرامیٹرز کو ترتیب دینا، آڈیو ڈیٹا اسٹریمز پر کارروائی کرنا، اور مختلف پروفائل لیئرز کو نافذ کرنا شامل ہے۔ Zephyr کے نمونے ہیں samples/bluetooth/bap_unicast_server اور samples/bluetooth/bap_broadcast_source یہ بہترین نقطہ آغاز ہے۔

اگر آپ سماعت کے آلات، ایئربڈز، یا دیگر آڈیو ڈیوائسز بناتے ہیں، تو Zephyr’s LE Audio ایک سنجیدہ سرمایہ کاری کے قابل ہے۔ اوپن سورس اسٹیک آپ کے نفاذ میں مکمل مرئیت فراہم کرتا ہے، اور Nordic کے nRF5340 اور nRF54 سیریز کے چپس ضروری ہارڈ ویئر سپورٹ فراہم کرتے ہیں۔

بلوٹوتھ ایپلی کیشنز کو ڈیبگ کرنا

BLE ایپلیکیشنز کو باقاعدہ ایمبیڈڈ ایپلی کیشنز کے مقابلے ڈیبگ کرنا زیادہ مشکل ہے کیونکہ وائرلیس کمیونیکیشنز پوشیدہ ہیں۔ آپ ہوا میں بریک پوائنٹس نہیں لگا سکتے۔ BLE ڈیبگنگ کو قابل انتظام بنانے کے لیے ٹولز اور تکنیکوں میں شامل ہیں:

زیفیر کا لاگنگ سب سسٹم یہ آپ کی دفاع کی پہلی لائن ہے۔ تفصیلی بلوٹوتھ لاگ ان کو فعال کریں۔ prj.conf:

CONFIG_LOG=y
CONFIG_BT_DEBUG_LOG=y
CONFIG_BT_LOG_LEVEL_DBG=4

CONFIG_LOG=y لاگنگ فریم ورک کو چالو کریں۔ CONFIG_BT_DEBUG_LOG=y اور CONFIG_BT_LOG_LEVEL_DBG=4 بلوٹوتھ اسٹیک کے لیے ڈیبگ لیول لاگنگ کو فعال کرتا ہے۔

یہ تمام HCI کمانڈز، اشتہاری ایونٹس، کنکشن ایونٹس، GATT آپریشنز، اور غلطیاں دکھاتے ہوئے تفصیلی آؤٹ پٹ تیار کرتا ہے۔ آؤٹ پٹ کنسول میں جاتا ہے (عام طور پر UART)۔ یہ بہت لفظی ہے، لہذا اسے فعال ڈیبگنگ کے دوران ہی فعال کریں۔

زیفیر شیل بلوٹوتھ کے ساتھ کام کرنے کے لیے ایک انٹرایکٹو کمانڈ لائن فراہم کرتا ہے۔

CONFIG_SHELL=y
CONFIG_BT_SHELL=y

اس کو چالو کرنے سے آپ کو اس طرح کے شیل کمانڈ ملیں گے: bt init، bt advertise on، bt connect، bt gatt discoverاور bt gatt read آپ سیریل کنسول کے ذریعے بلوٹوتھ اسٹیک کو انٹرایکٹو طریقے سے کنٹرول اور معائنہ کر سکتے ہیں۔ یہ جانچ کے لیے بہت اہم ہے کیونکہ یہ آپ کو دستی طور پر کارروائیوں کو متحرک کرنے اور فرم ویئر میں ترمیم کیے بغیر نتائج کو چیک کرنے کی اجازت دیتا ہے۔

موبائل کے لیے nRF کنیکٹ (iOS/Android) ایک ضروری ساتھی ٹول ہے۔ اسکیننگ اور کنیکٹنگ کے علاوہ، یہ تمام GATT خدمات اور خصوصیات کو ظاہر کرتا ہے، خصوصیات کو پڑھ/لکھ سکتا/سبسکرائب کر سکتا ہے، خام اشتہاری ڈیٹا دکھاتا ہے، اور BLE ایونٹس کو ٹائم سٹیمپ کے ساتھ لاگ کرتا ہے۔ اس کا استعمال اس بات کی تصدیق کے لیے کریں کہ آپ کا آلہ درست طریقے سے تشہیر کر رہا ہے، کہ GATT ڈیٹا بیس درست ہے، اور یہ کہ پڑھنا/لکھنا/اطلاعات حسب توقع کام کر رہی ہیں۔

بلوٹوتھ سونگھنے والا حقیقی وائرلیس پیکٹ کیپچر کریں۔ nRF52840 DK کو بلوٹوتھ LE فرم ویئر کے لیے Nordic کے nRF سنففر کے ساتھ سنیفر کے طور پر استعمال کیا جا سکتا ہے۔ جب Wireshark (جس میں BLE پروٹوکول تجزیہ کار ہوتا ہے) کے ساتھ ملایا جاتا ہے، تو آپ تار پر موجود تمام پیکٹوں کا معائنہ کر سکتے ہیں، بشمول PDU اشتہارات، کنکشن کے واقعات، GATT کی درخواست/جواب، اور جوڑی کے تبادلے۔ جب پروٹوکول کی سطح پر کچھ کام نہیں کر رہا ہے تو یہ ڈیبگنگ کا بہترین ٹول ہے۔

عام ڈیبگنگ پیٹرن۔ اگر آپ کو اپنا اشتہار نظر نہیں آتا ہے، تو یقینی بنائیں کہ آپ کے اشتہار کا ڈیٹا 31 بائٹس (روایتی اشتہارات کے لیے) سے زیادہ نہیں ہے اور یہ کہ ایک فلیگ فیلڈ ہے۔

اگر کنکشن فوری طور پر گر جاتا ہے، تو درج ذیل کو چیک کریں: CONFIG_BT_PERIPHERAL فعال ہے (صرف CONFIG_BT_BROADCASTER)۔ اگر آپ کا GATT ریڈ صفر طوالت کا ڈیٹا واپس کرتا ہے، تو یقینی بنائیں کہ آپ کا پڑھا ہوا کال بیک اس میں صحیح قدر لوٹاتا ہے: bt_gatt_attr_read. اگر اطلاع نہیں پہنچتی ہے تو چیک کریں کہ آیا 0x0001 CCCD کو مرکزی طور پر لکھا گیا ہے۔ اگر جوڑا بنانا ناکام ہوجاتا ہے، تو درج ذیل کو چیک کریں: CONFIG_BT_SMP=y یہ سیٹ ہے اور تصدیقی کال بیک رجسٹرڈ ہے۔

BLE آلات کے لیے پاور آپٹیمائزیشن

ایک BLE ڈیوائس جس کی بیٹری صرف ایک ہفتے میں ختم ہو جاتی ہے وہ ٹوٹی ہوئی پروڈکٹ ہے۔ پاور آپٹیمائزیشن ڈیزائن کی ایک اہم رکاوٹ ہے، سوچنے کے بعد نہیں۔ Zephyr ٹولز فراہم کرتا ہے، لیکن آپ کو انہیں صحیح طریقے سے استعمال کرنا ہوگا۔

BLE ڈیوائس میں بجلی کا سب سے بڑا صارف ریڈیو ہے۔ ہر ایڈورٹائزنگ ایونٹ، کنکشن ایونٹ، اور اسکین ونڈو ایک وائرلیس ٹرانسمیٹر یا ریسیور کو ایک وقت میں ملی سیکنڈز کے لیے چالو کرتی ہے، جس میں ملی ایمپ کرنٹ استعمال ہوتا ہے۔ وائرلیس استعمال کو کم کرنا بیٹری کی زندگی کو بڑھانے کا ایک اہم ذریعہ ہے۔

اشتہارات کے لیے، اشتہارات کے درمیان وقفہ بڑھائیں۔ 1000ms کا وقفہ 200ms کے وقفے سے تقریباً 5 گنا کم طاقت استعمال کرتا ہے۔ اگر تیزی سے بازیافت اہم نہیں ہے، تو طویل وقفہ استعمال کریں۔

آپ دو قدمی اپروچ بھی استعمال کر سکتے ہیں۔ یعنی، یہ پاور آن ہونے کے بعد پہلے 30 سیکنڈز کے لیے تیز وقفوں (100 ms) کی تشہیر کرتا ہے، پھر مستحکم حالت کے لیے سست وقفوں (1000 ms) پر سوئچ کرتا ہے۔ Zephyr کا ایڈورٹائزنگ API اشتہارات کے دوران تبدیل کرنے والے پیرامیٹرز کی حمایت کرتا ہے۔

منسلک آلات کے لیے، پیریفرل لیٹنسی پیرامیٹر استعمال کریں۔ 4 کی پیریفرل لیٹینسی کا مطلب ہے کہ پیریفیرل جواب دینے سے پہلے چار کنکشن ایونٹس کو چھوڑ سکتا ہے۔ اگر کنکشن کا وقفہ 50ms ہے اور پیریفرل لیٹنسی 4 ہے، تو پیریفیرل 50ms کے بجائے ہر 250ms پر جاگ جائے گا۔ اگر ہائی تھرو پٹ کی ضرورت نہیں ہے، تو مرکز طویل کنکشن وقفوں کی درخواست کرتا ہے۔

static struct bt_le_conn_param conn_params = {
    .interval_min = 80,   /* 100 ms (units of 1.25 ms) */
    .interval_max = 160,  /* 200 ms */
    .latency = 4,
    .timeout = 400,       /* 4 seconds (units of 10 ms) */
};

/* After connection is established: */
bt_conn_le_param_update(conn, &conn_params);

کہ bt_conn_le_param_update فنکشن مرکز کو کنکشن پیرامیٹرز کو اپ ڈیٹ کرنے کی درخواست بھیجتا ہے۔ مرکزی طور پر، درخواست کو قبول یا مسترد کیا جا سکتا ہے۔ زیادہ تر مرکزی آلات (ٹیلی فون) معقول پیرامیٹر کی حدود کی اجازت دیتے ہیں۔

Zephyr کے سسٹم پاور مینجمنٹ کو فعال کریں۔

CONFIG_PM=y
CONFIG_PM_DEVICE=y

جب پاور مینجمنٹ کو فعال کیا جاتا ہے، تو کرنل پروسیسر کو کم طاقت والی حالت میں رکھتا ہے جب بھی کوئی تھریڈ چلنے کے لیے تیار نہ ہو۔

nRF52840 میں، بیکار کرنٹ تقریباً 3 mA (فعال) سے تقریباً 1.5 μA (RAM برقرار رکھنے کے ساتھ سسٹم آف) تک گر جاتا ہے۔ فرق بہت بڑا ہے۔ Zephyr پاور مینجمنٹ کی پالیسیاں خود بخود گہری نیند کی اس حالت کا انتخاب کرتی ہیں جس میں نظام اگلے طے شدہ ویک ایونٹ کی بنیاد پر داخل ہو سکتا ہے۔

ڈیوائس ٹری اوورلے میں غیر استعمال شدہ پیری فیرلز کو غیر فعال کریں۔ تمام فعال پیری فیرلز (UART، SPI، I2C) بیکار ہونے پر بھی بجلی استعمال کرتے ہیں۔ اگر پیداوار میں UART کی ضرورت نہیں ہے (صرف ترقیاتی لاگنگ کے لیے استعمال کیا جاتا ہے)، UART کو غیر فعال کریں۔

&uart0 {
    status = "disabled";
};

اصل موجودہ کھپت کی پیمائش کریں۔ نورڈک پاور پروفائلر کٹ II جیسے ٹولز مائیکرو امپ ریزولوشن پر ریئل ٹائم کرنٹ ڈرا دکھاتے ہیں۔ Zephyr کی CONFIG_THREAD_ANALYZER یہ دھاگے کے اسٹیک کو مناسب طریقے سے سائز کرنے میں مدد کرتا ہے (زیادہ سے زیادہ مختص اسٹیک RAM کو ضائع کرتا ہے، یعنی زیادہ RAM کو چلانے کی ضرورت ہے)۔

ایک اچھی طرح سے بہتر بنائے گئے BLE سینسر کا مقصد سنگل ہندسہ مائیکرو ایمپ اوسط کرنٹ ہے۔ اس کا مطلب یہ ہے کہ یہ کوائن سیل بیٹری پر برسوں تک چل سکتا ہے۔ Zephyr آپ کو یہ حاصل کرنے کی اجازت دیتا ہے، لیکن تمام پرتوں پر توجہ کی ضرورت ہے: ریڈیو شیڈولنگ، پیریفرل مینجمنٹ، گھڑی کی ترتیب، اور ایپلیکیشن ڈیزائن۔

Zephyr بلوٹوتھ اور دیگر اسٹیک

بلوٹوتھ اسٹیک کا انتخاب کرتے وقت آپ کے پاس اختیارات ہوتے ہیں۔ Zephyr کا موازنہ یہاں ہے:

1. زیفیر بمقابلہ نورڈک سافٹ ڈیوائس

Nordic’s SoftDevice Zephyr میں جانے سے پہلے ایک ملکیتی BLE اسٹیک تھا۔ SoftDevices پہلے سے مرتب شدہ بائنری بلابز ہیں، اس لیے ان کے اسٹیک کوڈ کو پڑھا یا تبدیل نہیں کیا جا سکتا۔ Nordic کا nRF Connect SDK (Zephyr پر مبنی) SoftDevice کو Zephyr کے اوپن سورس اسٹیک سے بدل دیتا ہے۔ اگر آپ ایک نیا نورڈک پروجیکٹ شروع کر رہے ہیں، تو Zephyr کو آزمائیں۔ SoftDevice میراث ہے۔

Zephyr بمقابلہ NimBLE (Apache Mynewt)

NimBLE ایک ہلکا پھلکا، اوپن سورس BLE ہوسٹ اسٹیک ہے جو اصل میں Apache Mynewt پروجیکٹ سے ہے (اسٹینڈ تنہا اور ESP-IDF کے لیے پورٹیبل بھی دستیاب ہے)۔ NimBLE Zephyr کے اسٹیک سے چھوٹا ہے اور انتہائی محدود RAM والے آلات کے لیے بہتر ہو سکتا ہے۔ Zephyr کا اسٹیک زیادہ خصوصیت سے بھرپور ہے (LE آڈیو، میش، ڈائریکشن فائنڈنگ) اور اس میں وسیع تر صنعت کو اپنایا گیا ہے۔ ایک نئی پروڈکٹ کے لیے، Zephyr ایک زیادہ طاقتور انتخاب ہے جب تک کہ آپ RAM کے ذریعے سختی سے محدود نہ ہوں۔

Zephyr بمقابلہ ESP-IDF بلوٹوتھ

Espressif کے ESP-IDF میں ESP32 چپ کے لیے بلوٹوتھ اسٹیک (Bluedroid یا NimBLE) شامل ہے۔ اگر آپ صرف ESP32 ہارڈویئر استعمال کرتے ہیں تو ESP-IDF ایک درست انتخاب ہے۔ Zephyr ESP32 کو سپورٹ کرتا ہے اور دوسرے ہارڈ ویئر، ایک مربوط بلڈ سسٹم، اور ایک زیادہ جامع BLE فیچر سیٹ کو پورٹیبلٹی پیش کرتا ہے۔ اگر آپ کو کبھی چپ کو تبدیل کرنے کی ضرورت ہو تو Zephyr کی پورٹیبلٹی ایک اہم فائدہ ہے۔

ملکیتی اسٹیک کے ساتھ Zephyr اور وینڈر SDKs

بہت سے چپ فروش اپنے BLE SDKs کو بند سورس اسٹیک کے ساتھ فراہم کرتے ہیں۔ یہ اچھی طرح سے کام کرتا ہے، لیکن آپ اس وینڈر کے ماحولیاتی نظام میں بند ہیں۔ Zephyr پورٹیبلٹی، اوپن سورس، اور ایک بڑی کمیونٹی کی باہمی تعاون پیش کرتا ہے۔ ٹریڈ آف یہ ہے کہ سیکھنے کا منحنی خطوط زیادہ تیز ہے۔

ایک معروف چپ کا استعمال کرتے ہوئے جن پروڈکٹس کو شیڈول کے مطابق جاری کرنے کی ضرورت ہے، ایک وینڈر SDK شروع کرنے کے لیے تیز تر ہو سکتا ہے۔ پروڈکٹ لائنوں کے لیے جو ایک سے زیادہ چپس پر محیط ہیں یا طویل مدتی برقرار رکھنے کی قدر کرتی ہیں، Zephyr جیتتا ہے۔

میں یہاں سے کہاں جاؤں؟

ہم نے اس ہینڈ بک میں بہت کچھ شامل کیا ہے۔ اب آپ کو BLE کی بنیادی باتیں، GAP ایڈورٹائزنگ، GATT سروسز، کنیکٹیویٹی، نوٹیفیکیشنز، پیئرنگ، میش، LE آڈیو، ڈیبگنگ، اور پاور آپٹیمائزیشن کو سمجھنا چاہیے۔ میں نے تمام کلیدی تصورات کے لیے کوڈ لکھا۔ جاری رکھنے کا طریقہ یہاں ہے:

Zephyr بلوٹوتھ نمونہ ڈائرکٹری (zephyr/samples/bluetooth/)۔ اس میں بلوٹوتھ سے متعلق 30 سے ​​زیادہ مثالیں ہیں۔ کہ peripheral_hr نمونے میں دل کی شرح کی مکمل پروفائل موجود ہے۔ کہ central نمونہ دکھاتا ہے کہ اسکیننگ/کنکشن مرکوز کردار کیسے بنایا جائے۔ کہ mesh/ ذیلی ڈائرکٹری میں میش ڈیولپمنٹ کے لیے لائٹ سوئچز، لائٹ بلب اور سینسر کی مثالیں شامل ہیں۔ کہ bap_* نمونہ LE آڈیو کو ظاہر کرتا ہے۔

Zephyr بلوٹوتھ دستاویزات پڑھیں۔ docs.zephyrproject.org/latest/connectivity/bluetooth/. API حوالہ تمام فنکشنز، میکروز اور کنفیگریشن کے اختیارات کا احاطہ کرتا ہے۔ بلوٹوتھ فن تعمیر کی دستاویز بیان کرتی ہے کہ میزبان، کنٹرولر، اور HCI پرتیں کس طرح تعامل کرتی ہیں۔

اگر آپ نورڈک ہارڈویئر استعمال کرتے ہیں، تو nRF Connect SDK سیٹ اپ حاصل کریں۔ nRF Connect SDK Zephyr کے اوپر نورڈک مخصوص خصوصیات شامل کرتا ہے، بشمول بلوٹوتھ لائبریری، ملکیتی وائرلیس پروٹوکول (ESB، Gazell)، اور سیلولر موڈیم سپورٹ۔ یہ وہی Zephyr کرنل اور بلڈ سسٹم استعمال کرتا ہے۔

اسے حقیقی بنائیں۔ یہ ڈیسک لیمپ کے لیے BLE ریموٹ کنٹرول ہے۔ یہ ایک ایسا سینسر ہے جو آپ کے موبائل فون پر اندرونی درجہ حرارت اور نمی کی اطلاع دیتا ہے۔ BLE کنیکٹوٹی کے ساتھ حسب ضرورت کی بورڈ۔ پالتو جانوروں کا ٹریکر۔

اس علم کو مستحکم کرنے کا بہترین طریقہ اصلی ہارڈ ویئر پر حقیقی مسائل کا سامنا کرنا اور ان کو حل کرنا ہے۔ ہر BLE پروڈکٹ کی اپنی منفرد خصوصیات ہوتی ہیں (iOS اور Android کے ساتھ کنکشن کے پیرامیٹرز پر بات چیت، بانڈ کے نقصان کے بعد دوبارہ کنکشن کو سنبھالنا، موثر ڈیٹا کی منتقلی کے لیے MTU سائز کا انتظام کرنا)، اور آپ ان کو بنا کر سیکھتے ہیں۔

BLE ماحولیاتی نظام بہت بڑا اور بڑھ رہا ہے۔ Zephyr کمیونٹی اور انٹرپرائز سپورٹ کے ساتھ پیداواری معیار، اوپن سورس فاؤنڈیشن فراہم کرتا ہے تاکہ آنے والے سالوں کے لیے فعال ترقی کو ممکن بنایا جا سکے۔ اب آپ کو اس پر تعمیر شروع کرنے کا علم ہے۔

خلاصہ

اس ہینڈ بک میں Zephyr OS میں بلوٹوتھ کی ترقی کے مکمل دائرہ کار کا احاطہ کیا گیا ہے، بنیادی تصورات سے لے کر پیداوار کے لیے تیار خصوصیات تک۔

BLE Basics سیکشن نے ذہنی ماڈل قائم کیا جس پر باقی سب کچھ مبنی ہے۔ GAP دریافت اور کنیکٹیویٹی کو کنٹرول کرتا ہے، GATT اس بات کی وضاحت کرتا ہے کہ ڈیٹا کی ساخت اور تبادلہ کیسے ہوتا ہے، خدمات اور خصوصیات ڈیوائس کا API تشکیل دیتے ہیں، اور UUID تمام اجزاء کی شناخت کرتا ہے۔ یہ تصورات Zephyr کے لیے مخصوص نہیں ہیں اور کسی بھی BLE اسٹیک پر لاگو ہوتے ہیں۔

Zephyr کی طرف، ہم تیزی سے پیچیدہ ایپلی کیشنز بنا رہے ہیں۔ بیکن نے کم سے کم BLE سیٹ اپ کا مظاہرہ کیا۔ یعنی اسٹیک کو شروع کریں اور اشتہار شروع کریں۔ ایل ای ڈی سروس یہ ظاہر کرتی ہے کہ فون پر ہارڈ ویئر کو کیسے کنٹرول کیا جا سکتا ہے اور GATT کو پڑھنے اور لکھنے کی خصوصیات کے ساتھ متعارف کرایا جاتا ہے۔ نوٹیفکیشن کی مثال ریئل ٹائم ڈیٹا پش کو شامل کرتی ہے، اور پورا سینسر نوڈ ایڈورٹائزنگ، GATT، کنکشن مینجمنٹ، اور متواتر ڈیٹا ڈیلیوری کو ایک مربوط ایپلی کیشن میں یکجا کرتا ہے۔

ان میں سے ہر ایک نمونہ (اشتہارات کا ڈیٹا مرتب کرنا، GATT کال بیکس پر دستخط کرنا، CCC کو سنبھالنا، کنکشن کے حوالہ جات کا انتظام کرنا) آپ کے بنائے ہوئے ہر BLE پروجیکٹ میں ظاہر ہوگا۔

معیاری ہارٹ ریٹ پروفائل نے یہ ظاہر کیا کہ SIG کے ذریعے بیان کردہ 16-bit UUID کو Zephyr کے پہلے سے طے شدہ UUID میکروز کے ساتھ کیسے ضم کیا جا سکتا ہے تاکہ عام BLE ایپس کے ساتھ انٹرآپریبلٹی کو فعال کیا جا سکے۔

مرکزی کردار کی مثال نے BLE کے دیگر پہلوؤں کو ظاہر کیا: سروس کی دریافت، کنیکٹوٹی، اور دور دراز کے آلات پر دریافت۔ ایم ٹی یو گفت و شنید اور پی ایچ وائی سلیکشن کنکشن قائم ہونے کے بعد ڈیٹا تھرو پٹ اور کوریج کو بہتر بنانے کے دو اہم ذرائع ہیں، اور دونوں کے لیے Kconfig اور رن ٹائم API کالز میں مربوط ترتیب کی ضرورت ہوتی ہے۔

DFU سیکشن نے MCUboot کو BLE پر SMP کے ساتھ مربوط کرکے فیلڈ اپ ڈیٹ ایبل فرم ویئر کے لیے پیداواری ضروریات کو پورا کیا۔

پوائنٹ ٹو پوائنٹ کنیکٹیویٹی کے علاوہ، بلوٹوتھ میش آٹومیشن اور بڑے پیمانے پر IoT تعیناتیوں کی تعمیر کے لیے BLE کو کئی سے زیادہ نیٹ ورکس تک پھیلاتا ہے، جبکہ LE آڈیو LC3 کوڈیک اور براڈکاسٹ صلاحیتوں کے ساتھ وائرلیس آڈیو کی اگلی نسل کی نمائندگی کرتا ہے۔ جوڑا بنانا اور سیکیورٹی پیداواری آلات کو غیر مجاز رسائی سے بچاتی ہے۔ پاور آپٹیمائزیشن، ڈیبگنگ ٹولز، اور اسٹیک موازنے حقیقی مصنوعات کو مارکیٹ میں لانے کے لیے درکار عملی علم کو مکمل کرتے ہیں۔

یہاں پیش کردہ کوڈ پیٹرن اور Kconfig کے اختیارات Zephyr پر کسی بھی BLE ڈیوائس کو بنانے کے لیے ایک ٹول کٹ بناتے ہیں، سادہ بیکنز سے لے کر پیچیدہ ملٹی پروٹوکول گیٹ ویز تک۔

اوپر تک سکرول کریں۔