Skip to content

Instantly share code, notes, and snippets.

@wwj718
Last active January 7, 2024 07:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wwj718/2c2ba8c69a2ff34daf0900bdec57bb44 to your computer and use it in GitHub Desktop.
Save wwj718/2c2ba8c69a2ff34daf0900bdec57bb44 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>MicroBlocks BLE client</title>
</head>
<body>
<button id="connect">连接 MicroBlocks 设备</button>
<input type="text" id="inputData" placeholder="输入数据" />
<button id="sendData">发送数据</button>
<div id="output"></div>
<script>
const MICROBLOCKS_SERVICE_UUID = 'bb37a001-b922-4018-8e74-e14824b3a638'
const MICROBLOCKS_RX_CHAR_UUID = 'bb37a002-b922-4018-8e74-e14824b3a638' // board receive characteristic
const MICROBLOCKS_TX_CHAR_UUID = 'bb37a003-b922-4018-8e74-e14824b3a638' // board transmit characteristic
let bleDevice = null;
let txCharacteristic = null;
let message_buffer = new Uint8Array();
// 建立蓝牙连接
document.getElementById("connect").addEventListener("click", () => {
let device = navigator.bluetooth
.requestDevice({
filters: [
{services: [MICROBLOCKS_SERVICE_UUID]}
]
})
.then((device) => {
// 处理连接断开事件
device.addEventListener('gattserverdisconnected', (event) => {alert("连接断开");});
bleDevice = device;
return device.gatt.connect();
})
.then((server) => server.getPrimaryService(MICROBLOCKS_SERVICE_UUID))
.then((service) => {
// 获取 RX 和 TX 特征
return Promise.all([
service.getCharacteristic(MICROBLOCKS_RX_CHAR_UUID),
service.getCharacteristic(MICROBLOCKS_TX_CHAR_UUID),
]);
})
.then((characteristics) => {
const [rxCharacteristic, txCharacteristic] = characteristics;
this.txCharacteristic = txCharacteristic;
// 订阅 TX 特征的通知
txCharacteristic.startNotifications().then((_) => {
txCharacteristic.addEventListener(
"characteristicvaluechanged",
handleNotifications
);
});
})
.catch((error) => {
console.log("连接错误:" + error);
});
});
// 发送蓝牙消息
document.getElementById("sendData").addEventListener("click", () => {
const data = new TextEncoder().encode(
document.getElementById("inputData").value
);
let length = data.length + 1;
let bytes = new Uint8Array([ ...(new Uint8Array([251, 27, 0, length % 256, parseInt((length / 256))])), ...data, ...(new Uint8Array([254]))])
bleDevice.gatt
.getPrimaryService(MICROBLOCKS_SERVICE_UUID)
.then((service) => service.getCharacteristic(MICROBLOCKS_RX_CHAR_UUID))
.then((characteristic) => characteristic.writeValue(bytes))
.catch((error) => {
console.log("发送数据错误:" + error);
});
});
// 接收蓝牙消息
function _match(filter) {
let buf = message_buffer;
let result = [];
let bytesRemaining = null;
let cmd = null;
let msgLen = null;
let end = null;
let length = buf.length;
let i = 0;
while (true) {
while (!(i >= length || buf[i] == 250 || buf[i] == 251)) {
i += 1; // skip to start of next message
}
bytesRemaining = length - i;
if (bytesRemaining < 1) {
// # nothing to process
message_buffer = buf.slice(i);
return result;
}
cmd = buf[i];
if (cmd == 250 && bytesRemaining >= 3) {
// short message (3 bytes)
if (filter == buf[i + 1]) {
result.push(buf.slice(i, i + 3));
}
i += 3;
} else {
if (cmd == 251 && bytesRemaining >= 5) {
// ong message (>= 5 bytes)
msgLen = 256 * buf[i + 4] + buf[i + 3];
end = i + 5 + msgLen;
if (end > length) {
// long message is not yet complete
message_buffer = buf.slice(i);
return result;
}
if (filter == buf[i + 1]) {
result.push(buf.slice(i, end));
}
i = end;
} else {
message_buffer = buf.slice(i);
return result;
}
}
}
}
function handleNotifications(event) {
// let value = new TextDecoder().decode(event.target.value);
let result = [];
let msg = new Uint8Array(event.target.value.buffer);
message_buffer = new Uint8Array([...message_buffer, ...msg]);
for (const msgBytes of _match(27)) {
let string = new TextDecoder().decode(msgBytes.slice(4));
result.push(string.replace("\x00", "")); //
}
if (result != []){
document.getElementById("output").textContent = "收到数据: " + result.join("");
}
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment