3
3
*/
4
4
5
5
import { FileTransferClient } from '../common/ble-file-transfer.js' ;
6
- import { CONNTYPE , CONNSTATE } from '../constants.js' ;
6
+ import { CONNTYPE } from '../constants.js' ;
7
7
import { Workflow } from './workflow.js' ;
8
8
import { GenericModal , DeviceInfoModal } from '../common/dialogs.js' ;
9
- import { sleep , getUrlParam } from '../common/utilities.js' ;
9
+ import { sleep } from '../common/utilities.js' ;
10
10
11
11
const bleNusServiceUUID = 'adaf0001-4369-7263-7569-74507974686e' ;
12
12
const bleNusCharRXUUID = 'adaf0002-4369-7263-7569-74507974686e' ;
@@ -63,23 +63,23 @@ class BLEWorkflow extends Workflow {
63
63
bond : btnBond
64
64
} ;
65
65
66
- btnRequestBluetoothDevice . addEventListener ( 'click' , async ( event ) => {
67
- await this . onRequestBluetoothDeviceButtonClick ( event ) ;
68
- } ) ;
69
- btnBond . addEventListener ( 'click' , async ( event ) => {
70
- await this . onBond ( event ) ;
71
- } ) ;
72
- btnReconnect . addEventListener ( 'click' , async ( event ) => {
73
- await this . reconnectButtonHandler ( event ) ;
74
- } ) ;
66
+ btnRequestBluetoothDevice . addEventListener ( 'click' , this . onRequestBluetoothDeviceButtonClick . bind ( this ) ) ;
67
+ btnBond . addEventListener ( 'click' , this . onBond . bind ( this ) ) ;
68
+ btnReconnect . addEventListener ( 'click' , this . reconnectButtonHandler . bind ( this ) ) ;
75
69
70
+ // Check if Web Bluetooth is available
76
71
if ( ! ( await this . available ( ) instanceof Error ) ) {
77
72
let stepOne ;
78
73
if ( stepOne = modal . querySelector ( '.step:first-of-type' ) ) {
79
74
stepOne . classList . add ( "hidden" ) ;
80
75
}
81
- const devices = await navigator . bluetooth . getDevices ( ) ;
82
- this . connectionStep ( devices . length > 0 ? 2 : 1 ) ;
76
+ try {
77
+ const devices = await navigator . bluetooth . getDevices ( ) ;
78
+ console . log ( devices ) ;
79
+ this . connectionStep ( devices . length > 0 ? 2 : 1 ) ;
80
+ } catch ( e ) {
81
+ console . log ( "New Permissions backend for Web Bluetooth not enabled. Go to chrome://flags/#enable-web-bluetooth-new-permissions-backend to enable." , e ) ;
82
+ }
83
83
} else {
84
84
modal . querySelectorAll ( '.step:not(:first-of-type)' ) . forEach ( ( stepItem ) => {
85
85
stepItem . classList . add ( "hidden" ) ;
@@ -92,7 +92,9 @@ class BLEWorkflow extends Workflow {
92
92
93
93
async onSerialReceive ( e ) { ;
94
94
// TODO: Make use of super.onSerialReceive() so that title can be extracted
95
- this . writeToTerminal ( this . decoder . decode ( e . target . value . buffer , { stream : true } ) ) ;
95
+ let output = this . decoder . decode ( e . target . value . buffer , { stream : true } ) ;
96
+ console . log ( output ) ;
97
+ this . writeToTerminal ( output ) ;
96
98
}
97
99
98
100
async connectToSerial ( ) {
@@ -102,6 +104,8 @@ class BLEWorkflow extends Workflow {
102
104
this . txCharacteristic = await this . serialService . getCharacteristic ( bleNusCharTXUUID ) ;
103
105
this . rxCharacteristic = await this . serialService . getCharacteristic ( bleNusCharRXUUID ) ;
104
106
107
+ // Remove any existing event listeners to prevent multiple reads
108
+ this . txCharacteristic . removeEventListener ( 'characteristicvaluechanged' , this . onSerialReceive . bind ( this ) ) ;
105
109
this . txCharacteristic . addEventListener ( 'characteristicvaluechanged' , this . onSerialReceive . bind ( this ) ) ;
106
110
await this . txCharacteristic . startNotifications ( ) ;
107
111
return true ;
@@ -118,92 +122,102 @@ class BLEWorkflow extends Workflow {
118
122
console . log ( 'Getting existing permitted Bluetooth devices...' ) ;
119
123
const devices = await navigator . bluetooth . getDevices ( ) ;
120
124
121
- console . log ( '> Got ' + devices . length + ' Bluetooth devices .' ) ;
125
+ console . log ( '> Found ' + devices . length + ' Bluetooth device(s) .' ) ;
122
126
// These devices may not be powered on or in range, so scan for
123
127
// advertisement packets from them before connecting.
124
128
for ( const device of devices ) {
125
129
await this . connectToBluetoothDevice ( device ) ;
126
130
}
127
131
}
128
132
catch ( error ) {
129
- console . log ( 'Argh! ' + error ) ;
133
+ console . error ( error ) ;
134
+ await this . _showMessage ( error ) ;
130
135
}
131
136
}
132
137
}
133
138
139
+ // Bring up a dialog to request a device
140
+ async requestDevice ( ) {
141
+ return navigator . bluetooth . requestDevice ( {
142
+ filters : [ { services : [ 0xfebb ] } , ] , // <- Prefer filters to save energy & show relevant devices.
143
+ optionalServices : [ 0xfebb , bleNusServiceUUID ]
144
+ } ) ;
145
+ }
146
+
134
147
async connectToBluetoothDevice ( device ) {
135
148
const abortController = new AbortController ( ) ;
136
149
137
- device . addEventListener ( 'advertisementreceived' , async ( event ) => {
150
+ async function onAdvertisementReceived ( event ) {
138
151
console . log ( '> Received advertisement from "' + device . name + '"...' ) ;
139
152
// Stop watching advertisements to conserve battery life.
140
153
abortController . abort ( ) ;
141
154
console . log ( 'Connecting to GATT Server from "' + device . name + '"...' ) ;
142
155
try {
143
- await this . showBusy ( device . gatt . connect ( ) ) ;
156
+ await device . gatt . connect ( ) ;
157
+ } catch ( error ) {
158
+ await this . _showMessage ( "Failed to connect to device. Try forgetting device from OS bluetooth devices and try again." ) ;
159
+ }
160
+ if ( device . gatt . connected ) {
144
161
console . log ( '> Bluetooth device "' + device . name + ' connected.' ) ;
145
162
await this . switchToDevice ( device ) ;
163
+ } else {
164
+ console . log ( 'Unable to connect to bluetooth device "' + device . name + '.' ) ;
146
165
}
147
- catch ( error ) {
148
- console . log ( 'Argh! ' + error ) ;
149
- }
150
- } , { once : true } ) ;
166
+ }
151
167
152
- //await this.showBusy(device.gatt.connect());
153
- await navigator . bluetooth . requestDevice ( {
154
- filters : [ { services : [ 0xfebb ] } , ] , // <- Prefer filters to save energy & show relevant devices.
155
- optionalServices : [ 0xfebb , bleNusServiceUUID ]
156
- } ) ;
168
+ device . removeEventListener ( 'advertisementreceived' , onAdvertisementReceived . bind ( this ) ) ;
169
+ device . addEventListener ( 'advertisementreceived' , onAdvertisementReceived . bind ( this ) ) ;
157
170
158
171
this . debugLog ( "connecting to " + device . name ) ;
159
172
try {
160
173
console . log ( 'Watching advertisements from "' + device . name + '"...' ) ;
161
174
await device . watchAdvertisements ( { signal : abortController . signal } ) ;
162
175
}
163
176
catch ( error ) {
164
- console . log ( 'Argh! ' + error ) ;
177
+ console . error ( error ) ;
178
+ await this . _showMessage ( error ) ;
165
179
}
166
180
}
167
181
168
182
// Request Bluetooth Device
169
183
async onRequestBluetoothDeviceButtonClick ( e ) {
170
- try {
184
+ // try {
171
185
console . log ( 'Requesting any Bluetooth device...' ) ;
172
186
this . debugLog ( "Requesting device. Cancel if empty and try existing" ) ;
173
- let device = await navigator . bluetooth . requestDevice ( {
174
- filters : [ { services : [ 0xfebb ] } , ] , // <- Prefer filters to save energy & show relevant devices.
175
- optionalServices : [ 0xfebb , bleNusServiceUUID ]
176
- } ) ;
187
+ let device = await this . requestDevice ( ) ;
177
188
178
- await this . showBusy ( device . gatt . connect ( ) ) ;
179
189
console . log ( '> Requested ' + device . name ) ;
190
+ await device . gatt . connect ( ) ;
180
191
181
192
await this . switchToDevice ( device ) ;
182
- }
193
+ /* }
183
194
catch (error) {
184
- console . log ( 'Argh: ' + error ) ;
195
+ console.error(error);
196
+ await this._showMessage(error);
185
197
this.debugLog('No device selected. Try to connect to existing.');
186
- }
198
+ }*/
187
199
}
188
200
189
201
async switchToDevice ( device ) {
190
202
console . log ( device ) ;
191
203
this . bleDevice = device ;
204
+ this . bleDevice . removeEventListener ( "gattserverdisconnected" , this . onDisconnected . bind ( this ) ) ;
192
205
this . bleDevice . addEventListener ( "gattserverdisconnected" , this . onDisconnected . bind ( this ) ) ;
193
206
this . bleServer = this . bleDevice . gatt ;
194
207
console . log ( "connected" , this . bleServer ) ;
195
208
let services ;
196
209
197
- try {
210
+ console . log ( device . gatt . connected ) ;
211
+ //try {
198
212
services = await this . bleServer . getPrimaryServices ( ) ;
199
- } catch ( e ) {
213
+ /* } catch (e) {
200
214
console.log(e, e.stack);
201
- }
215
+ }*/
202
216
console . log ( services ) ;
203
217
204
218
console . log ( 'Initializing File Transfer Client...' ) ;
205
219
this . initFileClient ( new FileTransferClient ( this . bleDevice , 65536 ) ) ;
206
- this . debugLog ( "connected" ) ;
220
+ await this . fileHelper . bond ( ) ;
207
221
await this . connectToSerial ( ) ;
208
222
209
223
// Enable/Disable UI buttons
@@ -256,15 +270,17 @@ class BLEWorkflow extends Workflow {
256
270
if ( result = await super . connect ( ) instanceof Error ) {
257
271
return result ;
258
272
}
273
+ // Is this a new connection?
259
274
if ( ! this . bleDevice ) {
260
275
let devices = await navigator . bluetooth . getDevices ( ) ;
261
276
for ( const device of devices ) {
262
277
await this . connectToBluetoothDevice ( device ) ;
263
278
}
264
279
}
265
280
281
+ // Do we have a connection now but still need to connect serial?
266
282
if ( this . bleDevice && ! this . bleServer ) {
267
- await await this . showBusy ( this . bleDevice . gatt . connect ( ) ) ;
283
+ await this . showBusy ( this . bleDevice . gatt . connect ( ) ) ;
268
284
this . switchToDevice ( this . bleDevice ) ;
269
285
}
270
286
}
0 commit comments