Bluetooth

במסמך הזה מוסבר איך להשתמש באביזרי Bluetooth, Bluetooth Socket ו-Bluetooth Low ממשקי API של Energy לתקשורת עם Bluetooth ומכשירי Bluetooth עם צריכת אנרגיה נמוכה.

למידע ברקע על Bluetooth, אפשר לעיין במפרט הרשמי של Bluetooth.

דרישות לגבי מניפסטים

באפליקציות Chrome שמשתמשות ב-Bluetooth, מוסיפים את רשומת Bluetooth למניפסט ומציינים אם מתאימים, את המזהים הייחודיים (UUID) של הפרופילים, הפרוטוקולים או השירותים שאתם רוצים להטמיע, וגם אם אם אתם רוצים להשתמש בהם באמצעות ממשקי ה-API עם שקע צריכת אנרגיה נמוכה או socket.

לדוגמה, להטמעה של שקע:

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

ליישום עם צריכת אנרגיה נמוכה:

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

כדי לגשת רק למצב המתאם, לאתר מכשירים בקרבת מקום ולקבל מידע בסיסי על מכשירים, נדרשת רק הרשומה עצמה:

"bluetooth": {}

פרטי המתאם

מתקבל מצב המתאם

כדי לבדוק את המצב של מתאם ה-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, יש להשתמש במכשיר bluetooth.getDevices method:

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. קמפיין Discovery יכול הם עתירי משאבים, לכן מומלץ לקרוא ל-bluetooth.stopDiscovery בסיום הפעולה.

מומלץ להפעיל את Bluetooth ל-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, כל סשנים של גילוי יסתיימו ולא יתחדשו באופן אוטומטי כשהרדיו מופעל. אם זה חשוב לאפליקציה שלך, כדאי לצפות אירוע bluetooth.onAdapterStateChanged. אם המאפיין discovering ישתנה ל-false, אז כדי להמשיך, האפליקציה תצטרך לקרוא שוב ל-bluetooth.startDiscovery. יש לנהוג בזהירות תגליות מושקעות במשאבים.

זיהוי של מכשירים

יש כמה אפשרויות שונות לזיהוי מכשירים שהוחזרו על ידי bluetooth.getDevices והאירועים הקשורים.

אם המכשיר תומך במפרט מזהה המכשיר של Bluetooth, יתווספו מספר נכסים אובייקט המכשיר שמכיל את השדות שהוגדרו במפרט הזה. דוגמה:

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.

רוב מכשירי Bluetooth מספקים סיווג של פרטי המכשיר כשדה ביט שמתורגם בהתאם מסמך Baseband Assigned Numbers. שדה הביטים הזה זמין ב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. המידע הזה כולל רוב מכשירי ה-Bluetooth הקלאסיים בשוק.

מתבצעת התחברות לשקע

כדי להתחבר למכשיר, נדרשים שלושה דברים. שקע כדי לבצע את החיבור נוצר באמצעות bluetoothSocket.create; כתובת המכשיר שאליו ברצונך להתחבר, וה-UUID של השירות עצמו.

לפני החיבור, עליך לוודא שהמתאם מודע למכשיר באמצעות bluetooth.getDevice או ממשקי ה-API לגילוי מכשירים.

המידע הדרוש כדי ליצור את החיבור הבסיסי, כולל אם ה-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) מאוחר יותר socket.

קבלה ושליחה ל-socket

קבלת נתונים מ-socket ושליחה אליהם משתמשים באובייקטים מסוג ArrayBuffer. כדי ללמוד על ArrayBuffers, לעיין בסקירה הכללית, מערכים מסוג JavaScript ובמדריך, איך להמיר את ArrayBuffer אל String וממנה.

כדי לשלוח נתונים שיש לכם ב-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) לכן ה-listener של האירוע הזה מתווסף בדרך כלל בין 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. הקריאה החוזרת (callback) מציינת שגיאה עד 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) היא טכנולוגיה אלחוטית לצריכת חשמל מופחתת צריכה. ה-API של Bluetooth Low Energy מאפשר לאפליקציות ליישם את התפקיד המרכזי חיבור LE לציוד היקפי. בקטעים הבאים מתואר איך למצוא תוכן, להתחבר אליהם ואיך אינטראקציה עם ציוד היקפי בחיבור Bluetooth עם צריכת אנרגיה נמוכה.

איתור ציוד היקפי וחיבור אליו

כמו במכשירי Bluetooth מסורתיים, ניתן לגלות ציוד היקפי מסוג LE באמצעות השיטות שמתוארות בקטע גילוי מכשירים בקרבת מקום . מכשיר LE הופך את עצמו לגלוי על ידי שליחת חבילות נתונים שנקרא 'נתוני פרסום' ושהמכשיר נמצא במצב פרסום. נתוני הפרסום עשוי להכיל מזהי UUID של שירותים שזמינים במכשיר. אם קיימים, מזהי UUID אלה ניתן לגשת אליו באמצעות המאפיין uuids של האובייקט bluetooth.Device המתאים.

אחרי הגילוי, אפשר לחבר מכשיר LE באמצעות קריאה ל-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...
    ...
  });
});

לאחר החיבור, המאפיין connected של האובייקט bluetooth.Device התואם מקבלים את הערך true. קריאה ל-bluetoothLowEnergy.connect יוצרת הצהרה על ידי בחיבור הפיזי למכשיר. יכול להיות שקיים חיבור פיזי למכשיר בלי לקרוא כלל ל-bluetoothLowEnergy.connect (לדוגמה, בגלל אפליקציה אחרת). לחשבון במקרה כזה, למרות שהאפליקציה עדיין יכולה לקיים אינטראקציה עם השירותים של המכשיר, היא אמורה קוראים תמיד ל-bluetoothLowEnergy.connect כדי למנוע מאפליקציה אחרת לנתק קישור פיזי.

לאחר שאין צורך לחבר את האפליקציה יותר, היא תוכל להסיר את תביעת הבעלות שלה על החיבור על ידי קריאה ל-bluetoothLowEnergy.disconnect:

chrome.bluetoothLowEnergy.disconnect(deviceAddress);

חשוב לשים לב שהפעולה הזו לא בהכרח תשמיד את הקישור הפיזי למכשיר, כי היא עשויה לגרום אפליקציות שיש להן חיבורים פעילים למכשיר. לפעמים המכשיר עלול להפוך מנותקות מסיבות שאינן בשליטת האפליקציה (למשל, אם המכשיר נעלם או מנותק באופן מפורש על ידי המשתמש דרך תוכנות של מערכת ההפעלה). האפליקציה צריכה לתעד את האירוע bluetooth.onDeviceChanged כדי לקבל התראות על שינויים ולחבר אותו מחדש אם צריך.

לאחר ההתחברות, המכשיר שבו פועל Chrome יהיה בתפקיד המרכזי שנקרא המכשיר המחובר לרשת אחרת נחשב בתפקיד היקפי. בשלב הזה האפליקציה יכולה לנהל אינטראקציה עם השירותים במכשיר באמצעות השיטות שמתוארות בקטע הבא. הערה: בשלב זה ממשקי API לא תומכים בפעולה של ציוד היקפי מסוג LE; אפליקציות יכולות רק להטמיע את התפקיד המרכזי.

שירותים, מאפיינים ומתארים

Bluetooth עם צריכת אנרגיה נמוכה מבוסס על פרוטוקול פשוט של בקשה-תגובה שנקרא Attribute Protocol (ATT). כאשר משתמשים ב-ATT, מכשיר מרכזי יוצר אינטראקציה עם המאפיינים (המאפיינים) האלה בציוד היקפי באמצעות פרופיל Bluetooth מיוחד שנקרא פרופיל מאפיינים כללי (GATT). GATT שמגדיר את המושגים הבאים ברמה הכללית:

  • שירות: שירות GATT מייצג איסוף של נתונים והתנהגויות קשורות כדי להשיג פונקציה מסוימת של המכשיר. לדוגמה, מוניטור דופק בדרך כלל יקבל לפחות "שירות דופק" אחד. מידע על שירות GATT כלול אובייקט bluetoothLowEnergy.Service.
  • מאפיין: מאפיין GATT הוא רכיב נתונים בסיסי המשמש לבניית שירות GATT, שמכיל ערך וגם מאפיינים שמגדירים את האופן שבו ניתן לגשת לערך הזה. לדוגמה, "שירות דופק" כולל 'מדידת דופק' משמש לקבלת ערך הדופק של המשתמש. מידע על מאפיין GATT כלול אובייקט bluetoothLowEnergy.Characteristic.
  • מתאר: מתאר של מאפיין GATT מכיל מידע נוסף על מאפיין. מידע על מתאר מאפיין GATT כלול אובייקט bluetoothLowEnergy.Descriptor.

ה-API של 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;
    }
  }
  ...
});

לכל שירות, מאפיין ומתאר שניתן לגשת אליהם דרך ה-API מוקצה ערך ייחודי שאפשר לקבל באמצעות השדה 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 לשליטה בהתנהגות ההתראות.