البلوتوث

يوضّح هذا المستند كيفية استخدام واجهات برمجة التطبيقات Bluetooth ومقبس بلوتوث وبلوتوث منخفض الطاقة للاتصال بالأجهزة التي تتضمّن بلوتوث وأجهزة منخفضة الطاقة.

للحصول على معلومات أساسية حول البلوتوث، يمكنك الاطّلاع على مواصفات البلوتوث الرسمية.

متطلبات ملف البيان

بالنسبة إلى تطبيقات Chrome التي تستخدم تقنية البلوتوث، أضِف إدخال Bluetooth إلى البيان وحدِّد، إذا كان ذلك مناسبًا، المعرّفات الفريدة العالمية (UUID) للملفات الشخصية أو البروتوكولات أو الخدمات التي تريد تنفيذها، بالإضافة إلى ما إذا كنت تريد تنفيذها مع المقبس و/أو واجهات برمجة التطبيقات المنخفضة الطاقة.

على سبيل المثال لتنفيذ المقبس:

"bluetooth": {
  "uuids": [ "1105", "1106" ],
  "socket": true
}

وبالنسبة إلى التنفيذ المتعلق بالطاقة المنخفضة:

"bluetooth": {
  "uuids": [ "180D", "1809", "180F" ],
  "low_energy": true
}

للوصول إلى حالة المحوّل فقط واكتشاف الأجهزة المجاورة والحصول على المعلومات الأساسية حول الأجهزة، يلزم إدخال الإدخال نفسه فقط:

"bluetooth": {}

معلومات المحوِّل

جارٍ الحصول على حالة المحوِّل

لمعرفة حالة محوّل البلوتوث، استخدِم طريقة bluetooth.getAdapterState:

chrome.bluetooth.getAdapterState(function(adapter) {
  console.log("Adapter " + adapter.address + ": " + adapter.name);
});

إشعارات المحوِّل

يتم إرسال حدث bluetooth.onAdapterStateChanged كلما تغيّرت حالة المحوّل. ويمكن استخدام هذا، على سبيل المثال، لتحديد وقت تشغيل لاسلكي المحول أو إيقافه.

var powered = false;
chrome.bluetooth.getAdapterState(function(adapter) {
  powered = adapter.powered;
});

chrome.bluetooth.onAdapterStateChanged.addListener(
  function(adapter) {
    if (adapter.powered != powered) {
      powered = adapter.powered;
      if (powered) {
        console.log("Adapter radio is on");
      } else {
        console.log("Adapter radio is off");
      }
    }
  });

معلومات الجهاز

عرض الأجهزة المعروفة

للحصول على قائمة بالأجهزة المعروفة لمحوّل البلوتوث، استخدِم طريقة bluetooth.getDevices على النحو التالي:

chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    console.log(devices[i].address);
  }
});

يتم إرجاع جميع الأجهزة، بما في ذلك الأجهزة المقترِنة والأجهزة التي تم رصدها مؤخرًا. لن تبدأ هذه الميزة في اكتشاف أجهزة جديدة (راجِع اكتشاف الأجهزة المجاورة).

تلقّي إشعارات من الجهاز

بدلاً من استدعاء bluetooth.getDevices بشكل متكرّر، يمكنك استخدام الأحداث bluetooth.onDeviceAdded وbluetooth.onDeviceChanged وbluetooth.onDeviceRemoved لتلقّي الإشعارات.

يتم إرسال حدث bluetooth.onDeviceAdded عندما يتم اكتشاف جهاز من خلال المحوّل أو عندما يتم الاتصال بالمحوّل:

chrome.bluetooth.onDeviceAdded.addListener(function(device) {
  console.log(device.address);
});

لا تؤدي إضافة أداة معالجة لهذا الحدث إلى بدء اكتشاف الأجهزة (راجِع اكتشاف الأجهزة المجاورة).

يتم إرسال إشعار إلى التغييرات التي يتم إجراؤها على الأجهزة، بما في ذلك الأجهزة التي تم اكتشافها سابقًا والتي تم إقرانها، من خلال حدث bluetooth.onDeviceChanged:

chrome.bluetooth.onDeviceChanged.addListener(function(device) {
  console.log(device.address);
});

أخيرًا، يتم إرسال حدث bluetooth.onDeviceRemoved كلّما تمت إزالة جهاز مقترِن من النظام أو كلّما لم يتمّ رصد جهاز مؤخرًا:

chrome.bluetooth.onDeviceRemoved.addListener(function(device) {
  console.log(device.address);
});

جارٍ اكتشاف الأجهزة المجاورة

لبدء رصد الأجهزة المجاورة، استخدِم طريقة bluetooth.startDiscovery. قد تستهلك مهام الاستكشاف المزيد من الموارد، لذا عليك الاتصال بـ bluetooth.stopDiscovery عند الانتهاء.

يجب الاتصال بـ bluetooth.startDiscovery عندما يحتاج تطبيقك إلى اكتشاف الأجهزة المجاورة. يجب عدم جعل المكالمة مشروطة باستخدام السمة discovering في bluetooth.AdapterState. سينجح الاتصال حتى إذا كان تطبيق آخر يكتشف الأجهزة المجاورة، ويضمن أنّ المحوّل يواصل اكتشاف الأجهزة بعد توقف التطبيق الآخر.

يتم تلقّي معلومات عن كل جهاز تم اكتشافه حديثًا باستخدام حدث bluetooth.onDeviceAdded. وبالنسبة إلى الأجهزة التي سبق أن تم اكتشافها مؤخرًا أو التي سبق إقرانها أو تم الاتصال بها، لن يتم إرسال الحدث. بدلاً من ذلك، يجب الاتصال بـ bluetooth.getDevices للحصول على المعلومات الحالية، واستخدام الحدث bluetooth.onDeviceChanged لتلقّي إشعارات بالتغييرات التي تطرأ على هذه المعلومات نتيجةً للاكتشاف.

مثال:

var device_names = {};
var updateDeviceName = function(device) {
  device_names[device.address] = device.name;
};
var removeDeviceName = function(device) {
  delete device_names[device.address];
}

// Add listeners to receive newly found devices and updates
// to the previously known devices.
chrome.bluetooth.onDeviceAdded.addListener(updateDeviceName);
chrome.bluetooth.onDeviceChanged.addListener(updateDeviceName);
chrome.bluetooth.onDeviceRemoved.addListener(removeDeviceName);

// With the listeners in place, get the list of devices found in
// previous discovery sessions, or any currently active ones,
// along with paired devices.
chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    updateDeviceName(devices[i]);
  }
});

// Now begin the discovery process.
chrome.bluetooth.startDiscovery(function() {
  // Stop discovery after 30 seconds.
  setTimeout(function() {
    chrome.bluetooth.stopDiscovery(function() {});
  }, 30000);
});

إذا أوقف المستخدم تشغيل الراديو عبر البلوتوث، سيتم إنهاء جميع جلسات الاكتشاف ولن يتم استئنافها تلقائيًا عند تشغيل الراديو. إذا كان هذا الأمر مهمًا لتطبيقك، يجب مشاهدة حدث bluetooth.onAdapterStateChanged. إذا تم تغيير السمة discovering إلى false، سيحتاج تطبيقك إلى الاتصال بـ bluetooth.startDiscovery مجددًا لاستئنافه. عليك توخّي الحذر من طبيعة الاستكشاف الكثيفة للموارد.

التعرّف على الأجهزة

يتم تقديم عدد من الخيارات المختلفة لتحديد الأجهزة التي يتم إرجاعها من خلال bluetooth.getDevices والأحداث ذات الصلة به.

إذا كان الجهاز متوافقًا مع مواصفات رقم تعريف الجهاز الخاصة بالبلوتوث، تُضاف عدة خصائص إلى عنصر "الجهاز" الذي يحتوي على الحقول المحددة من خلال هذه المواصفات. مثال:

chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    if (devices[0].vendorIdSource != undefined) {
      console.log(devices[0].address + ' = ' +
                  devices[0].vendorIdSource + ':' +
                  devices[0].vendorId.toString(16) + ':' +
                  devices[0].productId.toString(16) + ':' +
                  devices[0].deviceId.toString(16));
    }
  }
});

عادةً ما تكون مواصفات رقم تعريف الجهاز كافية لتحديد طراز معيّن، وحتى مراجعة جهاز من المورّد. وفي حال عدم توفّر هذا الجهاز، عليك بدلاً من ذلك الاعتماد على معلومات حول فئة الجهاز أو نوعه، ويتم دمج هذه المعلومات اختياريًا مع بادئة الشركة المصنّعة في address.

توفِّر معظم أجهزة البلوتوث معلومات فئة الجهاز كحقل بت يتم تفسيره وفقًا لمستند أرقام النطاق الأساسي المخصّصة. يتوفّر حقل البت هذا في السمة deviceClass.

chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    if (devices[0].vendorIdSource != undefined) {
      console.log(devices[0].address + ' = ' +
                  devices[0].deviceClass.toString(16));
    }
  }
});

قد يكون تحليل الحقل معقدًا، لذا بالنسبة إلى أنواع الأجهزة الأكثر شيوعًا، يتعامل Chrome مع ذلك نيابةً عنك ويضبط الحقل type. إذا لم يكن ذلك متاحًا أو غير كافٍ لاحتياجاتك، ستحتاج إلى تحليل deviceClass بنفسك.

chrome.bluetooth.getDevices(function(devices) {
  for (var i = 0; i < devices.length; i++) {
    if (devices[0].vendorIdSource != undefined) {
      console.log(devices[0].address + ' = ' + devices[0].type);
    }
  }
});

استخدام بروتوكول RFCOMM وL2CAP

وقد تجري تطبيقات Chrome اتصالات بأي جهاز يتيح استخدام خدمات RFCOMM أو L2CAP. ويشمل ذلك معظم أجهزة البلوتوث الكلاسيكية في السوق.

التوصيل بمقبس

لإجراء اتصال بجهاز، تحتاج إلى ثلاثة أشياء. مقبس لإجراء الاتصال به تم إنشاؤه باستخدام bluetoothSocket.create وعنوان الجهاز الذي تريد الاتصال به والمعرّف الفريد العام للخدمة نفسها.

قبل إجراء الاتصال، يجب عليك التحقق من أن المحوِّل على دراية بالجهاز باستخدام bluetooth.getDevice أو واجهات برمجة تطبيقات اكتشاف الجهاز.

المعلومات اللازمة لإنشاء الاتصال الأساسي، بما في ذلك ما إذا كان يجب استخدام بروتوكول RFCOMM أو L2CAP والقناة أو PSM الذي يتم الحصول عليه باستخدام اكتشاف بروتوكول وصف الجلسة (SDP) على الجهاز.

مثال:

var uuid = '1105';
var onConnectedCallback = function() {
  if (chrome.runtime.lastError) {
    console.log("Connection failed: " + chrome.runtime.lastError.message);
  } else {
    // Profile implementation here.
  }
};

chrome.bluetoothSocket.create(function(createInfo) {
  chrome.bluetoothSocket.connect(createInfo.socketId,
    device.address, uuid, onConnectedCallback);
});

احتفِظ بالمعرِّف لـ socketId حتى تتمكّن من إرسال البيانات (bluetoothSocket.send) لاحقًا إلى هذا المقبس.

الاستلام من المقبس والإرسال إليه

يؤدي تلقّي البيانات من المقبس وإرسالها إليه إلى استخدام كائنات ArrayBuffer. للتعرّف على ArrayBuffer، يمكنك الاطّلاع على النظرة العامة والصفائف المكتوبة بلغة JavaScript والبرنامج التعليمي كيفية تحويل ArrayBuffer إلى سلسلة ومن سلسلة.

لإرسال البيانات المتوفّرة لديك في arrayBuffer، استخدِم bluetoothSocket.send:

chrome.bluetoothSocket.send(socketId, arrayBuffer, function(bytes_sent) {
  if (chrome.runtime.lastError) {
    console.log("Send failed: " + chrome.runtime.lastError.message);
  } else {
    console.log("Sent " + bytes_sent + " bytes")
  }
})

على عكس طريقة إرسال البيانات، يتم استلام البيانات في حدث (bluetoothSocket.onReceive). يتم إنشاء المقابس بشكل غير متوقف مؤقتًا (راجِع bluetoothSocket.setPaused) لذلك تتم عادةً إضافة أداة الاستماع لهذا الحدث بين bluetoothSocket.create وbluetoothSocket.connect.

chrome.bluetoothSocket.onRecieve.addListener(function(receiveInfo) {
  if (receiveInfo.socketId != socketId)
    return;
  // receiveInfo.data is an ArrayBuffer.
});

أخطاء في مقبس الاستلام وانقطاع الاتصال

لتلقّي إشعارات بأخطاء المقبس، بما في ذلك انقطاع الاتصال، أضِف أداة معالجة إلى الحدث bluetoothSocket.onReceiveError.

chrome.bluetoothSocket.onReceiveError.addListener(function(errorInfo) {
  // Cause is in errorInfo.error.
  console.log(errorInfo.errorMessage);
});

فصل المقبس

لانقطاع الاتصال وفصل المقبس، استخدِم bluetoothSocket.disconnect.

chrome.bluetoothSocket.disconnect(socketId);

خدمات النشر

بالإضافة إلى إجراء اتصالات صادرة بالأجهزة، قد تنشر تطبيقات Chrome خدمات قد يستخدمها أي جهاز يتوافق مع RFCOMM أو L2CAP.

الاستماع على مقبس

يتم دعم نوعين من الخدمات المنشورة. معيار RFCOMM هو الأكثر استخدامًا ويغطي غالبية الأجهزة والملفات الشخصية:

var uuid = '1105';
chrome.bluetoothSocket.create(function(createInfo) {
  chrome.bluetoothSocket.listenUsingRfcomm(createInfo.socketId,
    uuid, onListenCallback);
});

أمّا بروتوكول L2CAP، فهو الخيار الآخر ويشمل أنواع الأجهزة الأخرى والاستخدامات الخاصة بالموردين مثل تحميل البرامج الثابتة.

var uuid = '0b87367c-f188-47cd-bc20-a5f4f70973c6';
chrome.bluetoothSocket.create(function(createInfo) {
  chrome.bluetoothSocket.listenUsingL2cap(createInfo.socketId,
    uuid, onListenCallback);
});

في كلتا الحالتَين، يمكن ضبط bluetoothSocket.ListenOptions اختياريًا لتخصيص قناة معيّنة أو PSM. تشير معاودة الاتصال إلى حدوث خطأ من خلال chrome.runtime.lastError والنجاح في الحالات الأخرى. احتفِظ بالمعرِّف في SocketId بحيث يمكنك قبول الاتصالات (bluetoothSocket.onAccept) من هذا المقبس لاحقًا.

يتم قبول عمليات ربط العملاء

يتم قبول اتصالات العميل وتمريرها إلى تطبيقك من خلال حدث bluetoothSocket.onAccept.

chrome.bluetoothSocket.onAccept.addListener(function(acceptInfo) {
  if (info.socketId != serverSocketId)
    return;

  // Say hello...
  chrome.bluetoothSocket.send(acceptInfo.clientSocketId,
    data, onSendCallback);

  // Accepted sockets are initially paused,
  // set the onReceive listener first.
  chrome.bluetoothSocket.onReceive.addListener(onReceive);
  chrome.bluetoothSocket.setPaused(false);
});

إيقاف قبول عمليات الربط بالعملاء

لإيقاف قبول اتصالات العملاء وإلغاء نشر الخدمة، استخدِم bluetoothSocket.disconnect.

chrome.bluetoothSocket.disconnect(serverSocketId);

التفاعل مع الأجهزة منخفضة الطاقة

تقنية Bluetooth Low Energy أو (Bluetooth Smart) هي تقنية لاسلكية تهدف إلى الحدّ من استهلاك الطاقة. تسمح واجهة برمجة التطبيقات Bluetooth Low Energy للتطبيقات بتنفيذ الدور المركزي في اتصال LE بجهاز ملحق. توضّح الأقسام التالية كيفية اكتشاف الأجهزة الملحقة التي تعمل بالبلوتوث منخفض الطاقة والاتصال بها والتفاعل معها.

اكتشاف الأجهزة الملحقة والاتصال بها

كما هو الحال مع الأجهزة التقليدية التي تتضمّن بلوتوث، يمكن اكتشاف الأجهزة الملحقة ذات عدسة منخفضة الطاقة باستخدام الطرق الموضحة في اكتشاف الأجهزة المجاورة . ويجعل جهاز LE نفسه قابلاً للاكتشاف عن طريق إرسال حِزم البيانات المسماة "البيانات الإعلانية" ويُقال إن الجهاز في الوضع الإعلاني. قد تحتوي بيانات الإعلانات على معرّفات UUID للخدمات المتوفرة على الجهاز. وفي حال توفّر هذه المعرّفات الفريدة، يمكن الوصول إليها باستخدام السمة uuids للعنصر bluetooth.Device المقابل.

بعد اكتشاف الجهاز، يمكن توصيله من خلال الاتصال بـ bluetoothLowEnergy.connect ليتمكّن التطبيق من التفاعل مع خدماته:

chrome.bluetooth.onDeviceAdded.addListener(function(device) {
  var uuid = '0000180d-0000-1000-8000-00805f9b34fb';
  if (!device.uuids || device.uuids.indexOf(uuid) < 0)
    return;

  // The device has a service with the desired UUID.
  chrome.bluetoothLowEnergy.connect(device.address, function () {
    if (chrome.runtime.lastError) {
      console.log('Failed to connect: ' + chrome.runtime.lastError.message);
      return;
    }

    // Connected! Do stuff...
    ...
  });
});

بعد الربط، ستظهر القيمة true للسمة connected في العنصر bluetooth.Device المقابل. يؤدي الاتصال بـ bluetoothLowEnergy.connect إلى إنشاء مطالبة من خلال التطبيق بشأن الاتصال الفعلي بالجهاز. يمكن أن يحدث اتصال فعلي بالجهاز بدون استدعاء bluetoothLowEnergy.connect (على سبيل المثال، بسبب تطبيق آخر). في هذه الحالة، بينما لا يزال بإمكان تطبيقك التفاعل مع خدمات الجهاز، يجب أن يتصل دائمًا بـ bluetoothLowEnergy.connect لمنع تطبيق آخر من إلغاء ربط الرابط الفعلي.

عندما لا يكون تطبيقك بحاجة إلى الربط، يمكنه إزالة مطالبته بشأن الاتصال من خلال الاتصال bluetoothLowEnergy.disconnect:

chrome.bluetoothLowEnergy.disconnect(deviceAddress);

يُرجى العلم أنّ هذا الإجراء لن يؤدي بالضرورة إلى محو الرابط الفعلي إلى الجهاز، لأنّ هناك تطبيقات أخرى لديها اتصالات نشطة بالجهاز. في بعض الأحيان، قد يصبح الجهاز غير متصل لأسباب خارجة عن سيطرة التطبيق (على سبيل المثال، إذا اختفى الجهاز أو انقطع اتصاله صراحةً من قِبل المستخدم من خلال برامج الخدمات الخاصة بنظام التشغيل). يجب أن يلتزم تطبيقك بالحدث bluetooth.onDeviceChanged ليتم إعلامك بالتغييرات التي تحدث في الاتصال وإعادة الاتصال إذا لزم الأمر.

بعد الاتصال بالإنترنت، سيكون الجهاز الذي يعمل بنظام التشغيل Chrome في ما يُسمى الدور المركزي، بينما يقال أن الجهاز البعيد هو الدور الطرفي. عند هذه المرحلة، يمكن لتطبيقك التفاعل مع الخدمات على الجهاز باستخدام الطرق الموضحة في القسم التالي. ملاحظة: لا تتيح واجهات برمجة التطبيقات حاليًا العمل كأجهزة ملحقة ذات كفاءة منخفضة، ويمكن للتطبيقات تنفيذ الدور المركزي فقط.

الخدمات والخصائص والواصفات

تعتمد تقنية Bluetooth Low Energy على بروتوكول بسيط للاستجابة للطلب يُسمى بروتوكول السمات (ATT). باستخدام إطار عمل شفافية تتبّع التطبيقات (ATT)، يتفاعل الجهاز المركزي مع ما يُسمّى السمات على الأجهزة الملحقة من خلال التوافق مع ملف تعريف خاص للبلوتوث يُعرف باسم ملف السمات العامة (GATT). يحدد GATT المفاهيم عالية المستوى التالية:

  • الخدمة: تمثل خدمة GATT مجموعة من البيانات والسلوكيات المرتبطة بها لإنجاز وظيفة معينة بأحد الأجهزة. على سبيل المثال، ستحتوي أداة مراقبة معدل نبضات القلب عادةً على "خدمة معدل قلب" واحدة على الأقل. يتم تضمين المعلومات المتعلقة بخدمة GATT في عنصر bluetoothLowEnergy.Service.
  • الخاصية: سمة GATT هي عنصر بيانات أساسي يُستخدم لإنشاء خدمة GATT، وتحتوي على قيمة إلى جانب الخصائص التي تحدد كيفية الوصول إلى هذه القيمة. على سبيل المثال، تحتوي "خدمة معدل ضربات القلب" على خاصية "قياس معدل ضربات القلب" التي تُستخدم للحصول على قيمة معدل ضربات قلب المستخدم. يتم تضمين المعلومات الخاصة بسمة GATT في عنصر bluetoothLowEnergy.Characteristic.
  • الواصف: يحتوي واصف سمة GATT على معلومات إضافية حول السمة. ترد معلومات حول واصف GATT المميز في عنصر bluetoothLowEnergy.Descriptor.

تسمح واجهة برمجة التطبيقات Bluetooth Low Energy للتطبيقات بالعثور على معلومات حول خدمات الجهاز وخصائصه وأدواته الوصفية من خلال الاتصال بـ bluetoothLowEnergy.getServices وbluetoothLowEnergy.getCharacteristics، وbluetoothLowEnergy.getDescriptors. يمكن للتطبيقات فلترة الخدمات والخصائص والأوصاف من خلال مقارنة حقل uuid بالمعرّف الفريد العام (UUID) المطلوب لـ GATT:

chrome.bluetoothLowEnergy.getServices(deviceAddress, function(services) {
  ...
  for (var i = 0; i < services.length; i++) {
    if (services[i].uuid == HEART_RATE_SERVICE_UUID) {
      heartRateService = services[i];
      break;
    }
  }
  ...
});

يتم تخصيص معرّف مثيل فريد لكل خدمة وخاصية وواصف يمكن الوصول إليها من خلال واجهة برمجة التطبيقات، والتي يمكن الحصول عليها باستخدام الحقل instanceId. ويمكن استخدام رقم تعريف المثيل هذا لتحديد عنصر GATT ولتنفيذ عمليات محدّدة عليه:

chrome.bluetoothLowEnergy.getCharacteristics(heartRateService.instanceId,
                                             function(chracteristics) {
  ...
  for (var i = 0; i < characteristics.length; i++) {
    if (characteristics[i].uuid == HEART_RATE_MEASUREMENT_UUID) {
      measurementChar = characteristics[i];
      break;
    }
  }
  ...
  chrome.bluetoothLowEnergy.getDescriptors(measurementChar.instanceId,
                                           function(descriptors) {
    ...
  });
});

أحداث الخدمة

بعد اتصال أحد الأجهزة، سيكتشف Chrome خدماته. عند اكتشاف كل خدمة وإزالتها، سيتلقّى التطبيق حدثَي bluetoothLowEnergy.onServiceAdded وbluetoothLowEnergy.onServiceRemoved:

  var initializeService = function(service) {
    if (!service) {
      console.log('No service selected!');
      // Reset UI, etc.
      ...
      return;
    }

    myService = service;

    // Get all the characteristics and descriptors and bootstrap the app.
    ...
  };

  chrome.bluetoothLowEnergy.onServiceAdded.addListener(function(service) {
    if (service.uuid == MY_SERVICE_UUID)
      initializeService(service);
  });

  chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function(service) {
    if (service.instanceId == myService.instanceId)
      initializeService(null);
  });

يستكشف Chrome جميع خصائص الخدمة وأوصافها على نحو غير متزامن ويرسل حدث bluetoothLowEnergy.onServiceAdded بعد اكتمال عملية الاكتشاف. في حال إنهاء الاتصال بأحد الأجهزة الملحقة، سيزيل Chrome جميع الخدمات ذات الصلة ويرسِل حدث bluetoothLowEnergy.onServiceRemoved.

يمكن أن تعدّل بعض الأجهزة الملحقة خدماتها، على سبيل المثال قد تتغير خصائص الخدمة أو قد تتم إضافة خدمات وإزالتها تمامًا. يُبلِغ Chrome التطبيقات بهذه التغييرات من خلال أحداث bluetoothLowEnergy.onServiceChanged وbluetoothLowEnergy.onServiceAdded، وbluetoothLowEnergy.onServiceRemoved.

  chrome.bluetoothLowEnergy.onServiceChanged.addListener(function(service) {
    if (service.instanceId != myService.instanceId)
      return;

    updateMyService(service);
  });

قراءة قيمة السمة وكتابتها

تشفر خاصية GATT جانبًا واحدًا من خدمتها. يقرأ التطبيق المركزي حالة خدمة الجهاز الملحق ويعمل عليها ويعدّلها من خلال العمل على قيمة السمة. قيمة السمة هي سلسلة من وحدات البايت ويتم تحديد معناها من خلال المواصفات العالية المستوى التي تحدّد سمة معيّنة. على سبيل المثال، تعمل قيمة خاصية قياس معدّل نبضات القلب على ترميز معدّل نبضات قلب المستخدم وإجمالي عدد السعرات الحرارية التي تم حرقها، في حين تعمل خاصية الموقع الجغرافي لأجهزة استشعار الجسم على ترميز الأماكن التي يجب ارتداء جهاز استشعار معدّل نبضات القلب فيها.

يوفّر Chrome طريقة bluetoothLowEnergy.readCharacteristicValue لقراءة قيمة إحدى الخاصيّة:

chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId,
                                                  function(result) {
  if (chrome.runtime.lastError) {
    console.log('Failed to read value: ' + chrome.runtime.lastError.message);
    return;
  }

  var bytes = new Uint8Array(result.value);

  // Do stuff with the bytes.
  ...
});

بعض الخصائص قابلة للكتابة، خاصة تلك التي تعمل كـ "نقاط تحكم"، حيث يكون لكتابة القيمة آثار جانبية. على سبيل المثال، تُستخدَم خاصية نقطة التحكم في معدّل نبضات القلب لمطالبة جهاز استشعار معدّل نبضات القلب بإعادة ضبط إجمالي عدد السعرات الحرارية المحروقة والاستجابة لعملية الكتابة فقط. لتحقيق ذلك، يوفّر Chrome طريقة bluetoothLowEnergy.writeCharacteristicValue:

var myBytes = new Uint8Array([ ... ]);
chrome.bluetoothLowEnergy.writeCharacteristicValue(chrc.instanceId,
                                                   myBytes.buffer,
                                                   function() {
  if (chrome.runtime.lastError) {
    console.log('Failed to write value: ' +
                chrome.runtime.lastError.message);
    return;
  }

  // Value is written now.
});

تعمل أدوات وصف الخصائص بالطريقة نفسها ويمكن أن تكون سهلة القراءة و/أو الكتابة. يوفّر Chrome طريقتَي bluetoothLowEnergy.readDescriptorValue وbluetoothLowEnergy.writeDescriptorValue لقراءة قيمة الوصف وكتابتها.

للتحقّق ممّا إذا كانت إحدى السمات تتيح القراءة أو الكتابة، يمكن أن يتحقّق أحد التطبيقات من الحقل properties لكائن bluetoothLowEnergy.Characteristic. بينما لا يحتوي هذا الحقل على معلومات حول متطلبات الأمان للوصول إلى قيمة، فإنه يصف عملية القيمة التي تدعمها الخاصية بشكل عام.

التعامل مع الإشعارات بشأن القيمة

توضّح بعض الخصائص قيمتها باستخدام الإشعارات أو المؤشرات. على سبيل المثال، خاصية قياس معدل ضربات القلب غير قابلة للقراءة أو الكتابة ولكنها ترسل تحديثات بشأن قيمتها الحالية على فترات منتظمة. يمكن للتطبيقات الاستماع إلى هذه الإشعارات باستخدام حدث bluetoothLowEnergy.onCharacteristicValueChanged.

  chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener(
      function(chrc) {
    if (chrc.instanceId != myCharId)
      return;

    var bytes = new Uint8Array(chrc.value);

    // Do stuff with the bytes.
    ...
  });

ولا يتم تفعيل هذه الميزة تلقائيًا حتى إذا كانت تتيح استخدام الإشعارات أو المؤشرات. يجب أن يستدعي التطبيق طريقتَي bluetoothLowEnergy.startCharacteristicNotifications و bluetoothLowEnergy.stopCharacteristicNotifications لبدء أو إيقاف تلقّي حدث bluetoothLowEnergy.onCharacteristicValueChanged..

  // Start receiving characteristic value notifications.
  var notifying = false;
  chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId,
                                                             function() {
    if (chrome.runtime.lastError) {
      console.log('Failed to enable notifications: ' +
                  chrome.runtime.lastError.message);
      return;
    }

    notifying = true;
  });

  ...

  // No longer interested in notifications from this characteristic.
  if (notifying) {
    chrome.bluetoothLowEnergy.stopCharacteristicNotifications(
        chrc.instanceId);
  }

بعد بدء تشغيل الإشعارات، سيتلقّى التطبيق bluetoothLowEnergy.onCharacteristicValueChanged في كل مرّة يتم فيها تلقّي إشعار أو إشارة من السمة. إذا كانت السمة تتيح القراءة، سيتم إرسال هذا الحدث أيضًا بعد إجراء مكالمة ناجحة إلى bluetoothLowEnergy.readCharacteristicValue. ويسمح ذلك للتطبيقات بتوحيد تدفق التحكّم في تعديل القيمة الذي يتم تشغيله من خلال طلب قراءة والإشعارات:

  chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener(
      function(chrc) {
    // Process the value.
    ...
  });

  chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId,
                                                             function() {
    // Notifications started. Read the initial value.
    chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId,
                                                      function(result) {
      ...
      // No need to do anything here since onCharacteristicValueChanged
      // will handle it.
    });
  });

إذا كانت إحدى السمات تتيح إرسال الإشعارات، سيحتوي الحقل properties على السمة "notify" أو السمة "indicate".

ملاحظة: إذا كانت إحدى السمات تدعم الإشعارات/المؤشرات، سيكون لها الواصف "إعداد خاصية العميل" لتفعيل الإشعارات أو إيقافها. ولا يسمح Chrome للتطبيقات بالكتابة إلى أداة الوصف هذه. وبدلاً من ذلك، يجب أن تستخدم التطبيقات طريقتَي bluetoothLowEnergy.startCharacteristicNotifications و bluetoothLowEnergy.stopCharacteristicNotifications للتحكّم في سلوك الإشعارات.