تسمح Web Bluetooth API للمواقع الإلكترونية بالاتصال بالأجهزة التي تتضمّن بلوتوث.
ماذا لو أخبرتك أن مواقع الويب يمكنها التواصل مع الأجهزة القريبة التي تتضمن بلوتوث بطريقة آمنة تحافظ على الخصوصية؟ بهذه الطريقة، يمكن أن تتفاعل أجهزة مراقبة معدّل نبضات القلب ومصابيح الإضاءة التي تغنّي وحتى السلاحف مباشرةً مع المواقع الإلكترونية.
حتى الآن، أصبحت القدرة على التفاعل مع الأجهزة التي تتضمّن بلوتوث متاحة فقط للتطبيقات الخاصة بالنظام الأساسي. تهدف Web Bluetooth API إلى تغيير هذا وجلبه إلى متصفحات الويب أيضًا.
قبل أن نبدأ
يفترض هذا المستند أن لديك بعض المعرفة الأساسية حول طريقة عمل البلوتوث المنخفض الطاقة (BLE) والملف التعريفي العام للسمة.
على الرغم من أنّ مواصفات Web Bluetooth API لم يتم الانتهاء منها بعد، فإنّ مؤلفي المواصفات يبحثون بجدية عن مطوّرين متحمّسين لتجربة واجهة برمجة التطبيقات هذه وتقديم ملاحظات حول المواصفات والملاحظات حول عملية التنفيذ.
تتوفّر مجموعة فرعية من Web Bluetooth API في ChromeOS وChrome لنظام التشغيل Android 6.0 وMac (Chrome 56) وWindows 10 (Chrome 70). هذا يعني أنّه من المفترض أن يكون بإمكانك طلب والاتصال بالأجهزة القريبة التي تتضمّن طاقة بلوتوث منخفضة، وقراءة/كتابة خصائص البلوتوث، وتلقّي إشعارات GATT، ومعرفة عندما ينقطع اتصال جهاز يتضمّن بلوتوث، وحتى القراءة والكتابة إلى أدوات وصف البلوتوث. راجِع جدول توافُق المتصفح في MDN للحصول على مزيد من المعلومات.
بالنسبة إلى نظام التشغيل Linux والإصدارات السابقة من Windows، يمكنك تفعيل العلامة #experimental-web-platform-features
في about://flags
.
متاحة لمرحلة التجربة والتقييم
للحصول على أكبر قدر ممكن من الملاحظات من المطوّرين الذين يستخدمون Web Bluetooth API في هذا المجال، سبق أن أضاف Chrome هذه الميزة في الإصدار 53 من Chrome كإصدار تجريبي من المصدر لأنظمة التشغيل ChromeOS وAndroid وMac.
انتهت الفترة التجريبية بنجاح في كانون الثاني (يناير) 2017.
متطلبات الأمان
لفهم مقايضة الأمان، أقترح مشاركة نموذج أمان البلوتوث على الويب الذي أعدّته "جيفري ياسكين"، وهو مهندس برمجيات في فريق Chrome، يعمل على مواصفات Web Bluetooth API.
HTTPS فقط
بما أنّ واجهة برمجة التطبيقات التجريبية هذه ميزة جديدة وفعّالة تمت إضافتها إلى الويب، لم يتم توفيرها سوى للسياقات الآمنة. وهذا يعني أنه ستحتاج إلى الإنشاء مع وضع بروتوكول أمان طبقة النقل (TLS) في الاعتبار.
يجب تفعيل إيماءة المستخدم.
كميزة أمان، يجب تفعيل إيماءة المستخدم، مثلاً اللمس أو النقر بالماوس، على الأجهزة التي تتضمّن بلوتوث
navigator.bluetooth.requestDevice
. نحن نتحدّث عن الاستماع إلى
فعاليات pointerup
وclick
وtouchend
.
button.addEventListener('pointerup', function(event) {
// Call navigator.bluetooth.requestDevice
});
المشاركة في الرمز
تعتمد Web Bluetooth API بشكل كبير على وعود JavaScript. إذا لم تكن معتادًا على هذه الممارسات، يمكنك الاطّلاع
على هذا البرنامج التعليمي الرائع للتعهدات. () => {}
هي دوال الأسهم لعام 2015 في ECMAScript.
طلب أجهزة تتضمّن بلوتوث
يتيح هذا الإصدار من مواصفات Web Bluetooth API للمواقع الإلكترونية، التي تعمل في الدور المركزي، الاتصال بخوادم GATT عن بُعد عبر اتصال BLE. وهو يدعم التواصل بين الأجهزة التي تستخدم البلوتوث 4.0 أو الإصدارات الأحدث.
عندما يطلب أحد المواقع الإلكترونية الوصول إلى الأجهزة المجاورة باستخدام navigator.bluetooth.requestDevice
، سيطلب المتصفّح من المستخدم أداة اختيار الأجهزة حيث يمكنه اختيار جهاز واحد أو إلغاء الطلب.
تستخدم الدالة navigator.bluetooth.requestDevice()
كائنًا إلزاميًا
يحدد عوامل التصفية. وتُستخدم هذه الفلاتر لعرض الأجهزة التي تتطابق فقط مع بعض
خدمات Bluetooth GATT المُعلَن عنها و/أو اسم الجهاز.
فلتر الخدمات
على سبيل المثال، لطلب أجهزة بلوتوث التي تعلن عن خدمة بطارية GATT:
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => { /* … */ })
.catch(error => { console.error(error); });
إذا لم تكن خدمة Bluetooth GATT مدرَجة في قائمة خدمات Bluetooth GATT الموحّدة، يمكنك تقديم إما المعرّف الفريد العالمي (UUID) للبلوتوث بالكامل أو نموذج قصير 16 أو 32 بت.
navigator.bluetooth.requestDevice({
filters: [{
services: [0x1234, 0x12345678, '99999999-0000-1000-8000-00805f9b34fb']
}]
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
فلتر الأسماء
يمكنك أيضًا طلب أجهزة تتضمّن بلوتوث استنادًا إلى اسم الجهاز الذي يتم الإعلان عنه باستخدام مفتاح الفلاتر name
أو حتى بادئة من هذا الاسم باستخدام مفتاح الفلاتر namePrefix
. يُرجى العلم أنّه في هذه الحالة، يجب أيضًا تحديد المفتاح
optionalServices
لتتمكّن من الوصول إلى أي خدمات غير مضمّنة في
فلتر الخدمة. وإذا لم تقم بذلك، فسوف تحصل على خطأ لاحقًا عند محاولة الوصول إليها.
navigator.bluetooth.requestDevice({
filters: [{
name: 'Francois robot'
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
فلتر بيانات الشركة المصنّعة
ومن الممكن أيضًا طلب أجهزة تتضمّن بلوتوث استنادًا إلى البيانات الخاصة بالشركة المصنّعة
التي يتم الإعلان عنها باستخدام مفتاح الفلاتر manufacturerData
. وهذا المفتاح هو مصفوفة من العناصر التي لها مفتاح معرّف شركة Bluetooth إلزامي اسمه companyIdentifier
. يمكنك أيضًا توفير بادئة بيانات تعمل على تصفية
بيانات الشركة المصنعة من أجهزة بلوتوث التي تبدأ بها. يُرجى العلم أنّه عليك
أيضًا تحديد مفتاح optionalServices
لتتمكّن من الوصول إلى أي خدمات
غير مضمّنة في فلتر الخدمة. وإذا لم تقم بذلك، ستتلقى رسالة خطأ لاحقًا
عند محاولة الوصول إليها.
// Filter Bluetooth devices from Google company with manufacturer data bytes
// that start with [0x01, 0x02].
navigator.bluetooth.requestDevice({
filters: [{
manufacturerData: [{
companyIdentifier: 0x00e0,
dataPrefix: new Uint8Array([0x01, 0x02])
}]
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
يمكن أيضًا استخدام القناع مع بادئة البيانات لمطابقة بعض الأنماط في بيانات الشركة المصنّعة. يمكنك الاطّلاع على الشرح لفلاتر بيانات البلوتوث لمعرفة المزيد من المعلومات.
فلاتر الاستبعاد
يتيح لك الخيار exclusionFilters
في navigator.bluetooth.requestDevice()
استبعاد بعض الأجهزة من أداة اختيار المتصفّح. يمكن استخدامه لاستبعاد الأجهزة التي تتطابق مع
فلتر أوسع ولكن غير متوافقة.
// Request access to a bluetooth device whose name starts with "Created by".
// The device named "Created by Francois" has been reported as unsupported.
navigator.bluetooth.requestDevice({
filters: [{
namePrefix: "Created by"
}],
exclusionFilters: [{
name: "Created by Francois"
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
عدم استخدام الفلاتر
أخيرًا، بدلاً من filters
، يمكنك استخدام المفتاح acceptAllDevices
لعرض جميع الأجهزة القريبة التي تتضمّن بلوتوث. عليك أيضًا تحديد مفتاح optionalServices
لتتمكّن من الوصول إلى بعض الخدمات. وإذا لم تقم بذلك، فستتلقى رسالة خطأ لاحقًا
عند محاولة الوصول إليها.
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
الاتصال بجهاز بلوتوث
إذًا، ماذا ستفعل الآن بعد أن أصبح لديك BluetoothDevice
؟ دعونا نتصل بخادم GATT عن بعد عبر البلوتوث والذي يحمل تعريفات الخدمة والخصائص.
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => {
// Human-readable name of the device.
console.log(device.name);
// Attempts to connect to remote GATT Server.
return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });
قراءة إحدى خصائص البلوتوث
هنا نتصل بخادم GATT للجهاز البعيد الذي يتضمّن بلوتوث. نريد الآن الحصول على خدمة GATT الأساسية وقراءة إحدى الخصائص التي تنتمي إلى هذه الخدمة. لنجرب، على سبيل المثال، قراءة مستوى الشحن الحالي لبطارية الجهاز.
في المثال السابق، battery_level
هي سمة مستوى البطارية الموحّدة.
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => device.gatt.connect())
.then(server => {
// Getting Battery Service…
return server.getPrimaryService('battery_service');
})
.then(service => {
// Getting Battery Level Characteristic…
return service.getCharacteristic('battery_level');
})
.then(characteristic => {
// Reading Battery Level…
return characteristic.readValue();
})
.then(value => {
console.log(`Battery percentage is ${value.getUint8(0)}`);
})
.catch(error => { console.error(error); });
في حال استخدام إحدى سمات GATT المخصّصة للبلوتوث، يمكنك تقديم إما معرّف UUID الكامل للبلوتوث أو نموذج قصير 16 أو 32 بت إلى service.getCharacteristic
.
يُرجى العِلم أنّه يمكنك أيضًا إضافة أداة معالجة حدث characteristicvaluechanged
إلى إحدى السمات الخاصة للتعامل مع قراءة قيمتها. يمكنك الاطّلاع على نموذج تغيير قيمة السمة المخصّصة للقراءة أيضًا لمعرفة كيفية التعامل مع إشعارات GATT القادمة اختياريًا.
…
.then(characteristic => {
// Set up event listener for when characteristic value changes.
characteristic.addEventListener('characteristicvaluechanged',
handleBatteryLevelChanged);
// Reading Battery Level…
return characteristic.readValue();
})
.catch(error => { console.error(error); });
function handleBatteryLevelChanged(event) {
const batteryLevel = event.target.value.getUint8(0);
console.log('Battery percentage is ' + batteryLevel);
}
الكتابة إلى إحدى خصائص البلوتوث
تعد الكتابة إلى سمة Bluetooth GATT سهلة مثل قراءتها. هذه المرة، لنستخدم نقطة التحكم في معدل ضربات القلب لإعادة ضبط قيمة حقل الطاقة المستنفدة على 0 على جهاز مراقبة معدل ضربات القلب.
أعدك أنه ما مِن سحر هنا. ويمكنك الاطّلاع على كل هذه التفاصيل في صفحة خصائص نقطة التحكّم في معدّل نبضات القلب.
navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_control_point'))
.then(characteristic => {
// Writing 1 is the signal to reset energy expended.
const resetEnergyExpended = Uint8Array.of(1);
return characteristic.writeValue(resetEnergyExpended);
})
.then(_ => {
console.log('Energy expended has been reset.');
})
.catch(error => { console.error(error); });
تلقّي إشعارات GATT
لنرَ الآن كيفية تلقّي إشعار عند تغيُّر خاصية قياس معدّل نبضات القلب على الجهاز:
navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => characteristic.startNotifications())
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged',
handleCharacteristicValueChanged);
console.log('Notifications have been started.');
})
.catch(error => { console.error(error); });
function handleCharacteristicValueChanged(event) {
const value = event.target.value;
console.log('Received ' + value);
// TODO: Parse Heart Rate Measurement value.
// See https://github.com/WebBluetoothCG/demos/blob/gh-pages/heart-rate-sensor/heartRateSensor.js
}
يوضّح لك نموذج الإشعارات كيفية إيقاف الإشعارات من خلال stopNotifications()
وإزالة أداة معالجة أحداث characteristicvaluechanged
التي تمت إضافتها بشكل صحيح.
إلغاء الربط بجهاز يتضمّن بلوتوث
لتوفير تجربة مستخدم أفضل، قد ترغب في الاستماع إلى أحداث إلغاء الربط ودعوة المستخدم إلى إعادة الاتصال:
navigator.bluetooth.requestDevice({ filters: [{ name: 'Francois robot' }] })
.then(device => {
// Set up event listener for when device gets disconnected.
device.addEventListener('gattserverdisconnected', onDisconnected);
// Attempts to connect to remote GATT Server.
return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });
function onDisconnected(event) {
const device = event.target;
console.log(`Device ${device.name} is disconnected.`);
}
يمكنك أيضًا الاتصال بـ device.gatt.disconnect()
لإلغاء ربط تطبيق الويب بالجهاز الذي يتضمّن بلوتوث. سيؤدي هذا الإجراء إلى ظهور مستمعي
حدث gattserverdisconnected
الحاليين. تجدر الإشارة إلى أنه لن يتوقف اتصال جهاز البلوتوث إذا كان هناك
تطبيق آخر يتصل بالفعل بالجهاز الذي يتضمّن بلوتوث. يمكنك الاطّلاع على نموذج إلغاء ربط الجهاز ونموذج إعادة الربط التلقائي لمزيد من التفاصيل.
قراءة أدوات الوصف عبر البلوتوث والكتابة فيها
أدوات وصف GATT لالبلوتوث هي سمات تصف قيمة مميّزة. ويمكنك قراءتها والكتابة بها بطريقة مشابهة لخصائص Bluetooth GATT.
لنرَ على سبيل المثال كيفية قراءة وصف المستخدم لفاصل زمني لقياس ميزان الحرارة الصحية للجهاز.
في المثال أدناه، يتم استخدام خدمة ميزان الحرارة Health،
measurement_interval
وسمة الفاصل الزمني للقياس، وgatt.characteristic_user_description
أداة وصف وصف المستخدم المميز.health_thermometer
navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => descriptor.readValue())
.then(value => {
const decoder = new TextDecoder('utf-8');
console.log(`User Description: ${decoder.decode(value)}`);
})
.catch(error => { console.error(error); });
الآن وبعد أن قرأنا وصف المستخدم للفاصل الزمني للقياس في ميزان الحرارة الصحية للجهاز، لنتعرّف على كيفية تحديثه وكتابة قيمة مخصّصة.
navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => {
const encoder = new TextEncoder('utf-8');
const userDescription = encoder.encode('Defines the time between measurements.');
return descriptor.writeValue(userDescription);
})
.catch(error => { console.error(error); });
النماذج التجريبية والعروض التوضيحية والدروس التطبيقية حول الترميز
تم اختبار جميع نماذج بلوتوث الويب أدناه بنجاح. للحصول على هذه العيّنات على أكمل وجه، ننصحك بتثبيت [تطبيق BLE Peripheral Simulator Android] الذي يحاكي جهاز BLE الملحق بخدمة بطارية أو خدمة معدل ضربات القلب أو خدمة ميزان حرارة للصحة.
مبتدئ
- معلومات الجهاز - لاسترداد معلومات الجهاز الأساسية من جهاز تقنية BLE.
- مستوى البطارية: يمكنك استرداد معلومات البطارية من جهاز BLE الخاص بإعلانات البطارية.
- إعادة ضبط الطاقة - إعادة ضبط الطاقة المستنفدة من جهاز BLE يُعلن عن معدّل نبضات القلب.
- الخصائص المميزة - تعرض جميع خصائص سمة معينة من جهاز تقنية البلوتوث المنخفض الطاقة (BLE).
- الإشعارات: يمكنك تفعيل الإشعارات المميزة وإيقافها من جهاز تقنية البلوتوث المنخفض الطاقة.
- إلغاء ربط الجهاز: يمكنك قطع الاتصال وتلقّي إشعار بانقطاع الاتصال بجهاز BLE بعد الاتصال به.
- الحصول على الخصائص - احصل على جميع خصائص الخدمة المُعلَن عنها من جهاز تقنية BLE.
- الحصول على أدوات الوصف: احصل على الكلمات الوصفية لجميع خصائص الخدمة المُعلَن عنها من جهاز تقنية BLE.
- فلتر بيانات الشركة المصنّعة: يمكنك استرداد معلومات الجهاز الأساسية من جهاز BLE الذي يطابق بيانات الشركة المصنّعة.
- فلاتر الاستبعاد: يمكنك استرداد معلومات الجهاز الأساسية من جهاز يستخدم تقنية BLE من خلال عرض فلاتر الاستبعاد الأساسية.
الجمع بين عمليات متعددة
- خصائص GAP - احصل على جميع خصائص GAP لجهاز BLE.
- خصائص معلومات الجهاز - احصل على جميع خصائص معلومات الجهاز لجهاز BLE.
- فقدان الرابط: ضبط خاصية "مستوى التنبيه" لجهاز BLE (قيمة القراءة والكتابة القيم)
- اكتشاف الخدمات والخصائص: يمكنك اكتشاف جميع الخدمات الأساسية التي يمكن الوصول إليها وخصائصها من خلال جهاز تقنية البلوتوث المنخفض الطاقة.
- إعادة الاتصال التلقائي: يمكنك إعادة الاتصال بجهاز BLE غير متصل باستخدام خوارزمية التراجع الأسي.
- الاطّلاع على تغيير قيمة السمة: يمكنك الاطّلاع على مستوى البطارية وتلقّي إشعارات عند إجراء أي تغييرات من جهاز تقنية البلوتوث المنخفض الطاقة.
- قراءة أدوات الوصف: اقرأ جميع الأوصاف الخاصة بخصائص خدمة معيّنة من جهاز تقنية BLE.
- واصف الكتابة: اكتب نص الوصف "وصف المستخدم المميز" على جهاز تقنية BLE.
يمكنك أيضًا الاطّلاع على عروضنا التوضيحية التي تم تنظيمها حول البلوتوث على الويب والدروس التطبيقية الرسمية حول ترميز البلوتوث على الويب.
المكتبات
- web-bluetooth-utils عبارة عن وحدة npm تضيف بعض وظائف الراحة إلى واجهة برمجة التطبيقات.
- يتوفر مكوّن Web Bluetooth API في الوحدة المركزية noble، وهي الوحدة المركزية Node.js BLE الأكثر شيوعًا. ويتيح لك هذا إنشاء حزمة ويب/إضافة برامج إلى متصفّحات الويب بدون الحاجة إلى خادم WebSocket أو مكونات إضافية أخرى.
- angular-web-Bluetooth هو وحدة لخدمة Angular تزيل كل النصوص النموذجية اللازمة لإعداد Web Bluetooth API.
الأدوات
- بدء استخدام Web Bluetooth هو تطبيق ويب بسيط سيُنشئ كل رمز JavaScript النموذجي لبدء التفاعل مع جهاز يتضمّن بلوتوث. أدخِل اسم الجهاز، أو الخدمة، أو إحدى السمات، وحدِّد خصائصها، ومن ثم
- إذا كنت مطوّر برامج بلوتوث حاليًا، سينشئ المكوِّن الإضافي Web Bluetooth Developer Studio أيضًا رمز JavaScript لتقنية البلوتوث على الويب لجهازك الذي يتضمّن بلوتوث.
نصائح
تتوفّر صفحة عناصر البلوتوث الداخلية في Chrome على
about://bluetooth-internals
حتى تتمكّن من فحص كل ما يتعلق بأجهزة البلوتوث
القريبة: الحالة والخدمات والخصائص والميزات الوصفية.
أنصحك أيضًا بمراجعة الصفحة الرسمية كيفية الإبلاغ عن أخطاء البلوتوث في الويب، لأنّ تصحيح أخطاء البلوتوث قد يكون صعبًا في بعض الأحيان.
الخطوات التالية
تحقَّق أولاً من حالة تنفيذ المتصفّح والنظام الأساسي لمعرفة أجزاء Web Bluetooth API التي يتمّ تنفيذها حاليًا.
على الرغم من أنها لا تزال غير مكتملة، إليك نظرة سريعة على ما يمكن توقعه في المستقبل القريب:
- سيتم البحث عن إعلانات BLE القريبة مع
navigator.bluetooth.requestLEScan()
. - سيتتبّع حدث "
serviceadded
" الجديد خدمات GATT التي تتضمّن بلوتوث والمكتشفة حديثًا، بينما يتتبّع حدثserviceremoved
الخدمات التي تمت إزالتها. وسيتم تنشيط حدثservicechanged
جديد عند إضافة أي سمة و/أو واصف أو إزالتها من خدمة Bluetooth GATT.
إظهار الدعم لواجهة برمجة التطبيقات
هل تخطّط لاستخدام واجهة برمجة التطبيقات Web Bluetooth API؟ يساعد الدعم العام فريق Chrome في تحديد أولويات الميزات ويوضح لمورّدي المتصفِّح الآخرين مدى أهمية دعمهم.
يمكنك إرسال تغريدة إلى @ChromiumDev باستخدام الهاشتاغ
#WebBluetooth
وإعلامنا بمكان استخدامك لها وطريقة استخدامك لها.
المراجِع
- Stack Overflow
- حالة ميزات Chrome
- أخطاء تنفيذ Chrome
- مواصفات البلوتوث على الويب
- مشاكل المواصفات على GitHub
- تطبيق محاكاة الأجهزة الملحقة في تقنية BLE
شكر وتقدير
شكرًا لـ كايس باسك لمراجعة هذه المقالة. صورة رئيسية من SparkFun Electronics من بولدر، الولايات المتحدة الأمريكية