<html>
<head>
<title>Bluetooth Check - RJM Programming - June, 2022 ... thanks to https://googlechrome.github.io/samples/web-bluetooth/device-info.html</title>
<script type='text/javascript'>

var pref='';

function getSupportedProperties(characteristic) {
let supportedProperties = [];
for (const p in characteristic.properties) {
if (characteristic.properties[p] === true) {
supportedProperties.push(p.toUpperCase());
}
}
return '[' + supportedProperties.join(', ') + ']';
}

async function oldonButtonClick() {
let filters = [];


if (document.getElementById('service')) {
let filterService = document.querySelector('#service').value;
if (filterService.startsWith('0x')) {
filterService = parseInt(filterService);
}
if (filterService) {
filters.push({services: [filterService]});
}
}

if (document.getElementById('name')) {
let filterName = document.querySelector('#name').value;
if (filterName) {
filters.push({name: filterName});
}
}

if (document.getElementById('namePrefix')) {
let filterNamePrefix = document.querySelector('#namePrefix').value;
if (filterNamePrefix) {
filters.push({namePrefix: filterNamePrefix});
}
}

let options = {};
if (document.getElementById('allDevices')) {
if (document.querySelector('#allDevices').checked) {
options.acceptAllDevices = true;
} else {
options.filters = filters;
}
} else {
options.acceptAllDevices = true;
}

//let optionalServices = document.querySelector('#optionalServices').value
// .split(/, ?/).map(s => s.startsWith('0x') ? parseInt(s) : s)
// .filter(s => s && BluetoothUUID.getService);

//try {
console.log('Requesting Bluetooth Device...');
console.log('with ' + JSON.stringify(options));
//const device = await navigator.bluetooth.requestDevice({
// filters: [{services: ['battery_service']}]});

//if (1 == 2) {
//console.log('Connecting to GATT Server...');
//const server = await device.gatt.connect();

//console.log('Getting Battery Service...');
//const service = await server.getPrimaryService('battery_service');

//console.log('Getting Battery Level Characteristic...');
//const characteristic = await service.getCharacteristic('battery_level');

//console.log('Reading Battery Level...');
//const value = await characteristic.readValue();

//console.log('> Battery Level is ' + value.getUint8(0) + '%');
//}
//await navigator.bluetooth.requestDevice(options); //navigator.bluetooth.requestDevice(options)

try {
const device = await navigator.bluetooth.requestDevice(options);
//navigator.bluetooth.requestDevice({
// acceptAllDevices: true,
// optionalServices: optionalServices})
//.then(device => {
console.log('> Name: ' + device.name);
console.log('> Id: ' + device.id);
console.log('> Connected: ' + device.gatt.connected);
// return device.gatt.connect();
//})
// .then(server => {
// // Note that we could also get all services that match a specific UUID by
// // passing it to getPrimaryServices().
// console.log('Getting Services...');
// return server.getPrimaryServices();
// })
// .then(services => {
// console.log('Getting Characteristics...');
// let queue = Promise.resolve();
// services.forEach(service => {
// queue = queue.then(_ => service.getCharacteristics().then(characteristics => {
// console.log('> Service: ' + service.uuid);
// characteristics.forEach(characteristic => {
// console.log('>> Characteristic: ' + characteristic.uuid + ' ' +
// getSupportedProperties(characteristic));
// });
// }));
// });
// return queue;
// })
//.catch(error => {
} catch(error) {
console.log('Argh! ' + error);
// });
}
}

async function newestonButtonClick() {
const controlServiceUUID = 0xfff0; // Full UUID
const commandCharacteristicUUID = 0xfff4; //
var myCharacteristic;
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: [controlServiceUUID]

})

.then(device => {
console.log("Got device name: ", device.name);
console.log("id: ", device.id);
return device.gatt.connect();
console.log("Here");
})

.then(server => {

serverInstance = server;
console.log("Getting PrimaryService");
return server.getPrimaryService(controlServiceUUID);
})

.then(service => {
console.log("Getting Characteristic");
return service.getCharacteristic(commandCharacteristicUUID);
})

.then(characteristic => {
// 0x01,3,0x02,0x03,0x01
myCharacteristic = characteristic;
return myCharacteristic.startNotifications().then(_ => {
log('Notifications started');

myCharacteristic.addEventListener('characteristicvaluechanged', test);
});
})
.catch(function(error) {
console.log("Something went wrong. " + error);
});
}

function consolelog(incis) {
pref=incis + ' ... ';
document.getElementById('result').innerHTML+=incis + '</br>';
return console.log(incis);
}


async function onButtonClick() {
try {
consolelog('Requesting any Bluetooth Device...');
const device = await navigator.bluetooth.requestDevice({
// filters: [...] <- Prefer filters to save energy & show relevant devices.
acceptAllDevices: true,
optionalServices: ['device_information']});


consolelog('Connecting to GATT Server...');
const server = await device.gatt.connect();

consolelog('Getting Device Information Service...');
const service = await server.getPrimaryService('device_information');

consolelog('Getting Device Information Characteristics...');
const characteristics = await service.getCharacteristics();

const decoder = new TextDecoder('utf-8');
for (const characteristic of characteristics) {
switch (characteristic.uuid) {

case BluetoothUUID.getCharacteristic('manufacturer_name_string'):
await characteristic.readValue().then(value => {
consolelog('> Manufacturer Name String: ' + decoder.decode(value));
});
break;

case BluetoothUUID.getCharacteristic('model_number_string'):
await characteristic.readValue().then(value => {
consolelog('> Model Number String: ' + decoder.decode(value));
});
break;

case BluetoothUUID.getCharacteristic('hardware_revision_string'):
await characteristic.readValue().then(value => {
consolelog('> Hardware Revision String: ' + decoder.decode(value));
});
break;

case BluetoothUUID.getCharacteristic('firmware_revision_string'):
await characteristic.readValue().then(value => {
consolelog('> Firmware Revision String: ' + decoder.decode(value));
});
break;

case BluetoothUUID.getCharacteristic('software_revision_string'):
await characteristic.readValue().then(value => {
consolelog('> Software Revision String: ' + decoder.decode(value));
});
break;

case BluetoothUUID.getCharacteristic('system_id'):
await characteristic.readValue().then(value => {
consolelog('> System ID: ');
consolelog(' > Manufacturer Identifier: ' +
padHex(value.getUint8(4)) + padHex(value.getUint8(3)) +
padHex(value.getUint8(2)) + padHex(value.getUint8(1)) +
padHex(value.getUint8(0)));
consolelog(' > Organizationally Unique Identifier: ' +
padHex(value.getUint8(7)) + padHex(value.getUint8(6)) +
padHex(value.getUint8(5)));
});
break;

case BluetoothUUID.getCharacteristic('ieee_11073-20601_regulatory_certification_data_list'):
await characteristic.readValue().then(value => {
consolelog('> IEEE 11073-20601 Regulatory Certification Data List: ' +
decoder.decode(value));
});
break;

case BluetoothUUID.getCharacteristic('pnp_id'):
await characteristic.readValue().then(value => {
consolelog('> PnP ID:');
consolelog(' > Vendor ID Source: ' +
(value.getUint8(0) === 1 ? 'Bluetooth' : 'USB'));
if (value.getUint8(0) === 1) {
consolelog(' > Vendor ID: ' +
(value.getUint8(1) | value.getUint8(2) << 8));
} else {
consolelog(' > Vendor ID: ' +
getUsbVendorName(value.getUint8(1) | value.getUint8(2) << 8));
}
consolelog(' > Product ID: ' +
(value.getUint8(3) | value.getUint8(4) << 8));
consolelog(' > Product Version: ' +
(value.getUint8(5) | value.getUint8(6) << 8));
});
break;

default: consolelog('> Unknown Characteristic: ' + characteristic.uuid);
}
}
} catch(error) {
document.getElementById('result').innerHTML+='Argh! ' + pref + error + '</br>';
console.log('Argh! ' + pref + error);
}
}

/* Utils */

function padHex(value) {
return ('00' + value.toString(16).toUpperCase()).slice(-2);
}

function getUsbVendorName(value) {
// Check out page source to see what valueToUsbVendorName object is.
return value +
(value in valueToUsbVendorName ? ' (' + valueToUsbVendorName[value] + ')' : '');
}
</script>
</head>
<body>
<h2>Web Bluetooth API Testing</h2>
<h3>RJM Programming - June, 2022</h3>
<h4>Thanks to <a target=_blank title='https://googlechrome.github.io/samples/web-bluetooth/device-info.html' href='//googlechrome.github.io/samples/web-bluetooth/device-info.html'>https://googlechrome.github.io/samples/web-bluetooth/device-info.html</a></h4>
<div id=result>
</div><br><br>

<span>Name</span><br>
<input type=text id=name placeholder="" value=""></input><br><br>
<span>All Devices ... </span><br>
<input type=checkbox id=allDevices checked></input><br><br><br>
<input type=hidden id=optionalServices value=''></input>
<input type=hidden id=service value=''></input>
<input type=hidden id=characteristic value=''></input><br><br>
<button onclick="onButtonClick();">Bluetooth <br>Check</button>
</body>
</html>