Improved Bluetooth sketches and docs
This commit is contained in:
parent
6ba0802caf
commit
5a010bfb1b
3 changed files with 208 additions and 93 deletions
66
Arduino/Bluetooth.ino
Normal file
66
Arduino/Bluetooth.ino
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include <bluefruit.h>
|
||||
|
||||
unit8_t uvindexvalue = 0x0;
|
||||
#define UUID16_SVC_ENVIRONMENTAL_SENSING 0x181A
|
||||
#define UUID16_CHR_UV_INDEX 0x2A76
|
||||
|
||||
BLEService enviromental_sensing_service = BLEService(UUID16_SVC_ENVIRONMENTAL_SENSING);
|
||||
BLECharacteristic uv_index_characteristic = BLECharacteristic(UUID16_CHR_UV_INDEX);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.beginn(115200);
|
||||
delay(500);
|
||||
Serial.println("Start!");
|
||||
|
||||
Bluefruit.begin();
|
||||
Bluefruit.setName("Palm");
|
||||
|
||||
setupESService();
|
||||
startAvd();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
uvindexvalue = random(0, 11);
|
||||
|
||||
Serial.print("UV Index: ");
|
||||
Serial.println(uvindexvalue);
|
||||
|
||||
if (uv_index_characteristic.indicate(&uvindexvalue, sizeof(uvindexvalue)))
|
||||
{
|
||||
Serial.print("Updated UV Index: ");
|
||||
Serial.println(uvindexvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("UV Index Indicate not set");
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
|
||||
}
|
||||
|
||||
void startAvd(void)
|
||||
{
|
||||
Bluefruit.Advertising.addService(environmental_sensing_service);
|
||||
|
||||
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
|
||||
Bluefruit.Advertising.addTxPower();
|
||||
Bluefruit.Advertising.addName();
|
||||
Bluefruit.Advertising.restartOnDisconnect(true);
|
||||
Bluefruit.Advertising.setInterval(32, 244);
|
||||
Bluefruit.Advertising.setFastTimeout(30);
|
||||
Bluefruit.Advertising.start(0);
|
||||
}
|
||||
|
||||
void setupESService(void) {
|
||||
environmental_sensing_service.begin();
|
||||
|
||||
uv_index_characteristic.setProperties(CHR_PROPS_INDICATE);
|
||||
uv_index_characteristic.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
|
||||
uv_index_characteristic.setFixedLen(1);
|
||||
uv_index_characteristic.begin();
|
||||
|
||||
uv_index_characteristic.write(&uvindexvalue, sizeof(uvindexvalue));
|
||||
}
|
15
README.md
15
README.md
|
@ -7,8 +7,13 @@ Download [Android SDK Platform-Tools](https://developer.android.com/studio/relea
|
|||
|
||||
Commands:
|
||||
```
|
||||
./adb pair 10.1.0.125:38407
|
||||
./adb connect 10.1.0.125:39099
|
||||
./platform-tools/adb pair 10.1.0.125:38407
|
||||
./platform-tools/adb connect 10.1.0.125:39099
|
||||
```
|
||||
|
||||
And debug Chrome:
|
||||
```
|
||||
chrome://inspect/#devices
|
||||
```
|
||||
|
||||
Chrome flags to be enabled:
|
||||
|
@ -23,5 +28,7 @@ chrome://bluetooth-internals/#devices
|
|||
```
|
||||
Other resources:
|
||||
|
||||
- [GATT Characteristics](https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf)
|
||||
- [Using Web BLE](https://youtu.be/TsXUcAKi790)
|
||||
- [Android Wireless Debugging](https://youtu.be/gyVZdZtIxnw?t=49) Tutorial
|
||||
- [GATT Characteristics](https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf) Document
|
||||
- [Using Web BLE](https://youtu.be/TsXUcAKi790) Tutorial
|
||||
- [Adafruit Feather nRF52 Bluefruit LE](https://www.berrybase.de/adafruit-feather-nrf52-bluefruit-le) Dev. Boards
|
|
@ -1,108 +1,150 @@
|
|||
import { useState } from "react"
|
||||
|
||||
function Bluetooth() {
|
||||
const connectToDevice = async () => {
|
||||
if (!navigator.bluetooth)
|
||||
console.log('Web Bluetooth is not available!');
|
||||
navigator.bluetooth
|
||||
.requestDevice({
|
||||
filters: [
|
||||
{ namePrefix: "Chromecast Remote" }
|
||||
],
|
||||
optionalServices: ["battery_service"],
|
||||
})
|
||||
.then(device => {
|
||||
console.log(device);
|
||||
// console.log(device.id, device.name, device.gatt);
|
||||
// Set up event listener for when device gets disconnected.
|
||||
device.addEventListener('gattserverdisconnected', onDisconnected);
|
||||
const [startDisabled, setStartDisabled] = useState(true)
|
||||
const [stopDisabled, setStopDisabled] = useState(true)
|
||||
|
||||
console.log(1)
|
||||
// Attempts to connect to remote GATT Server.
|
||||
const gatt = device.gatt
|
||||
if (!gatt)
|
||||
throw new Error('no gatt');
|
||||
return gatt.connect();
|
||||
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(2)
|
||||
console.log(server)
|
||||
// Getting Battery Service…
|
||||
return server.getPrimaryService('battery_service');
|
||||
console.log('Getting GATT Service...')
|
||||
return server.getPrimaryService(bleService)
|
||||
})
|
||||
.then(service => {
|
||||
console.log(3)
|
||||
// Getting Battery Level Characteristic…
|
||||
return service.getCharacteristic('battery_level');
|
||||
// return service.getCharacteristic(0x2a19);
|
||||
console.log('Getting GATT Characteristic...')
|
||||
return service.getCharacteristic(bleCharacteristic)
|
||||
})
|
||||
.then(characteristic => {
|
||||
console.log(4)
|
||||
// Reading Battery Level…
|
||||
return characteristic.readValue();
|
||||
gattCharacteristic = characteristic
|
||||
characteristic.addEventListener('characteristicvaluechanged', handleChangedValue)
|
||||
|
||||
setStartDisabled(false)
|
||||
setStopDisabled(true)
|
||||
})
|
||||
.then(value => {
|
||||
console.log(5)
|
||||
console.log(`Battery percentage is ${value.getUint8(0)}`);
|
||||
})
|
||||
.catch(error => { console.log(error); });
|
||||
}
|
||||
const connectToDevice2 = async () => {
|
||||
if (!navigator.bluetooth)
|
||||
console.log('Web Bluetooth is not available!');
|
||||
let device = await navigator.bluetooth
|
||||
navigator.bluetooth
|
||||
.requestDevice({
|
||||
filters: [
|
||||
{ namePrefix: "Chromecast Remote" }
|
||||
],
|
||||
optionalServices: ["device_information"],
|
||||
})
|
||||
.then(device => {
|
||||
// Set up event listener for when device gets disconnected.
|
||||
device.addEventListener('gattserverdisconnected', onDisconnected);
|
||||
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}`)
|
||||
|
||||
console.log(1)
|
||||
// Attempts to connect to remote GATT Server.
|
||||
const gatt = device.gatt
|
||||
if (!gatt)
|
||||
throw new Error('no gatt');
|
||||
return gatt.connect();
|
||||
})
|
||||
.then(server => {
|
||||
console.log(2)
|
||||
console.log(server)
|
||||
// Getting Battery Service…
|
||||
return server.getPrimaryService('device_information');
|
||||
})
|
||||
.then(service => {
|
||||
console.log(3)
|
||||
// Getting Battery Level Characteristic…
|
||||
return service.getCharacteristic('manufacturer_name_string');
|
||||
})
|
||||
.then(characteristic => {
|
||||
console.log(4)
|
||||
// Reading Battery Level…
|
||||
return characteristic.readValue();
|
||||
})
|
||||
.then(value => {
|
||||
console.log(5)
|
||||
let decoder = new TextDecoder('utf-8');
|
||||
console.log(decoder.decode(value));
|
||||
})
|
||||
.catch(error => { console.log(error); });
|
||||
// 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)}`)
|
||||
}
|
||||
|
||||
const onDisconnected = (event: any) => {
|
||||
// alert("Device Disconnected");
|
||||
// console.log(event);
|
||||
const device = event.target;
|
||||
console.log(`Device "${device.name}" is disconnected.`);
|
||||
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 (
|
||||
<>
|
||||
<button className="bluetooth" onClick={connectToDevice2}>CONNECT</button>
|
||||
<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>
|
||||
</>
|
||||
)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue