<html>
<body>
<button onclick="ble.connect()">Connect</button>
<button onclick="ble.disconnect()">Disconnect</button>
</body>
<script>
var ble;
function log(obj,type){console.log(obj)}
document.addEventListener('DOMContentLoaded', () => {
ble=new Ble({
log, // ссылка на 'местную' функцию лога.
ondata:(event)=>{ // событие возникающее при срабатывании characteristicvaluechanged
log("OnData");
let value = event.target.value.buffer ? event.target.value : new DataView(event.target.value);
if(value.byteLength > 1) {
let ds = value.getUint8(0);
if(ds+2 >= value.byteLength) {
let idx = value.getUint8(1);
// тут мы начинаем обрабатывать команды?
switch(idx)
{
case 0x0c:
break;
}
}
}
}});
});
// Все что ниже по тексту, весь этот класс, в дальнейшем, мы вынесем в отдельный подключаемый модуль ble.js
// Он в теории универсален для любых датчиков
class Ble
{
devcnn = 0;
deviceCache = null;
characteristicCache = null;
constructor(params) {
this._log=params.log;
this.ondata=params.ondata;
}
handleEvent(event)
{
switch(event.type)
{
case 'gattserverdisconnected':
let device = event.target;
if(this.devcnn != 0) {
this.log('"' + device.name + '" bluetooth device disconnected, trying to reconnect...');
this.connectDeviceAndCacheCharacteristic(device)
.then(characteristic => {
return this.startNotifications(characteristic)
})
.catch(error => this.log(error,'error'));
}
break;
case 'characteristicvaluechanged':
this.log('characteristicvaluechanged');
if(this.ondata) this.ondata(event);
break;
}
}
connect() {
return (this.deviceCache ? Promise.resolve(this.deviceCache) :
this.requestBluetoothDevice()).then(
device => this.connectDeviceAndCacheCharacteristic(device))
.then(characteristic => this.startNotifications(characteristic))
.catch(err => {
this.log(err,'error');
});
}
connectDeviceAndCacheCharacteristic(device) {
if (device.gatt.connected && this.characteristicCache) {
this.log("Reconnect ok");
return Promise.resolve(this.characteristicCache);
}
this.log('Connecting to GATT server...');
return device.gatt.connect().then(server => {
this.log('GATT server connected, getting service...');
return server.getPrimaryService(0xffe0);
}).then(service => {
this.log('Service found, getting characteristic...');
return service.getCharacteristic(0xffe1);
}).then(characteristic => {
this.log('Characteristic found');
this.characteristicCache = characteristic;
return this.characteristicCache;
});
}
startNotifications(characteristic) {
this.log('Starting notifications...');
return characteristic.startNotifications()
.then(() => {
this.log('Notifications started');
characteristic.addEventListener('characteristicvaluechanged', this);
this.devcnn = 1;
this.stage_read = 0;
setTimeout(()=>{this.SendWhoIs(this)}, 500);
});
}
SendWhoIs(e){
this.log('Send command #00: WhoIs?');
this.characteristicCache.writeValue(new Uint8Array([0, 0]));
}
requestBluetoothDevice() {
this.log('Requesting bluetooth device...');
return navigator.bluetooth.requestDevice({
filters: [{namePrefix: 'tBLE'}],
optionalServices: ['0000ffe0-0000-1000-8000-00805f9b34fb', '0000ffe1-0000-1000-8000-00805f9b34fb']
}).then(device => {
this.log('"' + device.name + '" bluetooth device selected');
this.deviceCache = device;
this.deviceCache.addEventListener('gattserverdisconnected', this);
return this.deviceCache;
});
}
disconnect() {
this.devcnn = 0;
if (this.deviceCache) {
this.log('Disconnecting from "' + this.deviceCache.name + '" bluetooth device...');
this.deviceCache.removeEventListener('gattserverdisconnected', this);
if (this.deviceCache.gatt.connected) {
if (this.characteristicCache) {
this.characteristicCache.stopNotifications()
.then(_ => {
this.log('Notifications stopped');
this.characteristicCache.removeEventListener('characteristicvaluechanged', this);
if (this.deviceCache.gatt.connected) {
this.deviceCache.gatt.disconnect();
this.log('"' + this.deviceCache.name + '" bluetooth device disconnected');
}
this.deviceCache = null;
})
.catch(error => { this.log(error,'error');
if (this.characteristicCache) {
this.characteristicCache.removeEventListener('characteristicvaluechanged', this);
this.characteristicCache = null;
}
this.deviceCache = null;
});
}
}
}
else
{
this.log('"' + this.deviceCache.name + '" bluetooth device is already disconnected');
}
}
log(o)
{
if(this._log) this._log(o);
}
}
</script>
</html>