蓝牙协议已经发展到5.3版本了,应用蓝牙的设备也越来越多,特别是随着传感器和智能硬件时代的到来,现在除了常见的蓝牙耳机还有一大批设备应用蓝牙进行通信,例如手环、手表、温度计、体重秤。
蓝牙协议的数据读写我一直很头疼,可以参考的代码较少,而且大多是安卓平台的代码,Windows平台不能说完全没有,也就那么几个,代码读起来还很奇怪。
最近发现浏览器也能读蓝牙设备了,用js语言,而且代码清晰简单,经过一天的学习取得了一点进度,分享一下。
先上代码,这个代码改了uuid直接就能跑起来。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=100, initial-scale=1.0">
<title>测试</title>
</head>
<body>
<button onclick="clickme()" class="btn">点击</button>
<div id="data"></div>
<script type="text/javascript" >
function clickme(){
readbluetooth()
.then(v => console.log(v))
.catch(e => console.log(e));
}
async function readbluetooth(){
let device = await navigator.bluetooth.requestDevice({
optionalServices: ['48093801-1a48-11e9-ab14-d663bd873d93']
, acceptAllDevices: true//设置acceptAllDevices代表查询所有蓝牙设备 也是必须配置optionalServices
});
device.addEventListener('gattserverdisconnected', onDisconnected);//监听设备断开连接
let server = await device.gatt.connect();
let service = await server.getPrimaryService('48093801-1a48-11e9-ab14-d663bd873d93');//这里需要服务UUID 还是可以提供完整的蓝牙UUID或简短的16位或32位形式
let services = await server.getPrimaryServices();
let characteristics = await service.getCharacteristics();//获取设备所有信息特征值
let characteristic = await service.getCharacteristic('48090001-1a48-11e9-ab14-d663bd873d93');//这里需要读的特征值UUID 还是可以提供完整的蓝牙UUID或简短的16位或32位形式
characteristic.startNotifications();//开始监听
characteristic.addEventListener(
'characteristicvaluechanged', e => {
//监听设备端的操作 获取到值之后再解析
console.log('e.target.value:',ab2hex(e.target.value.buffer));
document.getElementById('data').InnerText=ab2hex(e.target.value.buffer);
}
);
}
function onDisconnected(event) {
const device = event.target;
console.log(`设备: ${device.name} 已经断开连接`);
}
function string2buffer(str) {
let val = "";
if (!str) return;
let length = str.length;
let index = 0;
let array = [];
while (index < length) {
array.push(str.substring(index, index + 2));
index = index + 2;
}
val = array.join(",");
// 将16进制转化为ArrayBuffer
return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16);
})).buffer
}
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2);
}
)
return hexArr.join('');
} </script>
</body>
</html>
这个是参考了别人的一些代码写出来的,调整了一下格式,满足了一点强迫症。参考链接在最下面
重点
service的uuid一定要有。这里不对代码没法往后跑,
characteristic的uuid最好也直接写死,虽然可以读取所有可用的characteristic,但是每个uuid对应的功能是固定的,除非你不知道都对应什么功能,应该找蓝牙设备的开发者或开发文档,而不是读出来挨个猜挨个试。
service的uuid有一些是固定的,参考https://blog.csdn.net/chy555chy/article/details/52230651,这时可以用服务名代替uuid,我查到的代码很多都是用的服务名,可我的设备不是标准设备,没有服务名,给我很大困扰。直接用uuid就可以
chrome://bluetooth-internals/,这个地址是浏览器自带的蓝牙调试地址,比常见的手机蓝牙助手还好用。缺点是还处在实验阶段,有些设备可能扫描不出来,有些功能可能会部分支持,例如我的设备只能扫描别人,不能被人扫描。
参考文献
https://web.dev/i18n/zh/bluetooth/
https://github.com/WebBluetoothCG/demos/tree/gh-pages/heart-rate-sensor