leaky-ships/leaky-ships/components/Bluetooth.tsx
2023-07-11 19:25:44 +02:00

189 lines
5.4 KiB
TypeScript

import { useState } from "react"
function Bluetooth() {
const [startDisabled, setStartDisabled] = useState(true)
const [stopDisabled, setStopDisabled] = useState(true)
const deviceName = "Chromecast Remote"
// ble UV Index
const bleService = "environmental_sensing"
const bleCharacteristic = "uv_index"
// ble Battery percentage
// const bleService = 'battery_service'
// const bleCharacteristic = 'battery_level'
// ble Manufacturer Name
// const bleService = 'device_information'
// const bleCharacteristic = 'manufacturer_name_string'
let bluetoothDeviceDetected: BluetoothDevice
let gattCharacteristic: BluetoothRemoteGATTCharacteristic
function isWebBluetoothEnabled() {
if (!navigator.bluetooth) {
alert("Web Bluetooth API is not available in this browser!")
return false
}
return true
}
function getDeviceInfo() {
const options = {
// acceptAllDevices: true,
filters: [{ name: deviceName }],
// optionalServices: ['battery_service'],
}
console.log("Requesting Bluetooth Device...")
return navigator.bluetooth
.requestDevice(options)
.then((device) => {
bluetoothDeviceDetected = device
console.log("> Name: " + device.name)
device.addEventListener("gattserverdisconnected", onDisconnected)
})
.catch((error) => console.log("Argh! " + error))
}
function read() {
if (!isWebBluetoothEnabled()) return
return getDeviceInfo()
.then(connectGatt)
.then((_) => {
console.log("Reading UV Index...")
return gattCharacteristic.readValue()
})
.catch((error) => console.log("Waiting to start reading: " + error))
}
function connectGatt() {
if (
bluetoothDeviceDetected.gatt &&
bluetoothDeviceDetected.gatt.connected &&
gattCharacteristic
)
return Promise.resolve()
if (!bluetoothDeviceDetected || !bluetoothDeviceDetected.gatt)
return Promise.reject()
return bluetoothDeviceDetected.gatt
.connect()
.then((server) => {
console.log("Getting GATT Service...")
return server.getPrimaryService(bleService)
})
.then((service) => {
console.log("Getting GATT Characteristic...")
return service.getCharacteristic(bleCharacteristic)
})
.then((characteristic) => {
gattCharacteristic = characteristic
characteristic.addEventListener(
"characteristicvaluechanged",
handleChangedValue,
)
setStartDisabled(false)
setStopDisabled(true)
})
}
function handleChangedValue(event: Event) {
const characteristic = event.target as BluetoothRemoteGATTCharacteristic
if (!characteristic.value) {
console.log("Characteristic undefined!")
return
}
const value = characteristic.value.getUint8(0)
const now = new Date()
// Output the UV Index
console.log(
`> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} UV Index is ${value}`,
)
// Output the Battery percentage
// console.log(`> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} Battery percentage is ${value}`)
// Output the Manufacturer Name
// let decoder = new TextDecoder('utf-8')
// console.log(`> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} Manufacturer Name is ${decoder.decode(characteristic.value)}`)
}
function start() {
if (!isWebBluetoothEnabled()) return
gattCharacteristic
.startNotifications()
.then((_) => {
console.log("Start reading...")
setStartDisabled(true)
setStopDisabled(false)
})
.catch((error) => console.log("[ERROR] Start: " + error))
}
function stop() {
if (!isWebBluetoothEnabled()) return
gattCharacteristic
.stopNotifications()
.then((_) => {
console.log("Stop reading...")
setStartDisabled(false)
setStopDisabled(true)
})
.catch((error) => console.log("[ERROR] Stop: " + error))
}
function onDisconnected(event: Event) {
alert("Device Disconnected")
// console.log(event)
const device = event.target as BluetoothDevice
console.log(`Device "${device.name}" is disconnected.`)
}
return (
<div>
<button id="read" className="bluetooth" onClick={read}>
Connect with BLE device
</button>
<button
id="start"
className="bluetooth"
disabled={startDisabled}
onClick={start}
>
Start
</button>
<button
id="stop"
className="bluetooth"
disabled={stopDisabled}
onClick={stop}
>
Stop
</button>
<p>
<span
className="App-link"
onClick={() => {
navigator.clipboard.writeText(
"chrome://flags/#enable-experimental-web-platform-features",
)
}}
// target="_blank"
style={{ cursor: "pointer" }}
// rel="noopener noreferrer"
>
Step 1
</span>{" "}
<span
className="App-link"
onClick={() => {
navigator.clipboard.writeText(
"chrome://flags/#enable-web-bluetooth-new-permissions-backend",
)
}}
// target="_blank"
style={{ cursor: "pointer" }}
// rel="noopener noreferrer"
>
Step 2
</span>
</p>
</div>
)
}
export default Bluetooth