{"id":5456,"date":"2017-08-10T07:12:33","date_gmt":"2017-08-09T22:12:33","guid":{"rendered":"https:\/\/gunmagisgeek.com\/wordpress\/?p=5456"},"modified":"2017-08-10T12:34:41","modified_gmt":"2017-08-10T03:34:41","slug":"web-bluetooth-api-%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%a6%e3%83%96%e3%83%a9%e3%82%a6%e3%82%b6%e3%81%a0%e3%81%91%e3%81%a7microbit%e3%81%a8ble%e9%80%9a%e4%bf%a1%e3%81%97%e3%81%a6%e3%81%bf%e3%82%8b","status":"publish","type":"post","link":"https:\/\/gunmagisgeek.com\/blog\/microbit\/5456","title":{"rendered":"Web Bluetooth API \u3092\u4f7f\u3063\u3066\u30d6\u30e9\u30a6\u30b6\u3060\u3051\u3067Micro:bit\u3068BLE\u901a\u4fe1\u3057\u3066\u307f\u308b\u3002"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gunmagisgeek.com\/blog\/wp-content\/uploads\/2017\/08\/microbit_webBLE2-e1502241301615.png\" alt=\"microbit webBLE\" width=\"690\" height=\"485\" class=\"aligncenter size-full wp-image-5459 border\" srcset=\"https:\/\/gunmagisgeek.com\/blog\/wp-content\/uploads\/2017\/08\/microbit_webBLE2-e1502241301615.png 690w, https:\/\/gunmagisgeek.com\/blog\/wp-content\/uploads\/2017\/08\/microbit_webBLE2-e1502241301615-213x150.png 213w\" sizes=\"auto, (max-width: 690px) 100vw, 690px\" \/><\/p>\n<h2>\u6982\u8981<\/h2>\n<p>\u300c<a href=\"https:\/\/gunmagisgeek.com\/blog\/microbit\/5346\">Reveal.js\u3092Micro:bit(chibi:bit)\u3067\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u3059\u308b\u3002<\/a>\u300d\u306e\u8a18\u4e8b\u3067\u306f\u3001micro:bit(chibi:bit)\u3092\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u3068\u7e4b\u3052\u308b\u306e\u306b\u3001\u30d0\u30c3\u30af\u30a8\u30f3\u30c9\u3068\u3057\u3066node.js(BLE &#038; web socket)\u3092\u4f7f\u3063\u3066\u3044\u307e\u3057\u305f\u304c\u3001\u4eca\u56de\u306f\u3001Web Bluetooth API\u3092\u4f7f\u3063\u3066\u30d6\u30e9\u30a6\u30b6\u3060\u3051\u3067micro:bit\u3068\u901a\u4fe1\u3057\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p><strong>\u203b \u3044\u307e\u306e\u3068\u3053\u308dWeb Bluetooth API\u3092\u5229\u7528\u3067\u304d\u308b\u306e\u306f\u3001\u30c7\u30b9\u30af\u30c8\u30c3\u30d7\u306eChrome\/Opera\u3068\u4e00\u90e8\u6700\u65b0\u306eAndroid\u306e\u307f\u3067\u3059\u3002<\/strong><\/p>\n<p><a href=\"http:\/\/caniuse.com\/#feat=web-bluetooth\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gunmagisgeek.com\/blog\/wp-content\/uploads\/2017\/08\/webbluetooth_caniuse.png\" alt=\"Web Bluetooth \u5bfe\u5fdc\u8868\" width=\"586\" height=\"210\" class=\"alignnone size-full wp-image-5460 border\" srcset=\"https:\/\/gunmagisgeek.com\/blog\/wp-content\/uploads\/2017\/08\/webbluetooth_caniuse.png 586w, https:\/\/gunmagisgeek.com\/blog\/wp-content\/uploads\/2017\/08\/webbluetooth_caniuse-300x108.png 300w\" sizes=\"auto, (max-width: 586px) 100vw, 586px\" \/><\/a><\/p>\n<h2>\u4e8b\u524d\u6e96\u5099<\/h2>\n<ul>\n<li>\u30da\u30a2\u30ea\u30f3\u30b0\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u3092\u89e3\u9664\u3057\u3001\u3059\u3079\u3066\u306eBLE\u30b5\u30fc\u30d3\u30b9\u3092\u6709\u52b9\u306b\u3059\u308b\u305f\u3081\u306b\u4ee5\u4e0b\u306e\u4f5c\u696d\u3092\u884c\u3046\u5fc5\u8981\u304c\u3042\u308b\u3002\u53c2\u8003\uff1a<a href=\"https:\/\/github.com\/sandeepmistry\/node-bbc-microbit#flashing-microbit-firmware\">Flashing micro:bit firmware<\/a>\n<ol>\n<li><a href=\"https:\/\/github.com\/sandeepmistry\/node-bbc-microbit\/tree\/master\/firmware\">hex\u30d5\u30a1\u30a4\u30eb<\/a>\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u3002<\/li>\n<li>USB\u30b1\u30fc\u30d6\u30eb\u3092\u4f7f\u7528\u3057\u3066\u30de\u30a4\u30af\u30ed\u30d3\u30c3\u30c8\u3092PC\u306b\u63a5\u7d9a\u3002<\/li>\n<li>hex\u30d5\u30a1\u30a4\u30eb\u3092micro\uff1abit\u30c7\u30a3\u30b9\u30af\u30c9\u30e9\u30a4\u30d6\u306b\u30b3\u30d4\u30fc\u3059\u308b\u3002<\/li>\n<li>micro:bit\u3092\u518d\u8d77\u52d5\u3059\u308b\u3002<\/li>\n<li>LED\u306b\u30c9\u30c3\u30c8\u304c\u8868\u793a\u3055\u308c\u308b\u306e\u3067\u3001\u50be\u3051\u3066\u5186\u3092\u63cf\u304f(\u30ad\u30e3\u30ea\u30d6\u30ec\u30fc\u30b7\u30e7\u30f3)<\/li>\n<\/ol>\n<\/li>\n<li>\u30b5\u30fc\u30d3\u30b9\uff0f\u30ad\u30e3\u30e9\u30af\u30bf\u30ea\u30b9\u30c6\u30a3\u30c3\u30af\u306eUUID\u3092\u8abf\u3079\u3066\u304a\u304f\u3002<br \/><a href=\"https:\/\/lancaster-university.github.io\/microbit-docs\/resources\/bluetooth\/bluetooth_profile.html\">\u3053\u3053<\/a>\u3067\u78ba\u8a8d\u3067\u304d\u307e\u3059\u3002<\/li>\n<\/ul>\n<h2>\u53c2\u8003\u306b\u3057\u305f\u8a18\u4e8b<\/h2>\n<p><a href=\"http:\/\/qiita.com\/moaible\/items\/111e2b637f3404a2de49\">BLE\u306b\u3064\u3044\u3066\u4eca\u66f4\u8abf\u3079\u3066\u307f\u305f &#8211; Qiita<\/a><br \/>\n<a href=\"https:\/\/ics.media\/entry\/15520\">\u30d6\u30e9\u30a6\u30b6\u304b\u3089Bluetooth\u304c\u4f7f\u3048\u308b\uff01 JS\u3067Web Bluetooth API\u3092\u4f7f\u3063\u3066BLE\u6a5f\u5668\u3092\u64cd\u4f5c\u3059\u308b\u65b9\u6cd5[L\u30c1\u30ab\u30fb\u6e29\u6e7f\u5ea6\u30bb\u30f3\u30b5\u30fc\u7de8] &#8211; ICS MEDIA<\/a><\/p>\n<h2>\u63a5\u7d9a\u30d5\u30ed\u30fc<\/h2>\n<p>\u57fa\u672c\u7684\u306b\u306f\u3001\u30c7\u30d0\u30a4\u30b9 \u2192 GATT\u30b5\u30fc\u30d0\u30fc \u2192 \u30b5\u30fc\u30d3\u30b9 -> \u30ad\u30e3\u30e9\u30af\u30bf\u30ea\u30b9\u30c6\u30a3\u30c3\u30af\u3068\u8fbf\u3063\u3066\u3044\u304f\u3053\u3068\u3067\u3001\u5229\u7528\u3057\u305f\u3044\u6a5f\u80fd\u306b\u63a5\u7d9a\u3057\u307e\u3059\u3002<\/p>\n<ol>\n<li>\u30c7\u30d0\u30a4\u30b9\u306e\u30b9\u30ad\u30e3\u30f3(navigator.bluetooth.requestDevice)<\/li>\n<li>\u30da\u30a2\u30ea\u30f3\u30b0<\/li>\n<li>GATT\u30b5\u30fc\u30d0\u30fc\u306b\u63a5\u7d9a(device.gatt.connect)<\/li>\n<li>\u30b5\u30fc\u30d3\u30b9\u306e\u53d6\u5f97(server.getPrimaryService)<\/li>\n<li>\u30ad\u30e3\u30e9\u30af\u30bf\u30ea\u30b9\u30c6\u30a3\u30c3\u30af\u306e\u53d6\u5f97(service.getCharacteristic)<\/li>\n<li>\u30ad\u30e3\u30e9\u30af\u30bf\u30ea\u30b9\u30c6\u30a3\u30c3\u30af\u306bvalue\u3092\u66f8\u304d\u8fbc\u3080(characteristic.writeValue)<\/li>\n<\/ol>\n<p>\u4e0a\u8a18\u306e\u6d41\u308c\u3092\u30b3\u30fc\u30c9\u306b\u3059\u308b\u3068\u3053\u3046\u306a\u308a\u307e\u3059\u3002<\/p>\n<pre class=\"lang:js decode:true \" >navigator.bluetooth.requestDevice(options) \/\/\u30c7\u30d0\u30a4\u30b9\u306e\u30b9\u30ad\u30e3\u30f3\u3092\u958b\u59cb\r\n  .then(device =&gt; {\r\n    console.log(\"\u30c7\u30d0\u30a4\u30b9\u3092\u53d6\u5f97\u3057\u307e\u3057\u305f\", device);    \r\n    return device.gatt.connect();\r\n  })\r\n  .then(server =&gt;{\r\n    console.log(\"GATT\u30b5\u30fc\u30d0\u30fc\u306b\u63a5\u7d9a\u3057\u307e\u3057\u305f\", server);\r\n    return server.getPrimaryService(LED_SERVICE_UUID);\r\n  })\r\n  .then(service =&gt; {\r\n    console.log(\"\u30b5\u30fc\u30d3\u30b9\u3092\u53d6\u5f97\u3057\u307e\u3057\u305f\", service);\r\n    return service.getCharacteristic(LED_TEXT_CHARACTERISTIC_UUID);\r\n  })\r\n  .then(chara =&gt; {\r\n    console.log(\"\u30ad\u30e3\u30e9\u30af\u30bf\u30ea\u30b9\u30c6\u30a3\u30c3\u30af\u3092\u53d6\u5f97\u3057\u307e\u3057\u305f\", chara);\r\n    chara.writeValue(value);  \/\/\u5024\u3092\u66f8\u304d\u8fbc\u3080\r\n  })  \r\n  .catch(error =&gt; {\r\n    console.log(error);\r\n  });    <\/pre>\n<h2>LED\u3001\u30c6\u30ad\u30b9\u30c8\u8868\u793a\u30b5\u30f3\u30d7\u30eb<\/h2>\n<p>\u30d6\u30e9\u30a6\u30b6\u4e0a\u304b\u3089Micro:bit\u306b\u30c6\u30ad\u30b9\u30c8\u30c7\u30fc\u30bf\u3092\u9001\u4fe1\u3057\u3001LED\u306b\u8868\u793a\u3059\u308b\u30b5\u30f3\u30d7\u30eb\u3067\u3059\u3002<\/p>\n<blockquote class=\"twitter-tweet\" data-width=\"550\" data-dnt=\"true\">\n<p lang=\"ja\" dir=\"ltr\">Web Bluetooth API\u3067\u63a5\u7d9a\u3002<a href=\"https:\/\/twitter.com\/hashtag\/microbit?src=hash&amp;ref_src=twsrc%5Etfw\">#microbit<\/a> <a href=\"https:\/\/twitter.com\/hashtag\/chibibit?src=hash&amp;ref_src=twsrc%5Etfw\">#chibibit<\/a> <a href=\"https:\/\/t.co\/T11xDeiidG\">pic.twitter.com\/T11xDeiidG<\/a><\/p>\n<p>&mdash; \u6e05\u6c34\u6b63\u884c (@_shimizu) <a href=\"https:\/\/twitter.com\/_shimizu\/status\/895045902879948800?ref_src=twsrc%5Etfw\">August 8, 2017<\/a><\/p><\/blockquote>\n<p><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>\n<p><a href=\"https:\/\/shimz.me\/example\/WebBluetooth\/02\/index.html\">example<\/a><\/p>\n<pre class=\"lang:xhtml decode:true \" >&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n&lt;meta charset=\"utf-8\" \/&gt;\r\n&lt;meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"\/&gt;\r\n&lt;title&gt;&lt;\/title&gt;\r\n&lt;\/head&gt;\r\n\r\n&lt;body&gt;\r\n&lt;button id=\"connect\"&gt;\u63a5\u7d9a&lt;\/button&gt;\r\n&lt;button id=\"disconnect\"&gt;\u5207\u65ad&lt;\/button&gt;\r\n&lt;input id=\"message\" value=\"hello\" \/&gt;\r\n&lt;button id=\"send\"&gt;\u9001\u4fe1&lt;\/button&gt;\r\n\r\n&lt;script src=\"\/\/cdnjs.cloudflare.com\/ajax\/libs\/d3\/4.3.0\/d3.min.js\"&gt;&lt;\/script&gt;    \r\n    \r\n&lt;script&gt;\r\nvar bluetoothDevice;\r\nvar characteristic;\r\n\r\n\/\/chibi:bit BLE UUID\r\nvar LED_SERVICE_UUID                        = 'e95dd91d-251d-470a-a062-fa1922dfa9a8';\r\nvar LED_TEXT_CHARACTERISTIC_UUID            = 'e95d93ee-251d-470a-a062-fa1922dfa9a8';\r\n\r\n\r\n\/\/\u30dc\u30bf\u30f3\u30a4\u30d9\u30f3\u30c8\u30ea\u30b9\u30ca\u30fc\r\nd3.select(\"#connect\").on(\"click\", connect);\r\nd3.select(\"#disconnect\").on(\"click\", disconnect);    \r\nd3.select(\"#send\").on(\"click\", sendMessage);    \r\n\r\n\r\n\/\/chibi:bit\u306b\u63a5\u7d9a\u3059\u308b\r\nfunction connect() {\r\n  let options = {};\r\n\r\n  \r\n  \/\/options.acceptAllDevices = true;\r\n  \r\n  options.filters = [\r\n    {services: [LED_SERVICE_UUID]}, \/\/ <- \u91cd\u8981\r\n    {name: \"BBC micro:bit [vaget]\"}\r\n  ];\r\n  \r\n  navigator.bluetooth.requestDevice(options)\r\n  .then(device =&gt; {\r\n    bluetoothDevice = device;\r\n    console.log(\"device\", device);\r\n    return device.gatt.connect();\r\n  })\r\n  .then(server =&gt;{\r\n    console.log(\"server\", server)\r\n    return server.getPrimaryService(LED_SERVICE_UUID);\r\n  })\r\n  .then(service =&gt; {\r\n    console.log(\"service\", service)\r\n    return service.getCharacteristic(LED_TEXT_CHARACTERISTIC_UUID)\r\n  })\r\n  .then(chara =&gt; {\r\n    console.log(\"characteristic\", chara)\r\n    alert(\"BLE\u63a5\u7d9a\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3002\");\r\n    characteristic = chara;\r\n  })  \r\n  .catch(error =&gt; {\r\n    console.log(error);\r\n  });    \r\n}\r\n\r\n\/\/LED\u306b\u8868\u793a\u3059\u308b\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u9001\u4fe1\r\nfunction sendMessage() {\r\n  if (!bluetoothDevice || !bluetoothDevice.gatt.connected || !characteristic) return ;\r\n  var text = document.querySelector(\"#message\").value;\r\n  var arrayBuffe = new TextEncoder().encode(text);\r\n  characteristic.writeValue(arrayBuffe);        \r\n}\r\n\r\n\r\n\/\/BEL\u5207\u65ad\u51e6\u7406\r\nfunction disconnect() {\r\n  if (!bluetoothDevice || !bluetoothDevice.gatt.connected) return ;\r\n  bluetoothDevice.gatt.disconnect();\r\n  alert(\"BLE\u63a5\u7d9a\u3092\u5207\u65ad\u3057\u307e\u3057\u305f\u3002\")\r\n}\r\n\r\n&lt;\/script&gt;    \r\n&lt;\/body&gt;\r\n&lt;\/html&gt;\r\n<\/pre>\n<h2>\u30dd\u30a4\u30f3\u30c8<\/h2>\n<p>BLE\uff08Bluetooth Low Energy\uff09\u306b\u3064\u3044\u3066\u3042\u307e\u308a\u8a73\u3057\u304f\u306a\u304f\u3066\u3082\u3001\u7d50\u69cb\u3059\u3093\u306a\u308a\u3068\u3064\u306a\u304c\u308a\u307e\u3057\u305f\u3002<br \/>\n\u305f\u3060\u3001\u3044\u304f\u3064\u304b\u30cf\u30de\u308a\u3069\u3053\u308d\u304c\u3042\u3063\u305f\u306e\u3067\u63b2\u8f09\u3057\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n<ul>\n<li>\u5f53\u7136\u3067\u3059\u304cSSL\u5fc5\u9808<\/li>\n<li>\u30b5\u30fc\u30d3\u30b9\u3092\u5229\u7528\u3059\u308b\u306b\u306f\u3001requestDevice\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3067\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u3057\u3066\u304a\u304f\u5fc5\u8981\u304c\u3042\u308b\u3002\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u3057\u3066\u3044\u306a\u3044\u3068\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30a8\u30e9\u30fc\u304c\u3067\u308b\u3002<\/li>\n<li>writeValue\u30e1\u30bd\u30c3\u30c9\u3067\u30c6\u30ad\u30b9\u30c8\u3092\u66f8\u304d\u8fbc\u3080\u969b\u3001String\u578b\u3092ArrayBuffer or ArrayBufferView\u306b\u5909\u63db\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u3002<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\u6982\u8981 \u300cReveal.js\u3092Micro:bit(c&hellip;<\/p>\n","protected":false},"author":1,"featured_media":5459,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[70],"tags":[],"class_list":["post-5456","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microbit","has-post-thumbnail-archive"],"_links":{"self":[{"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/posts\/5456","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/comments?post=5456"}],"version-history":[{"count":1,"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/posts\/5456\/revisions"}],"predecessor-version":[{"id":5461,"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/posts\/5456\/revisions\/5461"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/media\/5459"}],"wp:attachment":[{"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/media?parent=5456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/categories?post=5456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gunmagisgeek.com\/blog\/wp-json\/wp\/v2\/tags?post=5456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}