I need to read distance measurements from a Leica Disto D2 in a Web App using Web Bluetooth API. I'm targeting recent Android devices so Chrome/Samsung Browser should support it.
I've adapted the code from the answer by Mark Robinson, fixed a couple of things and added support for auto-connecting on page refresh
Live demo https://murkle.github.io/utils/webbluetooth/leica_distoD2_laser_measurer.html
// info from https://stackoverflow.com/questions/69629692/how-to-read-laser-distance-measure-via-web-bluetooth
const DISTO_SERVICEID = '3ab10100-f831-4395-b29d-570977d5bf94';
const DISTO_DISTANCE = "3ab10101-f831-4395-b29d-570977d5bf94";
const DISTO_DISTANCE_UNIT = "3ab10102-f831-4395-b29d-570977d5bf94";
const DISTO_COMMAND = "3ab10109-f831-4395-b29d-570977d5bf94";
const STATE_RESPONSE = "3ab1010a-f831-4395-b29d-570977d5bf94";
const DS_MODEL_NAME = "3ab1010c-f831-4395-b29d-570977d5bf94";
const BATTERY_SERVICE = '0000180f-0000-1000-8000-00805f9b34fb';
const DEVICE_INFORMATION = '0000180a-0000-1000-8000-00805f9b34fb';
const namePrefix = "DISTO ";
let service;
let device;
const logElement = document.getElementById('logging'); ;
function log(message) {
const logEntry = document.createElement('div');
logEntry.classList.add('log-entry');
logEntry.innerText = message;
logElement.appendChild(logEntry);
}
function handleDisconnect() {
log('Connection lost. Device disconnected.');
document.getElementById('connectButton').disabled = false;
document.getElementById('disconnectButton').disabled = true;
alert('Connection lost. Device disconnected.');
}
function disconnectFromDevice() {
if (device && device.gatt.connected) {
device.gatt.disconnect();
}
}
function forgetDevice() {
if (device) {
device.forget();
}
}
async function discoverDevices() {
log("discoverDevices");
let filters = [];
// filter on EITHER namePrefix OR services
filters.push({
namePrefix: namePrefix
});
//filters.push({
// services: [DISTO_SERVICEID]
//});
let options = {
optionalServices: [DEVICE_INFORMATION, BATTERY_SERVICE, DISTO_SERVICEID],
acceptAllDevices: false
}
options.filters = filters;
device = await navigator.bluetooth.requestDevice(options);
log('> Name:' + device.name);
log('> Id:' + device.id);
log(device);
await connectToDevice(device);
log('Notifications have been started.');
}
async function connectToDevice(device) {
device.addEventListener('gattserverdisconnected', onDisconnected);
log('Connecting to GATT Server...');
const server = await device.gatt.connect();
log('Getting Service...');
const service = await server.getPrimaryService(DISTO_SERVICEID);
log('Getting Distance Characteristic...');
const characteristic = await service.getCharacteristic(DISTO_DISTANCE);
characteristic.addEventListener('characteristicvaluechanged', handleDistanceChanged);
log('Enabling notifications...');
await characteristic.startNotifications();
log('Connected to ' + device.name);
}
function handleDistanceChanged(event) {
const value = event.target.value;
log('Got distance: ' + value.getFloat32(0, true));
document.getElementById("result").innerHTML = "Distance = " + value.getFloat32(0, true).toFixed(4) + " m";
}
function onDisconnected(event) {
const device = event.target;
log(`Device ${device.name} is disconnected.`);
}
function log(message) {
const logEntry = document.createElement('div');
logEntry.classList.add('log-entry');
logEntry.innerText = message;
logElement.appendChild(logEntry);
}
// https://docs.google.com/document/d/1RF4D-60cQJWR1LoQeLBxxigrxJwYS8nLOE0qWmBF1eo/edit
// try to connect to existing device
async function getPermittedBluetoothDevices() {
let devices = await navigator.bluetooth.getDevices();
for (let device0 of devices) {
// Start a scan for each device before connecting to check that they're in
// range.
let abortController = new AbortController();
await device0.watchAdvertisements({
signal: abortController.signal
});
device0.addEventListener('advertisementreceived', async(evt) => {
// Stop the scan to conserve power on mobile devices.
abortController.abort();
// Advertisement data can be read from |evt|.
let deviceName = evt.name;
let uuids = evt.uuids;
let appearance = evt.appearance;
let pathloss = evt.txPower - evt.rssi;
let manufacturerData = evt.manufacturerData;
let serviceData = evt.serviceData;
if (evt.device.name.startsWith(namePrefix)) {
log("Found previously connected device " + device0.name)
// At this point, we know that the device is in range, and we can attempt
// to connect to it.
device = evt.device;
await connectToDevice(device);
} else {
log("Ignoring device " + device0.name + " as it doesn't start with " + namePrefix);
}
});
}
}
getPermittedBluetoothDevices();