| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Javascript for ValueControl, served from chrome://bluetooth-internals/. | 6 * Javascript for ValueControl, served from chrome://bluetooth-internals/. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 cr.define('value_control', function() { | 9 cr.define('value_control', function() { |
| 10 /** @const */ var Snackbar = snackbar.Snackbar; | 10 /** @const */ var Snackbar = snackbar.Snackbar; |
| 11 /** @const */ var SnackbarType = snackbar.SnackbarType; | 11 /** @const */ var SnackbarType = snackbar.SnackbarType; |
| 12 | 12 |
| 13 /** @typedef {{ |
| 14 * deviceAddress: string, |
| 15 * serviceId: string, |
| 16 * characteristicId: string, |
| 17 * descriptorId: (string|undefined) |
| 18 * properties: (number|undefined) |
| 19 * }} |
| 20 */ |
| 21 var ValueLoadOptions; |
| 22 |
| 13 /** @enum {string} */ | 23 /** @enum {string} */ |
| 14 var ValueDataType = { | 24 var ValueDataType = { |
| 15 HEXADECIMAL: 'Hexadecimal', | 25 HEXADECIMAL: 'Hexadecimal', |
| 16 UTF8: 'UTF-8', | 26 UTF8: 'UTF-8', |
| 17 DECIMAL: 'Decimal', | 27 DECIMAL: 'Decimal', |
| 18 }; | 28 }; |
| 19 | 29 |
| 20 /** | 30 /** |
| 21 * A container for an array value that needs to be converted to multiple | 31 * A container for an array value that needs to be converted to multiple |
| 22 * display formats. Internally, the value is stored as an array and converted | 32 * display formats. Internally, the value is stored as an array and converted |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 */ | 213 */ |
| 204 decorate: function() { | 214 decorate: function() { |
| 205 this.classList.add('value-control'); | 215 this.classList.add('value-control'); |
| 206 | 216 |
| 207 /** @private {!Value} */ | 217 /** @private {!Value} */ |
| 208 this.value_ = new Value([]); | 218 this.value_ = new Value([]); |
| 209 /** @private {?string} */ | 219 /** @private {?string} */ |
| 210 this.deviceAddress_ = null; | 220 this.deviceAddress_ = null; |
| 211 /** @private {?string} */ | 221 /** @private {?string} */ |
| 212 this.serviceId_ = null; | 222 this.serviceId_ = null; |
| 213 /** @private {?interfaces.BluetoothDevice.CharacteristicInfo} */ | 223 /** @private {?string} */ |
| 214 this.characteristicInfo_ = null; | 224 this.characteristicId_ = null; |
| 225 /** @private {?string} */ |
| 226 this.descriptorId_ = null; |
| 227 /** @private {number} */ |
| 228 this.properties_ = Number.MAX_SAFE_INTEGER; |
| 215 | 229 |
| 216 this.unavailableMessage_ = document.createElement('h3'); | 230 this.unavailableMessage_ = document.createElement('h3'); |
| 217 this.unavailableMessage_.textContent = 'Value cannot be read or written.'; | 231 this.unavailableMessage_.textContent = 'Value cannot be read or written.'; |
| 218 | 232 |
| 219 this.valueInput_ = document.createElement('input'); | 233 this.valueInput_ = document.createElement('input'); |
| 220 this.valueInput_.addEventListener('change', function() { | 234 this.valueInput_.addEventListener('change', function() { |
| 221 try { | 235 try { |
| 222 this.value_.setAs(this.typeSelect_.value, this.valueInput_.value); | 236 this.value_.setAs(this.typeSelect_.value, this.valueInput_.value); |
| 223 } catch (e) { | 237 } catch (e) { |
| 224 Snackbar.show(e.message, SnackbarType.ERROR); | 238 Snackbar.show(e.message, SnackbarType.ERROR); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 253 buttonsDiv.appendChild(this.readBtn_); | 267 buttonsDiv.appendChild(this.readBtn_); |
| 254 buttonsDiv.appendChild(this.writeBtn_); | 268 buttonsDiv.appendChild(this.writeBtn_); |
| 255 | 269 |
| 256 this.appendChild(this.unavailableMessage_); | 270 this.appendChild(this.unavailableMessage_); |
| 257 this.appendChild(inputDiv); | 271 this.appendChild(inputDiv); |
| 258 this.appendChild(buttonsDiv); | 272 this.appendChild(buttonsDiv); |
| 259 }, | 273 }, |
| 260 | 274 |
| 261 /** | 275 /** |
| 262 * Sets the settings used by the value control and redraws the control to | 276 * Sets the settings used by the value control and redraws the control to |
| 263 * match the read/write settings provided in | 277 * match the read/write settings in |options.properties|. If properties |
| 264 * |characteristicInfo.properties|. | 278 * are not provided, no restrictions on reading/writing are applied. |
| 265 * @param {string} deviceAddress | 279 * @param {!ValueLoadOptions} options |
| 266 * @param {string} serviceId | |
| 267 * @param {!interfaces.BluetoothDevice.CharacteristicInfo} | |
| 268 * characteristicInfo | |
| 269 */ | 280 */ |
| 270 load: function(deviceAddress, serviceId, characteristicInfo) { | 281 load: function(options) { |
| 271 this.deviceAddress_ = deviceAddress; | 282 this.deviceAddress_ = options.deviceAddress; |
| 272 this.serviceId_ = serviceId; | 283 this.serviceId_ = options.serviceId; |
| 273 this.characteristicInfo_ = characteristicInfo; | 284 this.characteristicId_ = options.characteristicId; |
| 285 this.descriptorId_ = options.descriptorId; |
| 286 |
| 287 if (options.properties) |
| 288 this.properties_ = options.properties; |
| 274 | 289 |
| 275 this.redraw(); | 290 this.redraw(); |
| 276 }, | 291 }, |
| 277 | 292 |
| 278 /** | 293 /** |
| 279 * Redraws the value control with updated layout depending on the | 294 * Redraws the value control with updated layout depending on the |
| 280 * availability of reads and writes and the current cached value. | 295 * availability of reads and writes and the current cached value. |
| 281 */ | 296 */ |
| 282 redraw: function() { | 297 redraw: function() { |
| 283 this.readBtn_.hidden = (this.characteristicInfo_.properties & | 298 this.readBtn_.hidden = |
| 284 interfaces.BluetoothDevice.Property.READ) === 0; | 299 (this.properties_ & interfaces.BluetoothDevice.Property.READ) === 0; |
| 285 this.writeBtn_.hidden = (this.characteristicInfo_.properties & | 300 this.writeBtn_.hidden = |
| 286 interfaces.BluetoothDevice.Property.WRITE) === 0; | 301 (this.properties_ & interfaces.BluetoothDevice.Property.WRITE) === 0; |
| 287 | 302 |
| 288 var isAvailable = !this.readBtn_.hidden || !this.writeBtn_.hidden; | 303 var isAvailable = !this.readBtn_.hidden || !this.writeBtn_.hidden; |
| 289 this.unavailableMessage_.hidden = isAvailable; | 304 this.unavailableMessage_.hidden = isAvailable; |
| 290 this.valueInput_.hidden = !isAvailable; | 305 this.valueInput_.hidden = !isAvailable; |
| 291 this.typeSelect_.hidden = !isAvailable; | 306 this.typeSelect_.hidden = !isAvailable; |
| 292 | 307 |
| 293 if (!isAvailable) | 308 if (!isAvailable) |
| 294 return; | 309 return; |
| 295 | 310 |
| 296 this.valueInput_.value = this.value_.getAs(this.typeSelect_.value); | 311 this.valueInput_.value = this.value_.getAs(this.typeSelect_.value); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 315 // messages. | 330 // messages. |
| 316 var GattResult = interfaces.BluetoothDevice.GattResult; | 331 var GattResult = interfaces.BluetoothDevice.GattResult; |
| 317 return Object.keys(GattResult).find(function(key) { | 332 return Object.keys(GattResult).find(function(key) { |
| 318 return GattResult[key] === result; | 333 return GattResult[key] === result; |
| 319 }); | 334 }); |
| 320 }, | 335 }, |
| 321 | 336 |
| 322 /** | 337 /** |
| 323 * Called when the read button is pressed. Connects to the device and | 338 * Called when the read button is pressed. Connects to the device and |
| 324 * retrieves the current value of the characteristic in the |service_id| | 339 * retrieves the current value of the characteristic in the |service_id| |
| 325 * with id |characteristic_id| | 340 * with id |characteristic_id|. If |descriptor_id| is defined, the |
| 341 * descriptor value with |descriptor_id| is read instead. |
| 326 * @private | 342 * @private |
| 327 */ | 343 */ |
| 328 readValue_: function() { | 344 readValue_: function() { |
| 329 this.readBtn_.disabled = true; | 345 this.readBtn_.disabled = true; |
| 330 | 346 |
| 331 device_broker.connectToDevice(this.deviceAddress_).then(function(device) { | 347 device_broker.connectToDevice(this.deviceAddress_).then(function(device) { |
| 348 if (this.descriptorId_) { |
| 349 return device.readValueForDescriptor( |
| 350 this.serviceId_, this.characteristicId_, this.descriptorId_); |
| 351 } |
| 352 |
| 332 return device.readValueForCharacteristic( | 353 return device.readValueForCharacteristic( |
| 333 this.serviceId_, this.characteristicInfo_.id); | 354 this.serviceId_, this.characteristicId_); |
| 334 }.bind(this)).then(function(response) { | 355 }.bind(this)).then(function(response) { |
| 335 this.readBtn_.disabled = false; | 356 this.readBtn_.disabled = false; |
| 336 | 357 |
| 337 if (response.result === interfaces.BluetoothDevice.GattResult.SUCCESS) { | 358 if (response.result === interfaces.BluetoothDevice.GattResult.SUCCESS) { |
| 338 this.setValue(response.value); | 359 this.setValue(response.value); |
| 339 Snackbar.show( | 360 Snackbar.show( |
| 340 this.deviceAddress_ + ': Read succeeded', SnackbarType.SUCCESS); | 361 this.deviceAddress_ + ': Read succeeded', SnackbarType.SUCCESS); |
| 341 return; | 362 return; |
| 342 } | 363 } |
| 343 | 364 |
| 344 var errorString = this.getErrorString_(response.result); | 365 var errorString = this.getErrorString_(response.result); |
| 345 Snackbar.show( | 366 Snackbar.show( |
| 346 this.deviceAddress_ + ': ' + errorString, SnackbarType.ERROR, | 367 this.deviceAddress_ + ': ' + errorString, SnackbarType.ERROR, |
| 347 'Retry', this.readValue_.bind(this)); | 368 'Retry', this.readValue_.bind(this)); |
| 348 }.bind(this)); | 369 }.bind(this)); |
| 349 }, | 370 }, |
| 350 | 371 |
| 351 /** | 372 /** |
| 352 * Called when the write button is pressed. Connects to the device and | 373 * Called when the write button is pressed. Connects to the device and |
| 353 * retrieves the current value of the characteristic in the |service_id| | 374 * retrieves the current value of the characteristic in the |
| 354 * with id |characteristic_id| | 375 * |service_id| with id |characteristic_id|. If |descriptor_id| is defined, |
| 376 * the descriptor value with |descriptor_id| is written instead. |
| 355 * @private | 377 * @private |
| 356 */ | 378 */ |
| 357 writeValue_: function() { | 379 writeValue_: function() { |
| 358 this.writeBtn_.disabled = true; | 380 this.writeBtn_.disabled = true; |
| 359 | 381 |
| 360 device_broker.connectToDevice(this.deviceAddress_).then(function(device) { | 382 device_broker.connectToDevice(this.deviceAddress_).then(function(device) { |
| 383 if (this.descriptorId_) { |
| 384 return device.writeValueForDescriptor( |
| 385 this.serviceId_, this.characteristicId_, this.descriptorId_, |
| 386 this.value_.getArray()); |
| 387 } |
| 388 |
| 361 return device.writeValueForCharacteristic( | 389 return device.writeValueForCharacteristic( |
| 362 this.serviceId_, this.characteristicInfo_.id, | 390 this.serviceId_, this.characteristicId_, this.value_.getArray()); |
| 363 this.value_.getArray()); | |
| 364 }.bind(this)).then(function(response) { | 391 }.bind(this)).then(function(response) { |
| 365 this.writeBtn_.disabled = false; | 392 this.writeBtn_.disabled = false; |
| 366 | 393 |
| 367 if (response.result === interfaces.BluetoothDevice.GattResult.SUCCESS) { | 394 if (response.result === interfaces.BluetoothDevice.GattResult.SUCCESS) { |
| 368 Snackbar.show( | 395 Snackbar.show( |
| 369 this.deviceAddress_ + ': Write succeeded', SnackbarType.SUCCESS); | 396 this.deviceAddress_ + ': Write succeeded', SnackbarType.SUCCESS); |
| 370 return; | 397 return; |
| 371 } | 398 } |
| 372 | 399 |
| 373 var errorString = this.getErrorString_(response.result); | 400 var errorString = this.getErrorString_(response.result); |
| 374 Snackbar.show( | 401 Snackbar.show( |
| 375 this.deviceAddress_ + ': ' + errorString, SnackbarType.ERROR, | 402 this.deviceAddress_ + ': ' + errorString, SnackbarType.ERROR, |
| 376 'Retry', this.writeValue_.bind(this)); | 403 'Retry', this.writeValue_.bind(this)); |
| 377 }.bind(this)); | 404 }.bind(this)); |
| 378 }, | 405 }, |
| 379 } | 406 } |
| 380 | 407 |
| 381 return { | 408 return { |
| 382 ValueControl: ValueControl, | 409 ValueControl: ValueControl, |
| 383 ValueDataType: ValueDataType, | 410 ValueDataType: ValueDataType, |
| 384 }; | 411 }; |
| 385 }); | 412 }); |
| OLD | NEW |