1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
<html>
<head>
<title>Setup AIRMX device</title>
</head>
<body>
<h1>Setup your AIRMX device</h1>
<div>
<button id="connect" type="button">
Connect
</button>
</div>
<script>
const DEVICE_NAME = 'AIRMX Pro'
const MAIN_SERVICE_UUID = '22210000-554a-4546-5542-46534450464d'
const WRITE_CHAR_UUID = '22210001-554a-4546-5542-46534450464d'
const NOTIFY_CHAR_UUID = '22210002-554a-4546-5542-46534450464d'
async function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function connectToDevice() {
const device = await navigator.bluetooth.requestDevice({
filters: [
{ name: DEVICE_NAME }
],
optionalServices: [MAIN_SERVICE_UUID]
})
const server = await device.gatt.connect()
const service = await server.getPrimaryService(MAIN_SERVICE_UUID)
const writeChar = await service.getCharacteristic(WRITE_CHAR_UUID)
const notifyChar = await service.getCharacteristic(NOTIFY_CHAR_UUID)
// 1. Enable notifications
await notifyChar.startNotifications()
notifyChar.addEventListener('characteristicvaluechanged', handleDeviceResponse)
await delay(500)
// 2. Send the first bind command
await sendBindCommand(writeChar)
}
function handleDeviceResponse(event) {
const value = event.target.value
const receivedBytes = []
for (let i = 0; i < value.byteLength; i++) {
receivedBytes.push(value.getUint8(i).toString(16).padStart(2, '0'))
}
console.log(`Received data from device: ${receivedBytes.join(' ')}`)
}
async function sendBindCommand(writeChar) {
const handshakePacket = new Uint8Array([
// --- 4-byte Header ---
0x01, // Sequence Number: 1
0x11, // Packet Info: (Packet 1 of 1)
0x00, // Command ID: 11 (Big Endian Short, MSB)
0x0B, // Command ID: 11 (Big Endian Short, LSB)
// --- 15-byte Payload ---
0x08, // Hardcoded first byte of payload
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Token (as 0L)
0x05, // Length of version string "1.0.0"
0x31, 0x2e, 0x30, 0x2e, 0x30 // ASCII for "1.0.0"
])
await sendRawData(writeChar, handshakePacket)
}
async function sendRawData(characteristic, data) {
const chunkSize = 20
for (let i = 0; i < data.length; i += chunkSize) {
const chunk = data.slice(i, i + chunkSize)
console.log(`Sending chunk: ${Array.from(chunk).map(b => b.toString(16).padStart(2, '0')).join(' ')}`)
await characteristic.writeValueWithResponse(chunk)
}
}
const connect = document.getElementById('connect')
connect.addEventListener('click', connectToDevice)
</script>
</body>
</html>
|