-
-
Save wwj718/2c2ba8c69a2ff34daf0900bdec57bb44 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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