UNPKG

webbluetooth

Version:

Node.js implementation of the Web Bluetooth Specification

146 lines (131 loc) 4.16 kB
/* * Node Web Bluetooth * Copyright (c) 2017 Rob Moran * * The MIT License (MIT) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // TODO: this example needs updating to use watchadvertisements const webbluetooth = require("../"); const eddystoneUUID = 0xFEAA; const frameTypes = { "UID": 0x00, "URL": 0x10, "TLM": 0x20 } const schemes = { 0x00: "http://www.", 0x01: "https://www.", 0x02: "http://", 0x03: "https://" } const expansions = { 0x00: ".com/", 0x01: ".org/", 0x02: ".edu/", 0x03: ".net/", 0x04: ".info/", 0x05: ".biz/", 0x06: ".gov/", 0x07: ".com", 0x08: ".org", 0x09: ".edu", 0x0a: ".net", 0x0b: ".info", 0x0c: ".biz", 0x0d: ".gov" } const deviceFound = bluetoothDevice => { const uuid = webbluetooth.BluetoothUUID.getService(eddystoneUUID); const eddyData = bluetoothDevice._adData.serviceData.get(uuid); if (eddyData) { const decoded = decodeEddystone(eddyData); if (decoded) { switch(decoded.type) { case frameTypes.UID: console.log(`txPower: ${decoded.txPower}`); break; case frameTypes.URL: console.log(`url: ${decoded.url}`); break; case frameTypes.TLM: console.log(`version: ${decoded.version}`); break; } } } }; const bluetooth = new webbluetooth.Bluetooth({ deviceFound }); const decodeEddystone = view => { const type = view.getUint8(0); if (typeof type === "undefined") return undefined; if (type === frameTypes.UID) { const uidArray = []; for (let i = 2; i < view.byteLength; i++) { const hex = view.getUint8(i).toString(16); uidArray.push(("00" + hex).slice(-2)); } return { type: type, txPower: view.getInt8(1), namespace: uidArray.slice(0, 10).join(), instance: uidArray.slice(10, 16).join() }; } if (type === frameTypes.URL) { const url = ""; for (let i = 2; i < view.byteLength; i++) { if (i === 2) { url += schemes[view.getUint8(i)]; } else { url += expansions[view.getUint8(i)] || String.fromCharCode(view.getUint8(i)); } } return { type: type, txPower: view.getInt8(1), url: url }; } if (type === frameTypes.TLM) { return { type: type, version: view.getUint8(1), battery: view.getUint16(2), temperature: view.getInt16(4), advCount: view.getUint32(6), secCount: view.getUint32(10) }; } } // Continuously scan (async () => { console.log("scanning..."); while (true) { try { await bluetooth.requestDevice({ filters: [{ services: [ eddystoneUUID ] }] }); } catch (error) { console.log(error); process.exit(); } } })();