mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
WebBluetooth Test API
This commit is contained in:
parent
4eec2c6ddc
commit
e15d54edfd
14 changed files with 701 additions and 14 deletions
|
@ -11,17 +11,17 @@ extern crate rand;
|
|||
#[cfg(target_os = "linux")]
|
||||
extern crate tinyfiledialogs;
|
||||
extern crate util;
|
||||
extern crate uuid;
|
||||
|
||||
pub mod test;
|
||||
|
||||
use bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothCharacteristicsMsg};
|
||||
use bluetooth_traits::{BluetoothDescriptorMsg, BluetoothDescriptorsMsg};
|
||||
use bluetooth_traits::{BluetoothDeviceMsg, BluetoothError, BluetoothMethodMsg};
|
||||
use bluetooth_traits::{BluetoothResult, BluetoothServiceMsg, BluetoothServicesMsg};
|
||||
use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions};
|
||||
use device::bluetooth::BluetoothAdapter;
|
||||
use device::bluetooth::BluetoothDevice;
|
||||
use device::bluetooth::BluetoothGATTCharacteristic;
|
||||
use device::bluetooth::BluetoothGATTDescriptor;
|
||||
use device::bluetooth::BluetoothGATTService;
|
||||
use device::bluetooth::{BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic};
|
||||
use device::bluetooth::{BluetoothGATTDescriptor, BluetoothGATTService};
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
use rand::Rng;
|
||||
use std::borrow::ToOwned;
|
||||
|
@ -33,6 +33,8 @@ use util::thread::spawn_named;
|
|||
|
||||
const ADAPTER_ERROR: &'static str = "No adapter found";
|
||||
|
||||
const ADAPTER_NOT_POWERED_ERROR: &'static str = "Bluetooth adapter not powered";
|
||||
|
||||
// A transaction not completed within 30 seconds shall time out. Such a transaction shall be considered to have failed.
|
||||
// https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 (Vol. 3, page 480)
|
||||
const MAXIMUM_TRANSACTION_TIME: u8 = 30;
|
||||
|
@ -71,7 +73,12 @@ macro_rules! return_if_cached(
|
|||
macro_rules! get_adapter_or_return_error(
|
||||
($bl_manager:expr, $sender:expr) => (
|
||||
match $bl_manager.get_or_create_adapter() {
|
||||
Some(adapter) => adapter,
|
||||
Some(adapter) => {
|
||||
if !adapter.is_powered().unwrap_or(false) {
|
||||
return drop($sender.send(Err(BluetoothError::Type(ADAPTER_NOT_POWERED_ERROR.to_string()))))
|
||||
}
|
||||
adapter
|
||||
},
|
||||
None => return drop($sender.send(Err(BluetoothError::Type(ADAPTER_ERROR.to_string())))),
|
||||
}
|
||||
);
|
||||
|
@ -155,6 +162,13 @@ fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequen
|
|||
return filters.iter().any(|f| matches_filter(device, f))
|
||||
}
|
||||
|
||||
fn is_mock_adapter(adapter: &BluetoothAdapter) -> bool {
|
||||
match adapter {
|
||||
&BluetoothAdapter::Mock(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BluetoothManager {
|
||||
receiver: IpcReceiver<BluetoothMethodMsg>,
|
||||
adapter: Option<BluetoothAdapter>,
|
||||
|
@ -228,6 +242,9 @@ impl BluetoothManager {
|
|||
BluetoothMethodMsg::WriteValue(id, value, sender) => {
|
||||
self.write_value(id, value, sender)
|
||||
},
|
||||
BluetoothMethodMsg::Test(data_set_name, sender) => {
|
||||
self.test(data_set_name, sender)
|
||||
}
|
||||
BluetoothMethodMsg::Exit => {
|
||||
break
|
||||
},
|
||||
|
@ -235,13 +252,46 @@ impl BluetoothManager {
|
|||
}
|
||||
}
|
||||
|
||||
// Test
|
||||
|
||||
fn test(&mut self, data_set_name: String, sender: IpcSender<BluetoothResult<()>>) {
|
||||
self.address_to_id.clear();
|
||||
self.service_to_device.clear();
|
||||
self.characteristic_to_service.clear();
|
||||
self.descriptor_to_characteristic.clear();
|
||||
self.cached_devices.clear();
|
||||
self.cached_services.clear();
|
||||
self.cached_characteristics.clear();
|
||||
self.cached_descriptors.clear();
|
||||
self.allowed_services.clear();
|
||||
self.adapter = BluetoothAdapter::init_mock().ok();
|
||||
match test::test(self, data_set_name) {
|
||||
Ok(_) => {
|
||||
let _ = sender.send(Ok(()));
|
||||
},
|
||||
Err(error) => {
|
||||
let _ = sender.send(Err(BluetoothError::Type(error.description().to_owned())));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Adapter
|
||||
|
||||
fn get_or_create_adapter(&mut self) -> Option<BluetoothAdapter> {
|
||||
pub fn get_or_create_adapter(&mut self) -> Option<BluetoothAdapter> {
|
||||
let adapter_valid = self.adapter.as_ref().map_or(false, |a| a.get_address().is_ok());
|
||||
if !adapter_valid {
|
||||
self.adapter = BluetoothAdapter::init().ok();
|
||||
}
|
||||
|
||||
let adapter = match self.adapter.as_ref() {
|
||||
Some(adapter) => adapter,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
if is_mock_adapter(adapter) && !adapter.is_present().unwrap_or(false) {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.adapter.clone()
|
||||
}
|
||||
|
||||
|
@ -270,7 +320,16 @@ impl BluetoothManager {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn select_device(&mut self, devices: Vec<BluetoothDevice>) -> Option<String> {
|
||||
fn select_device(&mut self, devices: Vec<BluetoothDevice>, adapter: &BluetoothAdapter) -> Option<String> {
|
||||
if is_mock_adapter(adapter) {
|
||||
for device in devices {
|
||||
if let Ok(address) = device.get_address() {
|
||||
return Some(address);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut dialog_rows: Vec<String> = vec!();
|
||||
for device in devices {
|
||||
dialog_rows.extend_from_slice(&[device.get_address().unwrap_or("".to_string()),
|
||||
|
@ -291,7 +350,7 @@ impl BluetoothManager {
|
|||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn select_device(&mut self, devices: Vec<BluetoothDevice>) -> Option<String> {
|
||||
fn select_device(&mut self, devices: Vec<BluetoothDevice>, _adapter: &BluetoothAdapter) -> Option<String> {
|
||||
for device in devices {
|
||||
if let Ok(address) = device.get_address() {
|
||||
return Some(address);
|
||||
|
@ -475,7 +534,9 @@ impl BluetoothManager {
|
|||
let mut adapter = get_adapter_or_return_error!(self, sender);
|
||||
if let Ok(ref session) = adapter.create_discovery_session() {
|
||||
if session.start_discovery().is_ok() {
|
||||
thread::sleep(Duration::from_millis(DISCOVERY_TIMEOUT_MS));
|
||||
if !is_mock_adapter(&adapter) {
|
||||
thread::sleep(Duration::from_millis(DISCOVERY_TIMEOUT_MS));
|
||||
}
|
||||
}
|
||||
let _ = session.stop_discovery();
|
||||
}
|
||||
|
@ -492,7 +553,7 @@ impl BluetoothManager {
|
|||
}
|
||||
|
||||
// Step 8.
|
||||
if let Some(address) = self.select_device(matched_devices) {
|
||||
if let Some(address) = self.select_device(matched_devices, &adapter) {
|
||||
let device_id = match self.address_to_id.get(&address) {
|
||||
Some(id) => id.clone(),
|
||||
None => return drop(sender.send(Err(BluetoothError::NotFound))),
|
||||
|
@ -528,7 +589,12 @@ impl BluetoothManager {
|
|||
for _ in 0..MAXIMUM_TRANSACTION_TIME {
|
||||
match d.is_connected().unwrap_or(false) {
|
||||
true => return drop(sender.send(Ok(true))),
|
||||
false => thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)),
|
||||
false => {
|
||||
if is_mock_adapter(&adapter) {
|
||||
break;
|
||||
}
|
||||
thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS));
|
||||
},
|
||||
}
|
||||
}
|
||||
return drop(sender.send(Err(BluetoothError::Network)));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue