I have a (3rd party) native android app which sends data to a sports scoreboard via bluetooth. The scoreboard has an embedded raspberry pi where the bluetooth server is running. It seems to work fine.
I have written a React SPA/PWA for controlling the scoreboard and have been investigating the Web Bluetooth API and putting it through its paces. It is showing great promise. However, I have an issue at the moment which I can't get to the bottom of. When my app first connects to the board, everything is hunky-dory. But then, if I disconnect, and then reconnect to the service, the bluetooth device no longer receives any data. No exception is being thrown, and the async call which is writing to the characteristic never seems to return (it appears to be running indefinitely in the background, and nothing is being written to the device). My code is below. It is only first draft. It is a react hook, whose functions are being called by various parts of the program.
The problem could well be with the server, but I just wanted a sanity check that I was handling things properly on the javascript side.
import { useEffect, useState } from 'react'
function useBluetoothScoreboard(options) {
const [isBluetoothAvailable, setIsBluetoothAvailable] = useState(false);
const [connectionInProgress, setConnectionInProgress] = useState(false);
const [isConnected, setIsConnected] = useState(false);
const [scoreboardDevice, setScoreboardDevice] = useState(null);
const [scoreboardDeviceServer, setScoreboardDeviceServer] = useState(null);
useEffect(() => {
navigator.bluetooth.getAvailability()
.then((available) => {
setIsBluetoothAvailable(available);
})
.catch(() => {
setIsBluetoothAvailable(false);
})
}, []);
const disconnected = () => {
console.log('Scoreboard is disconnected.');
}
const onConnect = async () => {
try {
if (!isConnected) {
const connectScoreboard = async () => {
const options = {
filters: [{
namePrefix: 'CricNet'
}],
optionalServices: ['5a0d6a15-b664-4304-8530-3a0ec53e5bc1']
};
let device = null;
if (!scoreboardDevice) {
console.log('Pairing with bluetooth scoreboard ...');
device = await navigator.bluetooth.requestDevice(options);
device.addEventListener('gattserverdisconnected', disconnected);
setScoreboardDevice(device);
}
else
{
device = scoreboardDevice;
}
console.log('Connecting to bluetooth scoreboard ...');
const deviceServer = await device.gatt.connect();
setScoreboardDeviceServer(deviceServer)
};
setConnectionInProgress(true);
await connectScoreboard();
setConnectionInProgress(false);
setIsConnected(true);
}
}
catch (e) {
console.error(e);
setConnectionInProgress(false);
setIsConnected(false);
}
};
const onDisconnect = async () => {
if (isConnected) {
console.log('Disconnecting ...');
if (scoreboardDevice.gatt.connected) {
scoreboardDevice.gatt.disconnect();
setScoreboardDeviceServer(null)
}
setIsConnected(false);
}
};
const write = async (total) => {
const buffer = new ArrayBuffer(6);
const view = new Int16Array(buffer);
view[0] = -1896;
view[1] = 0;
view[2] = total;
if (isConnected) {
try {
console.log('Getting service ...');
const service = await scoreboardDeviceServer.getPrimaryService('5a0d6a15-b664-4304-8530-3a0ec53e5bc1');
console.log('Getting characteristic ...');
const characteristic = await service.getCharacteristic('df531f62-fc0b-40ce-81b2-32a6262ea440');
await characteristic.writeValueWithoutResponse(buffer);
console.log('Should have written ...')
}
catch (e) {
console.log(e)
}
}
};
return { isBluetoothAvailable, connectionInProgress, isConnected, onConnect, write, onDisconnect };
}
export default useBluetoothScoreboard;