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:
|
Commands:
|
||||||
```
|
```
|
||||||
./adb pair 10.1.0.125:38407
|
./platform-tools/adb pair 10.1.0.125:38407
|
||||||
./adb connect 10.1.0.125:39099
|
./platform-tools/adb connect 10.1.0.125:39099
|
||||||
|
```
|
||||||
|
|
||||||
|
And debug Chrome:
|
||||||
|
```
|
||||||
|
chrome://inspect/#devices
|
||||||
```
|
```
|
||||||
|
|
||||||
Chrome flags to be enabled:
|
Chrome flags to be enabled:
|
||||||
|
@ -23,5 +28,7 @@ chrome://bluetooth-internals/#devices
|
||||||
```
|
```
|
||||||
Other resources:
|
Other resources:
|
||||||
|
|
||||||
- [GATT Characteristics](https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf)
|
- [Android Wireless Debugging](https://youtu.be/gyVZdZtIxnw?t=49) Tutorial
|
||||||
- [Using Web BLE](https://youtu.be/TsXUcAKi790)
|
- [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() {
|
function Bluetooth() {
|
||||||
const connectToDevice = async () => {
|
const [startDisabled, setStartDisabled] = useState(true)
|
||||||
if (!navigator.bluetooth)
|
const [stopDisabled, setStopDisabled] = useState(true)
|
||||||
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);
|
|
||||||
|
|
||||||
console.log(1)
|
const deviceName = 'Chromecast Remote'
|
||||||
// Attempts to connect to remote GATT Server.
|
// ble UV Index
|
||||||
const gatt = device.gatt
|
const bleService = 'environmental_sensing'
|
||||||
if (!gatt)
|
const bleCharacteristic = 'uv_index'
|
||||||
throw new Error('no gatt');
|
|
||||||
return gatt.connect();
|
// 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 => {
|
.then(server => {
|
||||||
console.log(2)
|
console.log('Getting GATT Service...')
|
||||||
console.log(server)
|
return server.getPrimaryService(bleService)
|
||||||
// Getting Battery Service…
|
|
||||||
return server.getPrimaryService('battery_service');
|
|
||||||
})
|
})
|
||||||
.then(service => {
|
.then(service => {
|
||||||
console.log(3)
|
console.log('Getting GATT Characteristic...')
|
||||||
// Getting Battery Level Characteristic…
|
return service.getCharacteristic(bleCharacteristic)
|
||||||
return service.getCharacteristic('battery_level');
|
|
||||||
// return service.getCharacteristic(0x2a19);
|
|
||||||
})
|
})
|
||||||
.then(characteristic => {
|
.then(characteristic => {
|
||||||
console.log(4)
|
gattCharacteristic = characteristic
|
||||||
// Reading Battery Level…
|
characteristic.addEventListener('characteristicvaluechanged', handleChangedValue)
|
||||||
return characteristic.readValue();
|
|
||||||
|
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 () => {
|
function handleChangedValue(event: Event) {
|
||||||
if (!navigator.bluetooth)
|
const characteristic = event.target as BluetoothRemoteGATTCharacteristic
|
||||||
console.log('Web Bluetooth is not available!');
|
if (!characteristic.value) {
|
||||||
let device = await navigator.bluetooth
|
console.log('Characteristic undefined!')
|
||||||
navigator.bluetooth
|
return
|
||||||
.requestDevice({
|
|
||||||
filters: [
|
|
||||||
{ namePrefix: "Chromecast Remote" }
|
|
||||||
],
|
|
||||||
optionalServices: ["device_information"],
|
|
||||||
})
|
|
||||||
.then(device => {
|
|
||||||
// Set up event listener for when device gets disconnected.
|
|
||||||
device.addEventListener('gattserverdisconnected', onDisconnected);
|
|
||||||
|
|
||||||
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); });
|
|
||||||
}
|
}
|
||||||
|
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}`)
|
||||||
|
|
||||||
const onDisconnected = (event: any) => {
|
// Output the Battery percentage
|
||||||
// alert("Device Disconnected");
|
// console.log(`> ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} Battery percentage is ${value}`)
|
||||||
// console.log(event);
|
|
||||||
const device = event.target;
|
// Output the Manufacturer Name
|
||||||
console.log(`Device "${device.name}" is disconnected.`);
|
// 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 (
|
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