-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathweb_ble_connection.js
More file actions
106 lines (84 loc) · 3.2 KB
/
web_ble_connection.js
File metadata and controls
106 lines (84 loc) · 3.2 KB
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import Constants from "../constants.js";
import Connection from "./connection.js";
class WebBleConnection extends Connection {
constructor(bleDevice) {
super();
this.bleDevice = bleDevice;
this.gattServer = null;
this.rxCharacteristic = null;
this.txCharacteristic = null;
this.init();
}
static async open() {
// ensure browser supports web bluetooth
if(!navigator.bluetooth){
alert("Web Bluetooth is not supported in this browser");
return;
}
// ask user to select device
const device = await navigator.bluetooth.requestDevice({
filters: [
{
services: [
Constants.Ble.ServiceUuid.toLowerCase(),
],
},
],
});
// make sure user selected a device
if(!device){
return null;
}
return new WebBleConnection(device);
}
async init() {
// listen for ble disconnect
this.bleDevice.addEventListener("gattserverdisconnected", () => {
this.onDisconnected();
});
// connect to gatt server
this.gattServer = await this.bleDevice.gatt.connect();
// find service
const service = await this.gattServer.getPrimaryService(Constants.Ble.ServiceUuid.toLowerCase());
const characteristics = await service.getCharacteristics();
// find rx characteristic (we write to this one, it's where the radio reads from)
this.rxCharacteristic = characteristics.find((characteristic) => {
return characteristic.uuid.toLowerCase() === Constants.Ble.CharacteristicUuidRx.toLowerCase();
});
// find tx characteristic (we read this one, it's where the radio writes to)
this.txCharacteristic = characteristics.find((characteristic) => {
return characteristic.uuid.toLowerCase() === Constants.Ble.CharacteristicUuidTx.toLowerCase();
});
// listen for frames from transmitted to us from the ble device
await this.txCharacteristic.startNotifications();
this.txCharacteristic.addEventListener('characteristicvaluechanged', (event) => {
const frame = new Uint8Array(event.target.value.buffer);
this.onFrameReceived(frame);
});
// fire connected event
await this.onConnected();
}
async close() {
try {
this.gattServer?.disconnect();
this.gattServer = null;
} catch(e) {
// ignore error when disconnecting
}
}
async write(bytes) {
try {
// fixme: NetworkError: GATT operation already in progress.
// todo: implement mutex to prevent multiple writes when another write is in progress
// we write to the rx characteristic, as that's where the radio reads from
await this.rxCharacteristic.writeValue(bytes);
} catch(e) {
console.log("failed to write to ble device", e);
}
}
async sendToRadioFrame(frame) {
this.emit("tx", frame);
await this.write(frame);
}
}
export default WebBleConnection;