The BLE Peripheral Simulator app, combined with the Web Bluetooth Samples, is a tremendous resource for developers.
Once a device is paired, is there any way through Web Bluetooth to bypass the pairing screen and go straight to the app?
Yes, this is possible. Code Source. Not my code though.
// Selected device object cache
let deviceCache = null;
// Launch Bluetooth device chooser and connect to the selected
function connect() {
return (deviceCache ? Promise.resolve(deviceCache) :
requestBluetoothDevice())
.then(device => connectDeviceAndCacheCharacteristic(device))
.then(characteristic => startNotifications(characteristic))
.catch(error => log(error));
function requestBluetoothDevice() {
log('Requesting bluetooth device...');
return navigator.bluetooth.requestDevice({
filters: [{services: [myService]}],
})
.then(device => {
log('"' + device.name + '" bluetooth device selected');
deviceCache = device;
// Listen for disconnet event
deviceCache.addEventListener('gattserverdisconnected',
handleDisconnection);
return deviceCache;
});
}
Also, there is a way of reconnecting after site refresh, but it is not implemented yet
I recently implemented a new permissions backend as well as two APIs that will enable previously permitted Bluetooth devices to be used.
The new permissions backend is implemented behind the chrome://flags/#enable-web-bluetooth-new-permissions-backend. The new backend will persist device permissions granted through requestDevice() until the permission is reset in Site Settings or the Page Info dialog box.
The getDevices() and watchAdvertisements() are implemented behind the chrome://flags/#enable-experimental-web-platform-features flag for Chrome 85.0.4165.0 or greater. The recommended use of these APIs is to use getDevices() to retrieve an array of permitted BluetoothDevices and then calling watchAdvertisements() on these devices to start a scan. When advertisement packets are detected from the devices, the advertisementreceived Event will be fired on the device that it corresponds to. At this point, the Bluetooth device is in range and can be connected to.
Please give this new feature a try, and file any bugs at https://crbug.com using the Blink>Bluetooth component.
Related
I am working on a POC where I use the experimental BLE scan interface to discover multiple Bluetooth devices, and connect to their GATT services from a web application.
Requesting a single device using navigator.bluetooth.requestDevice yields a device where I can connect to the GATT server.
When when I try to discover devices using requestLEScan, the devices I receive does not allow me to connect to the GATT server.
const [ devices, dispatch ] = useReducer(reducer, {});
const scanClick = () => {
navigator.bluetooth.requestLEScan({
acceptAllAdvertisements: true,
}).then((scan) => {
setTimeout(() => scan.stop(), 10000);
});
navigator.bluetooth.addEventListener('advertisementreceived', (event) => {
console.log("DEVICE DETECTED", event);
parseBluetoothDevice(event.device).then(x => x && dispatch(x));
});
}
const parseBluetoothDevice = async (device) => {
// Should return a representation with the device information I want to display
await device.gatt.connect();
...
}
The call to device.gatt.connect() throws an error:
GATT operation not authorized
How do I get authorized to access the GATT server on the detected device?
Is my problem that I need to call permissions.request(), which is not yet implemented for Bluetooth? (Bluetooth implementation status)
I have tried instead of setting acceptAllAdvertisement, to pass filters with a service UUID that I know my devices support - and that I want to query, but then I don't see any scan results.
I am running Chrome 83.0.4103.97 on MacOS with "experimental web features" enabled.
The requestLEScan() API only grants permission to start a scan and see advertisement packets from nearby devices, but it does not grant permission to connect to these devices. To do this, you would need to use requestDevice() and add the services that you're interested in using to the filter or to optionalServices.
In Chrome, the prompt displayed when requestDevice() requires the user to select the Bluetooth device that they want to allow the site to connect to, whereas the prompt displayed for requestLEScan() only asks if the user wants to allow the site to scan for nearby Bluetooth devices. This is why you aren't able to connect to these devices.
According to PWA Web Bluetooth documentation, it supports "either a BR/EDR or LE connection".
I am trying to test using the following code at the console of the Chrome devtools:
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
})
.then(device => {
// Human-readable name of the device.
console.log(device.name);
console.log(device.id);
// Attempts to connect to remote GATT Server.
return device.gatt.connect();
})
.then(server => { /* ... */ })
.catch(error => { console.error(error); });
I am using a Bluetooth music box to test it. It is recognized as "XTREME" as follows:
When I select the "XTREME" device and click "PAIR", I get an "Unsupported device" error at the console as shown below:
I've tried many other Bluetooth devices and got the same "Unsupported device" message.
What is going on? Isn't it supposed to be supported? How do I know which device is supported? Ideally, what do I do to know if my specific target device will be supported?
Please help!
Tks!
It seems that the problem is that Web Bluetooth only implement few Bluetooth protocols (GATT and LE).
More about Bluetooth protocols can be found here: https://en.wikipedia.org/wiki/List_of_Bluetooth_protocols
One can use and App to inspect the device protocol and see if it implements GATT or LE to check for Web Bluetooth compatibility. Example: https://play.google.com/store/apps/details?id=com.sanji.jasper_hsieh.sdpscanner&hl=en
I have previously paired with a Bluetooth device that supports RFCOMM.
When my app is opened I continuously try to connect to the device by opening the RFCOMM. This way my app automatically connects when the device comes in range.
deviceInfoCollection = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
LogData(String.Format("Number of mldp devices is {0}", deviceInfoCollection.Count));
foreach (DeviceInformation deviceInfo in deviceInfoCollection)
{
LogData(String.Format("ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
Then run this on a timer:
try
{
// The first time this method is invoked by a store app, it should be called
// from a UI thread in order to display the consent prompt
// https://msdn.microsoft.com/en-us/windows.devices.bluetooth.rfcomm.rfcommdeviceservice.fromidasync
RfcommDeviceService rfcommService = await RfcommDeviceService.FromIdAsync(deviceInfo.Id);
LogData(String.Format("ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
catch (Exception)
{
LogData(String.Format("Can not request rfcomm service from device ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
Is there any way to query when the device is in range , rather than trying to connect? I would prefer to only attempt connection when the device is in range.
For RFCOMM (BT2.0, BT2.1) you can run a device enumeration periodically, see also Get bluetooth devices in range
However your actual implementation with a connection attempt may work a little better.
For Bluetooth 4.0, you can listen to the advertisements of the BT module, see also https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BluetoothAdvertisement
If you're talking to an embedded device (e.g. some robot, or homebrew appliances using RFCOMM) I am afraid there is no better solution than what you're doing.
If you're taking to a phone (which supports both BT4.0 and BT2.1) you can use the BT4 advertisements to signal the proximity of the device, then connect via RFCOMM.
I wanted to use Usage default app to determine how much data my own app send when in roaming mode.
I was very surprised to see that my device sent about 500 Mo. Then I realised that other apps on my phone should have used the network also.
So my question is: how can I enable roaming for just my app and prevent network access for everything else (updates, agenda, mail, ...)?
I run Firefox-OS 2.0 on a ZTE-Open device.
No, this is not possible.
The Data Usage App performs a test like this using the with the Network Stats API:
var end = new Date();
var start = new Date();
// Returns a mozNetworkStats object
var test = navigator.mozNetworkStats.getSamples('mobile', start, end);
console.log(test);
But this test will return a sample of all device connections, not only yours. The simplest solution is to measure the traffic in your Network Monitor.
However, if you want to reduce the amount of mobile traffic for your application, you can restrict all connections to specific connection types (like wifi). Just listen to the typechange event of the NetworkInformation.connection API.
In your WebIDE console (Firefox OS 2.0):
navigator.connection
NetworkInformation { type: "wifi", ontypechange: null }
or
navigator.connection
NetworkInformation { type: "cellular", ontypechange: null }
Please notice, that Firefox OS <=1.5 will never show you a cellular type of connection (it will return none if not wifi).
If I have a Android phone which is already connected with a bluetooth headset (paired and connected) to it.
How I can get information about that specific headset.
Using getBondedDevices() method I get list of all paired devices..I need information about CONNECTED device only.
I can not wait for broadcast receiver to check status, because I need this information at the start of my application. So please suggest is there any way to get this information without waiting for broadcast.
You can do this through the IBluetoothA2dp interface in API 11 and up. Some more info on there is here: Android connect to a paired bluetooth headset
Here is a great resource to see the difference in what is available to this interface between API 10 and 11 where it changed quite a bit.
http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/bluetooth/BluetoothA2dp.java/?v=diff&id2=2.2_r1.1
Hope that helps.
You can use the getConnectedDevices for the HEADSET Profile to get the device to which it is connected.
Check this out to see if headset is connected (ICS only):
public boolean isVoiceConnected()
{
boolean retval = true;
try {
retval = BluetoothAdapter.getDefaultAdapter().getProfileConnectionState(android.bluetooth.BluetoothProfile.HEADSET) != android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
} catch (Exception exc) {
// nothing to do
}
return retval;
}