I'm trying to support web-bluetooth to connect to my devices and perform a simple task (such as playing LED).
However, the device information showed on the scanning dialog when calling navigator.bluetooth.requestDevice is not so clear. It only shows the device name and a random (?) hex string.
The problem here is all my devices have the same name (AWESOME_LED), thus it's not easy for the user to select the correct LED if all scanning items show the same device name info. As far as I know, we can not custom to add more info showing on the scanning dialog.
I come up with a new solution that is changing the device name to unique for each LED with the format AWESOME_LED + [uniqueid] e.g AWESOME_LED1, AWESOME_LED2, AWESOME_LED3 so that the user can distinguish one from the others.
My question are:
Is there any alternative solution without making the device name unique?
If not, is there any problem / rejection / limitation from Apple or Google for my current app on App Store / Google Play by not using the same device name for all devices? I have been investigating it at Apple forums / Accessory Design Guidelines and looks like there are no problems, just to make sure if anyone has faced trouble from Apple / Google.
Thanks for your help.
Scanning dialog
My question are:
Is there any alternative solution without making the device name unique?
The browser prompt is not customisable yet. One solution you highlighted already is to make your LED device name unique. If you're able to control the device, why not having one AWESOME_DEVICE name and a GATT characteristic you can write to that controls individual LED colors. Maybe something like:
const device = await navigator.bluetooth.requestDevice({
filters: [{ name: "AWESOME_DEVICE" }],
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService(0x1234); // Your service UUID
const characteristic = await service.getCharacteristic(0x5678); // Your characteristic UUID
// Set LED #1 to red color.
await characteristic.writeValue(
new Uint8Array(/*ledIndex=*/ 1, /*r=*/ 255, /*g=*/ 0, /*b=*/ 0)
);
If not, is there any problem / rejection / limitation from Apple or Google for my current app on App Store / Google Play by not using the
same device name for all devices? I have been investigating it at
[Apple forums][1] / [Accessory Design Guidelines][2] and looks like
there are no problems, just to make sure if anyone has faced trouble
from Apple / Google.
None that I'm aware of.
Related
My app currently uses the default alarm ringtone for certain events, which is realized using the following two lines of code in onCreate():
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
ringtone = RingtoneManager.getRingtone(getApplicationContext(), notification);
At the start of the activity class, I have defined ringtone:
Ringtone ringtone;
At the places in the code where the alarm should actually sound, I use ringtone.play() and ringtone.stop(). Works fine.
Now, I would now like to replace the default alarm tone with a custom tone (alarmsound.mp3). To that purpose, I've placed that custom tone in the resources of the app (res/raw/alarmsound.mp3).
How do I change my code to play the custom tone? I've checked this question for duplicates, but the answers (and even the questions) seem incredibly complicated and long (imagine accessing custom-made drawables would require so much code). Is there an easy way to do this, like by modifying or adding to the above code (and without having to ask the user any extra permissions)?
I already tried
Uri notification = RingtoneManager.getActualDefaultRingtoneUri(MainActivity.this, R.raw.alarmsound);
ringtone = RingtoneManager.getRingtone(getApplicationContext(), notification);
but that gave a NullPointerException in ringtone.play()
RingtoneManager.setActualDefaultRingtoneUri(baseContext, RingtoneManager.TYPE_RINGTONE,
Uri.parse("android.resource://com.apppackage/" + R.raw.alarmsound));
RingtoneManager.getRingtone(baseContext,
Uri.parse("android.resource://com.apppackage/" + R.raw.alarmsound));
I see that Google Chrome has not implemented filtering on manufacturer data. Issue 707635, does not seem to have any progress.
The Web Bluetooth specification has an (unstable) spec for filtering manufacturerData when using navigator.bluetooth.requestDevice (https://webbluetoothcg.github.io/web-bluetooth/#example-filter-by-manufacturer-service-data
Does anyone know if there is any progress on this or made this kind of filtering work?
Following our discussion, I've added support for manufacturer data filter in Web Bluetooth in Chrome 92. See https://crbug.com/707635
Here's an example:
// Filter Bluetooth devices from Google company with manufacturer data bytes
// that start with [0x01, 0x02].
navigator.bluetooth.requestDevice({
filters: [{
manufacturerData: [{
companyIdentifier: 0x00e0,
dataPrefix: new Uint8Array([0x01, 0x02])
}]
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
You'll find a sample at https://googlechrome.github.io/samples/web-bluetooth/manufacturer-data-filter.html and some developer documentation at https://web.dev/bluetooth/#manufacturer-data-filter
Let me know if that works for you ;)
The Chrome team has NOT made progress on this yet as you've noted. In the mean time, would filtering by device name, device name prefix, or GATT services work out for you?
You can try it with https://googlechrome.github.io/samples/web-bluetooth/device-info.html.
Short answer:
'Star' issue 707635 to receive updates and signal interest.
If you have a clear example / business case to share consider adding a comment to help developers understand how to prioritize this work.
Chromium is open source, consider contributing or finding a developer to do this work.
I try to test my action in the Google Actions Simulator. Unfortunately, the simulator does not seems to recognize the difference between the phone surface and the smart speaker surface within the simulator.
I tried to console log the screentest variable. In the logs both the phone & speaker surface show 'true', which clearly is not correct. I also checked to 'conversation' data log. Both phone & speaker output contain SCREEN_OUTPUT.
app.intent('Default Welcome Intent', (conv) => {
let screentest = conv.available.surfaces.capabilities.has('actions.capability.SCREEN_OUTPUT')
console.log(screentest)
if (screentest === true) {
conv.add('Text with screen')
} else if (screentest === false) {
conv.add('Text without screen')
} else {
conv.add('impossible')
}
})
Expected results: when using the speaker surface inside the simulator, the output of the assistant should be 'Text without Screen'.
Actual results: Both phone & speaker surface inside the simulator generate the answer: 'Text with screen'.
The issue is that you're not quite checking for surfaces correctly.
There are two sets of capabilities reported:
The capabilities available on the surface the user is currently using. If you're using the actions-on-google library, these are available using conv.surface.capabilties.has()
The capabilities available on any surface that the user has connected to their account. These are available using conv.available.surfaces.capabilities.has() if you're using the actions-on-google library.
You're currently using the second one when you should be checking the first one to see what the user is currently using.
You'll want to use the second in case there is something that you want to display to make sure they can handle it before suggesting you switch to it.
I have come across a problem with iBeacon transmission in AltBeacon library in XAMARIN.
In Android Studio, this code works perfect (I can detect created iBeacon on iPhone). I am using Android 5:
mBeaconTransmitter = new BeaconTransmitter(this, new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
Beacon beacon = new Beacon.Builder()
.setId1("FDA50693-A4E2-4FB1-AFCF-C6EB07647825")
.setId2("1000")
.setId3("2000")
.setManufacturer(0x004C)
.setTxPower(-59)
.setDataFields(Arrays.asList(new Long[] {0l}))
.build();
mBeaconTransmitter.startAdvertising(beacon);
However, I have not managed to attain the same result in XAMARIN (Visual Studio). I cannot detect created iBeacon on iPhone in this case:
var iBeaconParser = new BeaconParser();
iBeaconParser.SetBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
BeaconTransmitter beaconTransmitter = new BeaconTransmitter(ApplicationContext, iBeaconParser);
var beacon1 = new AltBeacon.Builder().SetId1("FDA50693-A4E2-4FB1-AFCF-C6EB07647825")
.SetId2("1000").SetId3("2000").SetTxPower(-59).SetManufacturer(0x004C).Build();
beaconTransmitter.StartAdvertising(beacon1);
The transmission also works in the second case. Other Android device could detect the created iBeacon. It was unsuccessful to detect the iBeacon on iPhone.
Thank you for any advice.
Hey buddy it's been almost 3 years you have ask this question so I don't know that is it still relevant for you or not but my be this will help others.
I have seen this code this is absolutely right for the beacon broadcasting and I will suggest to check that if you have bind IBeaconconsumer with beacon manage in the initialization function Bind((IBeaconConsumer)Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity); or check that if you have use _tagRegion and this refers to right one.
Hope this will help.
We are using atom electron to run an app in a "kiosk" type setting, we have 4 webcam devices connected to the physical computer, we want specifically 1 of those to be used for webrtc inside of the electron browser, then other 3 we use some C code to capture still frames. We know the USB path or the /dev/video{#} for the device we want.
Is there a way to either disable access by the view layer to the 3 webcams in node before we launch the electron window? Or another option is to set the default camera before we launch the view layer so that it will default to the webcam we want.
In the view layer we can get a list of devices and see if they are audio or video, but we can't get their /dev/video# or their USB path to figure out which one is the target webrtc cam, so this has not been very helpful yet.
Any help is great, I feel weird for having to post a question since for the last 12 years I have been able to find what I needed by searching, but its been about 3 hours so its time to ask for help.
I don't think Chromium provides a way to retrieve the USB path for a media source. You'll probably need to display a configuration screen to allow the user to select the correct camera (similar to this demo) the first time around and then use the source/device id as a mandatory constraint from that point on.
Another option is to find the correct camera based on the device label, though obviously this will only work if each camera has a distinct label. You can get all the device labels and ids by running this snippet in the DevTools console:
navigator.mediaDevices.enumerateDevices()
.then(devices => devices.forEach(
device => console.log(`kind: ${device.kind}: ${device.label} id=${device.deviceId}`)
))
.catch(err => console.log(err));
Either way, once you have the source/device id you can specify it as a mandatory constraint to ensure that only that one particular camera is used:
navigator.webkitGetUserMedia(
{
audio: false,
video: {
mandatory: {
chromeMediaSourceId: 'the camera source id obtained earlier',
}
}
},
stream => console.dir(stream),
error => console.log(error)
);