{"id":17,"date":"2020-10-24T12:11:11","date_gmt":"2020-10-24T12:11:11","guid":{"rendered":"https:\/\/www.bleuio.com\/blog\/?p=17"},"modified":"2022-01-24T14:55:08","modified_gmt":"2022-01-24T14:55:08","slug":"interact-with-bluetooth-devices-using-google-chrome","status":"publish","type":"post","link":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/","title":{"rendered":"Interact with Bluetooth devices using Google Chrome"},"content":{"rendered":"\n<p>Bluetooth is a wireless technology that enables the transfer of data between Bluetooth enabled devices within a short distance. The&nbsp;<em>Bluetooth<\/em>\u00ae community is making significant improvement in wireless innovation every year.<\/p>\n\n\n\n<p><strong>Bluetooth Low Energy<\/strong><\/p>\n\n\n\n<p>Bluetooth Low Energy is known under many names: BLE, Bluetooth LE&nbsp;or Bluetooth Smart. The strength of&nbsp;<strong>Bluetooth Low Energy<\/strong>&nbsp;is indeed its very low energy consumption which is cost-effective with a significant battery lifetime. The BLE technology provides an easy and reliable interface, which is hugely appreciated by mobile application developers, consumer electronics manufacturers and engineers. It is an industry-specific technologywhich has become suitable for the Internet of Things (IoT) allowing a quick transfer of low-consuming data such as movement, humidity or temperature.<\/p>\n\n\n\n<p>Usually, Bluetooth is used to pair mobile devices with other mobile or fixed devices. This could be your car, your earbuds, your smartwatch or your smart light. We have seen a lot of native app available that can interact with Bluetooth enabled devices, but how about connecting using a web browser? Yes, you can communicate with nearby Bluetooth devices using a web site in a secure and privacy-preserving way.<\/p>\n\n\n\n<p>A BLE device may have two roles, central or peripheral:<\/p>\n\n\n\n<p><strong>Central:&nbsp;<\/strong>Central device manages the overall process by doing the scanning and connection to peripheral devices.<\/p>\n\n\n\n<p><strong>Peripheral:&nbsp;<\/strong>Peripheral device provides connections and data transfer with the Central device periodically.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/max\/601\/0*oKoIkJ0HLqp9lahH.png\" alt=\"Image for post\"\/><\/figure>\n\n\n\n<p>In this article, we will try to connect BLE device with a web browser.<\/p>\n\n\n\n<p>Things we need :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Google chrome<\/li><li><a href=\"https:\/\/www.bleuio.com\/\">BleuIO, Bluetooth Low Energy Adapter<\/a>&nbsp;*<\/li><\/ul>\n\n\n\n<p>* The BleuIO is Bluetooth low energy solution that can be used to create new BLE 5.0 applications in the fastest and easiest way. This device supports Windows 10, Linux and macOS.<\/p>\n\n\n\n<p><strong>Before we start<\/strong><\/p>\n\n\n\n<p>The article assumes you have some general knowledge of how Bluetooth Low Energy (BLE) work.<\/p>\n\n\n\n<p>Since the&nbsp;<a href=\"https:\/\/developer.chrome.com\/apps\/serial\">Chrome Serial<\/a>&nbsp;specification on Google Chrome is not finalized yet, you will have to go to enable the highlighted flag, and restart Chrome.<\/p>\n\n\n\n<p>open&nbsp;<strong>chrome:\/\/flags\/#enable-experimental-web-platform-features<\/strong>&nbsp;in chrome browser.<\/p>\n\n\n\n<p>In this example, we\u2019re going to use javascript + html (and some css for styling) to setup the BleuIO and quickly start scanning or advertising as an iBeacon or an Eddystone simply by pressing a button. For a quick setup, copy the following script and save it in your local directory. You can also get the source code from&nbsp;<a href=\"https:\/\/github.com\/smart-sensor-devices-ab\/web_bluetooth\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>GITHUB PAGE<\/strong><\/a>.<\/p>\n\n\n\n<p>Here is a demo of final output.&nbsp;<a href=\"https:\/\/smart-sensor-devices-ab.github.io\/web_bluetooth\/\"><strong>View Demo<\/strong><\/a><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/max\/1145\/0*VCqTt_pu99j75Uru.png\" alt=\"Image for post\"\/><\/figure>\n\n\n\n<p><strong>index.html<\/strong><\/p>\n\n\n\n<p>Here we create a simple html page with a title, buttons and a field to display the output. We also add a textbox that will show up if the user doesn\u2019t meet the requirements for Chrome Serial.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;!DOCTYPE html&gt;<br>&lt;<strong>html<\/strong> lang=\"en\"&gt;<br>  &lt;<strong>head<\/strong>&gt;<br>    &lt;<strong>title<\/strong>&gt;Smart Sensor Devices Web Bluetooth Example&lt;\/<strong>title<\/strong>&gt;<br>    &lt;<strong>meta<\/strong> charset=\"utf-8\" \/&gt;<br>    &lt;<strong>meta<\/strong> name=\"ssd\" content=\"beaconexample\" \/&gt;<br>    &lt;<strong>meta<\/strong> http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" \/&gt;<br>    &lt;<strong>meta<\/strong> name=\"viewport\" content=\"width=device-width, initial-scale=1\" \/&gt;<br>    &lt;<strong>link<\/strong> rel=\"shortcut icon\" type=\"image\/png\" href=\"images\/favicon.png\" \/&gt;    &lt;<strong>script<\/strong>&gt;<br>      \/\/ Redirect to HTTPS if HTTP is requested.<br>      <strong>if<\/strong> (window.location.protocol === \"http:\") {<br>        window.location.href = \"https:\" + window.location.href.substring(5);<br>      }<br>    &lt;\/<strong>script<\/strong>&gt;<br>    &lt;<strong>link<\/strong> rel=\"stylesheet\" href=\"style.css\" \/&gt;<br>    &lt;<strong>link<\/strong><br>      rel=\"stylesheet\"<br>      href=\"https:\/\/stackpath.bootstrapcdn.com\/bootstrap\/4.5.2\/css\/bootstrap.min.css\"<br>      integrity=\"sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z\"<br>      crossorigin=\"anonymous\"<br>    \/&gt;    &lt;<strong>script<\/strong> src=\"script.js\" defer&gt;&lt;\/<strong>script<\/strong>&gt;<br>  &lt;\/<strong>head<\/strong>&gt;<br>  &lt;<strong>body<\/strong>&gt;<br>    &lt;<strong>div<\/strong> class=\"codesection\"&gt;<br>      &lt;<strong>div<\/strong> class=\"container\"&gt;<br>        &lt;<strong>h1<\/strong>&gt;Web Bluetooth Example&lt;\/<strong>h1<\/strong>&gt;<br>        &lt;<strong>main<\/strong> class=\"main\"&gt;<br>          &lt;<strong>div<\/strong> id=\"notSupported\" class=\"hidden\"&gt;<br>            Sorry, &lt;<strong>b<\/strong>&gt;Chrome Serial&lt;\/<strong>b<\/strong>&gt; is not supported on this device, make sure<br>            you're running Chrome 78 or later and have enabled the<br>            &lt;<strong>code<\/strong>&gt;#enable-experimental-web-platform-features&lt;\/<strong>code<\/strong>&gt; flag in<br>            &lt;<strong>code<\/strong>&gt;chrome:\/\/flags&lt;\/<strong>code<\/strong>&gt;<br>          &lt;\/<strong>div<\/strong>&gt;          &lt;<strong>br<\/strong> \/&gt;<br>          &lt;<strong>button<\/strong> id=\"butConnect\" type=\"button\" class=\"btn btn-success\"&gt;<br>            Connect<br>          &lt;\/<strong>button<\/strong>&gt;<br>          &lt;<strong>br<\/strong> \/&gt;&lt;<strong>br<\/strong> \/&gt;<br>          &lt;<strong>button<\/strong><br>            id=\"butIbeacon\"<br>            type=\"button\"<br>            disabled<br>            class=\"btn btn-warning\"<br>          &gt;<br>            Make iBeacon<br>          &lt;\/<strong>button<\/strong>&gt;<br>          &lt;<strong>button<\/strong> id=\"butEddystone\" type=\"button\" disabled class=\"btn btn-info\"&gt;<br>            Make Eddystone Beacon<br>          &lt;\/<strong>button<\/strong>&gt;<br>          &lt;<strong>button<\/strong> id=\"butScan\" type=\"button\" disabled class=\"btn btn-primary\"&gt;<br>            Scan BLE Devices<br>          &lt;\/<strong>button<\/strong>&gt;          &lt;<strong>pre<\/strong> id=\"log\" class=\"mt-5\"&gt;&lt;\/<strong>pre<\/strong>&gt;<br>        &lt;\/<strong>main<\/strong>&gt;<br>      &lt;\/<strong>div<\/strong>&gt;<br>    &lt;\/<strong>div<\/strong>&gt;<br>    &lt;<strong>div<\/strong> class=\"footer text-center mt-3\"&gt;<br>      Powered by &lt;<strong>a<\/strong> href=\"https:\/\/www.bleuio.com\/\" target=\"_blank\"&gt;BleuIO&lt;\/<strong>a<\/strong>&gt; .<br>      A product of<br>      &lt;<strong>a<\/strong> href=\"http:\/\/smartsensordevices.com\/\" target=\"_blank\"<br>        &gt;Smart Sensor Devices&lt;\/<strong>a<\/strong><br>      &gt;<br>    &lt;\/<strong>div<\/strong>&gt;    &lt;!-- end container --&gt;<br>    &lt;!-- JS, Popper.js, and jQuery --&gt;<br>    &lt;<strong>script<\/strong><br>      src=\"https:\/\/code.jquery.com\/jquery-3.5.1.slim.min.js\"<br>      integrity=\"sha384-DfXdz2htPH0lsSSs5nCTpuj\/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj\"<br>      crossorigin=\"anonymous\"<br>    &gt;&lt;\/<strong>script<\/strong>&gt;<br>    &lt;<strong>script<\/strong><br>      src=\"https:\/\/cdn.jsdelivr.net\/npm\/popper.js@1.16.1\/dist\/umd\/popper.min.js\"<br>      integrity=\"sha384-9\/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN\"<br>      crossorigin=\"anonymous\"<br>    &gt;&lt;\/<strong>script<\/strong>&gt;<br>    &lt;<strong>script<\/strong><br>      src=\"https:\/\/stackpath.bootstrapcdn.com\/bootstrap\/4.5.2\/js\/bootstrap.min.js\"<br>      integrity=\"sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8\/KUEfYiJOMMV+rV\"<br>      crossorigin=\"anonymous\"<br>    &gt;&lt;\/<strong>script<\/strong>&gt;<br>  &lt;\/<strong>body<\/strong>&gt;<br>&lt;\/<strong>html<\/strong>&gt;<\/pre>\n\n\n\n<p><strong>script.js<\/strong><\/p>\n\n\n\n<p>Here we is were we handle the functionality. We hook up our buttons with click-listeners and write the functions we need.<\/p>\n\n\n\n<p>By running:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">port = await navigator.serial.requestPort();<\/pre>\n\n\n\n<p>from the serial api we can get list of avalible com ports. Then we connect to that port and start listening for input from the dongle.<\/p>\n\n\n\n<p>The \u201cmake beacon\u201d button functions are setup with a static version of the iBeacon and Eddystone but you can just as easily hook up an input field and plug in the value in the \u2018writeCmd()\u2019 function in a similar fashion of that of the&nbsp;<a href=\"https:\/\/smart-sensor-devices-ab.github.io\/ssd005-manual\/docs\/ibeaconscript\">iBeacon<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/smart-sensor-devices-ab.github.io\/ssd005-manual\/docs\/eddystonebeaconscript\">Eddystone<\/a>&nbsp;examples.<\/p>\n\n\n\n<p>In the \u2018readLoop()\u2019 function we just print out everything we get from the dongle to the \u2018log\u2019 element. But you could just as well listen for the response message after a command that signals that the action has been successful or not (like OK, ADVERTISING or ERROR etc.) and handle that and print what you like as response.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\"use strict\";let port;<br>let reader;<br>let inputDone;<br>let outputDone;<br>let inputStream;<br>let outputStream;<br>let isIbeaconAdv = false;<br>let isEddystonesAdv = false;<br>let isScanning = false;const log = document.getElementById(\"log\");<br>const butIbeacon = document.getElementById(\"butIbeacon\");<br>const butEddystone = document.getElementById(\"butEddystone\");<br>const butConnect = document.getElementById(\"butConnect\");<br>const butScan = document.getElementById(\"butScan\");document.addEventListener(\"DOMContentLoaded\", () =&gt; {<br>  butIbeacon.addEventListener(\"click\", clickIbeacon);<br>  butEddystone.addEventListener(\"click\", clickEddystone);<br>  butScan.addEventListener(\"click\", clickScan);<br>  butConnect.addEventListener(\"click\", clickConnect);<br>  const notSupported = document.getElementById(\"notSupported\");<br>  notSupported.classList.toggle(\"disabled\", \"serial\" in navigator);<br>});<em>\/**<br> * @name connect<br> * Opens a Chrome Serial connection to a serial device such as a Smart USB Dongle 2.0 and sets up the input and<br> * output stream.<br> *\/<\/em><br>async function connect() {<br>  <em>\/\/ - Request a port and open a connection.<\/em><br>  port = await navigator.serial.requestPort();<br>  <em>\/\/ - Wait for the port to open.<\/em><br>  await port.open({ baudrate: 9600 });  const encoder = new TextEncoderStream();<br>  outputDone = encoder.readable.pipeTo(port.writable);<br>  outputStream = encoder.writable;  let decoder = new TextDecoderStream();<br>  inputDone = port.readable.pipeTo(decoder.writable);<br>  inputStream = decoder.readable.pipeThrough(<br>    new TransformStream(new LineBreakTransformer())<br>  );  reader = inputStream.getReader();<br>  readLoop().catch((error) =&gt; {<br>    toggleUIConnected(false);<br>    port = null;<br>    log.textContent = \"Dongle Disconnected!\";<br>  });<br>}<em>\/**<br> * @name disconnect<br> * Closes the Chrome Serial connection.<br> *\/<\/em><br>async function disconnect() {<br>  <em>\/\/ Close the input stream (reader).<\/em><br>  if (reader) {<br>    await reader.cancel();<br>    await inputDone.catch(() =&gt; {});<br>    reader = null;<br>    inputDone = null;<br>  }<br>  <em>\/\/ Close the output stream.<\/em><br>  if (outputStream) {<br>    await outputStream.getWriter().close();<br>    await outputDone;<br>    outputStream = null;<br>    outputDone = null;<br>  }<br>  <em>\/\/ Close the port.<\/em><br>  await port.close();<br>  port = null;<br>  log.textContent = \"Dongle Disconnected!\";<br>}<em>\/**<br> * @name clickConnect<br> * Click handler for the connect\/disconnect button.<br> * Checks if port != null<br> * If true: Checks if any beacons is advertising or scans are running and stops the advertsing or scan if so. Then runs disconnect() and set toggleUIConnected to false.<br> * if false: Runs connect() then set toggleUIConnected to true.<br> *\/<\/em><br>async function clickConnect() {<br>  log.textContent = \"\";<br>  if (port) {<br>    if (isEddystonesAdv || isIbeaconAdv) {<br>      writeCmd(\"AT+ADVSTOP\");<br>      butIbeacon.textContent = \"Make iBeacon\";<br>      butEddystone.textContent = \"Make Eddystone Beacon\";<br>      isIbeaconAdv = false;<br>      isEddystonesAdv = false;<br>    }<br>    <em>\/\/ If disconnected while scanning the dongle will restart<\/em><br>    if (isScanning) {<br>      writeCmd(\"\\x03\");<br>      butScan.textContent = \"Scan BLE Devices\";<br>      isScanning = false;<br>    }<br>    await disconnect();<br>    toggleUIConnected(false);<br>    return;<br>  }<br>  await connect();<br>  toggleUIConnected(true);<br>}<em>\/**<br> * @name clickIbeacon<br> * Click handler for the iBeacon button.<br> * Checks if an iBeacon is already running by checking the boolean isIbeaconAdv.<br> * If isIbeaconAdv = true: Stops advertising, changes the button text and shows the Eddystone button. Finally sets isEddystoneAdv = false.<br> * If isIbeaconAdv = false: Sets the advertising data to setup an iBeacon with a UUID and starts advertising.<br> * Also changes button text and hides the Eddystone button. Finally sets isIbeaconAdv = true.<br> *\/<\/em><br>function clickIbeacon() {<br>  console.log(\"IBEACON BUTTON PRESSED\");  if (isIbeaconAdv) {<br>    writeCmd(\"AT+ADVSTOP\");<br>    butEddystone;<br>    butIbeacon.textContent = \"Make iBeacon\";<br>    butEddystone.removeAttribute(\"disabled\");<br>    butScan.removeAttribute(\"disabled\");<br>    isIbeaconAdv = false;<br>    return;<br>  }<br>  writeCmd(\"AT+ADVDATAI=5f2dd896-b886-4549-ae01-e41acd7a354a0203010400\");<br>  setTimeout(() =&gt; {<br>    writeCmd(\"AT+ADVSTART=0;200;3000;0;\");<br>  }, 500); <em>\/\/ Waiting half a bit to make sure each command will get through separately.<\/em>  butIbeacon.textContent = \"Stop Beacon\";<br>  butEddystone.setAttribute(\"disabled\", \"true\");<br>  butScan.setAttribute(\"disabled\", \"true\");<br>  isIbeaconAdv = true;<br>}<em>\/**<br> * @name clickEddystone<br> * Click handler for the Eddystone Beacon button.<br> * Checks if an Eddystone beacon is already running by checking the boolean isEddystoneAdv.<br> * If isEddystoneAdv = true: Stops advertising, changes the button text and shows the iBeacon button. Finally sets isEddystoneAdv = false.<br> * If isEddystoneAdv = false: Sets the advertising data to setup an Eddystone beacon with a link to google.com and starts advertising.<br> * Also changes button text and hides the iBeacon button. Finally sets isEddystoneAdv = true.<br> *\/<\/em><br>function clickEddystone() {<br>  console.log(\"EDDYSTONE BUTTON PRESSED\");<br>  if (isEddystonesAdv) {<br>    writeCmd(\"AT+ADVSTOP\");<br>    butEddystone.textContent = \"Make Eddystone Beacon\";<br>    butIbeacon.removeAttribute(\"disabled\");<br>    butScan.removeAttribute(\"disabled\");<br>    isEddystonesAdv = false;<br>    return;<br>  }<br>  writeCmd(\"AT+ADVDATA=03:03:aa:fe 0d:16:aa:fe:10:00:03:67:6f:6f:67:6c:65:07\");<br>  setTimeout(() =&gt; {<br>    writeCmd(\"AT+ADVSTART=0;200;3000;0;\");<br>  }, 500); <em>\/\/ Waiting half a bit to make sure each command will get through separately.<\/em>  <em>\/\/butIbeacon.classList.toggle(\"disabled\", true);<\/em><br>  butIbeacon.setAttribute(\"disabled\", \"true\");<br>  butScan.setAttribute(\"disabled\", \"true\");  <em>\/\/butScan.classList.toggle(\"disabled\", true);<\/em><br>  butEddystone.textContent = \"Stop Beacon\";<br>  isEddystonesAdv = true;<br>}<em>\/**<br> * @name clickScan<br> * Click handler for the Scan button.<br> * Checks if a scan is already running by checking the boolean isScanning.<br> * If isScanning = true: Stops scanning and goes back to peripheral mode, changes the button text and shows the beacon buttons. Finally sets isScanning = false.<br> * If isScanning = false: Goes into Central mode and starts scanning for ble devices. Also changes button text and hides the beacon buttons. Finally sets isScanning = true.<br> *\/<\/em><br>function clickScan() {<br>  console.log(\"SCAN BUTTON PRESSED\");<br>  if (isScanning) {<br>    writeCmd(\"\\x03\"); <em>\/\/ Ctrl+C to stop the scan<\/em><br>    setTimeout(() =&gt; {<br>      writeCmd(\"AT+PERIPHERAL\"); <em>\/\/ Set the dongle in Peripheral mode needed for advertising.<\/em><br>    }, 500); <em>\/\/ Waiting half a bit to make sure each command will get through separately.<\/em><br>    isScanning = false;<br>    butScan.textContent = \"Scan BLE Devices\";<br>    butIbeacon.removeAttribute(\"disabled\");<br>    butEddystone.removeAttribute(\"disabled\");<br>    return;<br>  }<br>  writeCmd(\"AT+CENTRAL\"); <em>\/\/ Set the dongle in Central mode needed for scanning.<\/em><br>  setTimeout(() =&gt; {<br>    writeCmd(\"AT+GAPSCAN\");<br>  }, 500); <em>\/\/ Waiting half a bit to make sure each command will get through separately.<\/em>  butScan.textContent = \"Stop Scanning...\";<br>  butIbeacon.setAttribute(\"disabled\", \"true\");<br>  butEddystone.setAttribute(\"disabled\", \"true\");  isScanning = true;<br>}<em>\/**<br> * @name readLoop<br> * Reads data from the input stream and displays it on screen.<br> *\/<\/em><br>async function readLoop() {<br>  while (true) {<br>    const { value, done } = await reader.read();<br>    if (value) {<br>      log.textContent += value + \"\\n\";<br>    }<br>    if (done) {<br>      console.log(\"[readLoop] DONE\", done);<br>      reader.releaseLock();<br>      break;<br>    }<br>  }<br>}<em>\/**<br> * @name writeCmd<br> * Gets a writer from the output stream and send the command to the Smart USB Dongle 2.0.<br> * @param  {string} cmd command to send to the Smart USB Dongle 2.0<br> *\/<\/em><br>function writeCmd(cmd) {<br>  <em>\/\/ Write to output stream<\/em><br>  const writer = outputStream.getWriter();<br>  console.log(\"[SEND]\", cmd);  writer.write(cmd);<br>  <em>\/\/ Ignores sending carriage return if sending Ctrl+C<\/em><br>  if (cmd !== \"\\x03\") {<br>    writer.write(\"\\r\"); <em>\/\/ Important to send a carriage return after a command<\/em><br>  }<br>  writer.releaseLock();<br>}<em>\/**<br> * @name LineBreakTransformer<br> * TransformStream to parse the stream into lines.<br> *\/<\/em><br>class LineBreakTransformer {<br>  constructor() {<br>    <em>\/\/ A container for holding stream data until a new line.<\/em><br>    this.container = \"\";<br>  }  transform(chunk, controller) {<br>    <em>\/\/ Handle incoming chunk<\/em><br>    this.container += chunk;<br>    const lines = this.container.split(\"\\r\\n\");<br>    this.container = lines.pop();<br>    lines.forEach((line) =&gt; controller.enqueue(line));<br>  }  flush(controller) {<br>    <em>\/\/ Flush the stream.<\/em><br>    controller.enqueue(this.container);<br>  }<br>}<em>\/**<br> * @name toggleUIConnected<br> * Toggles the butIbeacon &amp; butEddystone buttons visable\/hidden depending on if dongle is connected or not.<br> * Also changes the text on butConnect depending on the action it actually will preform in the current state.<br> * @param  {boolean} connected true if connected, false if disconnected.<br> *\/<\/em><br>function toggleUIConnected(connected) {<br>  let lbl = \"Connect\";<br>  if (connected) {<br>    lbl = \"Disconnect\";<br>    butIbeacon.removeAttribute(\"disabled\");<br>    butEddystone.removeAttribute(\"disabled\");<br>    butScan.removeAttribute(\"disabled\");<br>  }<br>  butIbeacon.classList.toggle(\"disabled\", !connected);<br>  butEddystone.classList.toggle(\"disabled\", !connected);<br>  butScan.classList.toggle(\"disabled\", !connected);<br>  butConnect.textContent = lbl;<br>}<\/pre>\n\n\n\n<p><strong>style.css<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">.hidden {<br>  display: none !important;<br>}#notSupported {<br>  padding: 1em;<br>  background-color: red;<br>  color: white;<br>  margin-top: 1em;<br>  margin-bottom: 1em;<br>}.mb-button {<br>  align-self: center;<br>  background-color: #666;<br>  border-radius: 100%;<br>  box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 2px 9px 1px rgba(0, 0, 0, 0.12),<br>    0 4px 2px -2px rgba(0, 0, 0, 0.2);<br>  height: 30px;<br>  width: 30px;<br>}.pressed {<br>  background-color: #d81b60;<br>  box-shadow: inset 0px 0px 5px #c1c1c1;<br>  outline: none;<br>}<br>.caption {<br>  margin-top: 100px;<br>}<br>pre {<br>  padding: 20px;<br>  color: #ffffff !important;<br>  background-color: #222;<br>  white-space: pre;<br>  text-shadow: 0 1px 0 #000;<br>  border-radius: 5px;<br>  border-bottom: 1px solid #555;<br>  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4) inset, 0 0 20px rgba(0, 0, 0, 0.2) inset;<br>  font: 16px\/24px \"Courier New\", Courier, \"Lucida Sans Typewriter\", \"Lucida Typewriter\",<br>    monospace;<br>}<br>.codesection {<br>  background: #0d4c8d;<br>  color: white;<br>  padding: 20px 0;<br>  min-height: 500px;<br>}<\/pre>\n\n\n\n<p>Run the web app by simply opening&nbsp;<code><strong>index.html<\/strong><\/code>in the Chrome web browser.<\/p>\n\n\n\n<p>Make sure&nbsp;<strong>BleuIO&nbsp;<\/strong>is connected to your computer. Click&nbsp;<strong>Connect&nbsp;<\/strong>and wait a moment for your device to show up on the port screen.<\/p>\n\n\n\n<p>Select your device and press&nbsp;<strong>Connect<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/max\/873\/0*bqWHRFjyrMG8LeIx.jpg\" alt=\"Image for post\"\/><\/figure>\n\n\n\n<p>Once the device is connected. You will be able to use all the example script we prepared \u2014 IBeacon, Eddystone Beacon, Scan.<\/p>\n\n\n\n<p>Follow this video for more details.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Connect to Bluetooth device using Google Chrome with BleuIO\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/EIoh2SVa18Y?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Bluetooth is a wireless technology that enables the transfer of data between Bluetooth enabled devices within a short distance. The&nbsp;Bluetooth\u00ae community is making significant improvement in wireless innovation every year. Bluetooth Low Energy Bluetooth Low Energy is known under many names: BLE, Bluetooth LE&nbsp;or Bluetooth Smart. The strength of&nbsp;Bluetooth Low Energy&nbsp;is indeed its very low [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":18,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,2],"tags":[],"class_list":["post-17","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-bleuio","category-bleuio-tutorial"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Interact with Bluetooth devices using Google Chrome - BleuIO - Create Bluetooth Low Energy application<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Interact with Bluetooth devices using Google Chrome - BleuIO - Create Bluetooth Low Energy application\" \/>\n<meta property=\"og:description\" content=\"Bluetooth is a wireless technology that enables the transfer of data between Bluetooth enabled devices within a short distance. The&nbsp;Bluetooth\u00ae community is making significant improvement in wireless innovation every year. Bluetooth Low Energy Bluetooth Low Energy is known under many names: BLE, Bluetooth LE&nbsp;or Bluetooth Smart. The strength of&nbsp;Bluetooth Low Energy&nbsp;is indeed its very low [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/\" \/>\n<meta property=\"og:site_name\" content=\"BleuIO - Create Bluetooth Low Energy application\" \/>\n<meta property=\"article:published_time\" content=\"2020-10-24T12:11:11+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-01-24T14:55:08+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.bleuio.com\/blog\/wp-content\/uploads\/2022\/01\/0_C3LWl-21_twLTiQD.png\" \/>\n\t<meta property=\"og:image:width\" content=\"700\" \/>\n\t<meta property=\"og:image:height\" content=\"309\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"BleuIO\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/\"},\"author\":{\"name\":\"BleuIO\",\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/#\\\/schema\\\/person\\\/89bc581382d5964043f96efc54b75b80\"},\"headline\":\"Interact with Bluetooth devices using Google Chrome\",\"datePublished\":\"2020-10-24T12:11:11+00:00\",\"dateModified\":\"2022-01-24T14:55:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/\"},\"wordCount\":706,\"image\":{\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/0_C3LWl-21_twLTiQD.png\",\"articleSection\":[\"BleuIO\",\"BleuIO tutorial\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/\",\"url\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/\",\"name\":\"Interact with Bluetooth devices using Google Chrome - BleuIO - Create Bluetooth Low Energy application\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/0_C3LWl-21_twLTiQD.png\",\"datePublished\":\"2020-10-24T12:11:11+00:00\",\"dateModified\":\"2022-01-24T14:55:08+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/#\\\/schema\\\/person\\\/89bc581382d5964043f96efc54b75b80\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/0_C3LWl-21_twLTiQD.png\",\"contentUrl\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/0_C3LWl-21_twLTiQD.png\",\"width\":700,\"height\":309},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/interact-with-bluetooth-devices-using-google-chrome\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Interact with Bluetooth devices using Google Chrome\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/\",\"name\":\"BleuIO - Create Bluetooth Low Energy application\",\"description\":\"Learn Bluetooth Low Energy programming and build Bluetooth Low Energy Application\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/#\\\/schema\\\/person\\\/89bc581382d5964043f96efc54b75b80\",\"name\":\"BleuIO\",\"sameAs\":[\"https:\\\/\\\/www.bleuio.com\\\/blog\"],\"url\":\"https:\\\/\\\/www.bleuio.com\\\/blog\\\/author\\\/biadmin\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Interact with Bluetooth devices using Google Chrome - BleuIO - Create Bluetooth Low Energy application","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/","og_locale":"en_US","og_type":"article","og_title":"Interact with Bluetooth devices using Google Chrome - BleuIO - Create Bluetooth Low Energy application","og_description":"Bluetooth is a wireless technology that enables the transfer of data between Bluetooth enabled devices within a short distance. The&nbsp;Bluetooth\u00ae community is making significant improvement in wireless innovation every year. Bluetooth Low Energy Bluetooth Low Energy is known under many names: BLE, Bluetooth LE&nbsp;or Bluetooth Smart. The strength of&nbsp;Bluetooth Low Energy&nbsp;is indeed its very low [&hellip;]","og_url":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/","og_site_name":"BleuIO - Create Bluetooth Low Energy application","article_published_time":"2020-10-24T12:11:11+00:00","article_modified_time":"2022-01-24T14:55:08+00:00","og_image":[{"width":700,"height":309,"url":"https:\/\/www.bleuio.com\/blog\/wp-content\/uploads\/2022\/01\/0_C3LWl-21_twLTiQD.png","type":"image\/png"}],"author":"BleuIO","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/#article","isPartOf":{"@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/"},"author":{"name":"BleuIO","@id":"https:\/\/www.bleuio.com\/blog\/#\/schema\/person\/89bc581382d5964043f96efc54b75b80"},"headline":"Interact with Bluetooth devices using Google Chrome","datePublished":"2020-10-24T12:11:11+00:00","dateModified":"2022-01-24T14:55:08+00:00","mainEntityOfPage":{"@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/"},"wordCount":706,"image":{"@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/#primaryimage"},"thumbnailUrl":"https:\/\/www.bleuio.com\/blog\/wp-content\/uploads\/2022\/01\/0_C3LWl-21_twLTiQD.png","articleSection":["BleuIO","BleuIO tutorial"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/","url":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/","name":"Interact with Bluetooth devices using Google Chrome - BleuIO - Create Bluetooth Low Energy application","isPartOf":{"@id":"https:\/\/www.bleuio.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/#primaryimage"},"image":{"@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/#primaryimage"},"thumbnailUrl":"https:\/\/www.bleuio.com\/blog\/wp-content\/uploads\/2022\/01\/0_C3LWl-21_twLTiQD.png","datePublished":"2020-10-24T12:11:11+00:00","dateModified":"2022-01-24T14:55:08+00:00","author":{"@id":"https:\/\/www.bleuio.com\/blog\/#\/schema\/person\/89bc581382d5964043f96efc54b75b80"},"breadcrumb":{"@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/#primaryimage","url":"https:\/\/www.bleuio.com\/blog\/wp-content\/uploads\/2022\/01\/0_C3LWl-21_twLTiQD.png","contentUrl":"https:\/\/www.bleuio.com\/blog\/wp-content\/uploads\/2022\/01\/0_C3LWl-21_twLTiQD.png","width":700,"height":309},{"@type":"BreadcrumbList","@id":"https:\/\/www.bleuio.com\/blog\/interact-with-bluetooth-devices-using-google-chrome\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.bleuio.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Interact with Bluetooth devices using Google Chrome"}]},{"@type":"WebSite","@id":"https:\/\/www.bleuio.com\/blog\/#website","url":"https:\/\/www.bleuio.com\/blog\/","name":"BleuIO - Create Bluetooth Low Energy application","description":"Learn Bluetooth Low Energy programming and build Bluetooth Low Energy Application","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.bleuio.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.bleuio.com\/blog\/#\/schema\/person\/89bc581382d5964043f96efc54b75b80","name":"BleuIO","sameAs":["https:\/\/www.bleuio.com\/blog"],"url":"https:\/\/www.bleuio.com\/blog\/author\/biadmin\/"}]}},"_links":{"self":[{"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/posts\/17","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/comments?post=17"}],"version-history":[{"count":1,"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/posts\/17\/revisions"}],"predecessor-version":[{"id":19,"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/posts\/17\/revisions\/19"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/media\/18"}],"wp:attachment":[{"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/media?parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/categories?post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bleuio.com\/blog\/wp-json\/wp\/v2\/tags?post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}