initial support for bluetooth, pairing not tested, I don't have a supported device
This commit is contained in:
143
index.html
143
index.html
@@ -197,6 +197,36 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="border bg-gray-50 rounded shadow">
|
||||||
|
|
||||||
|
<div class="border-b px-2 py-1">
|
||||||
|
6. Configure Bluetooth (optional)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-3">
|
||||||
|
|
||||||
|
<div class="space-x-1">
|
||||||
|
<button @click="enableBluetooth" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
|
||||||
|
Enable
|
||||||
|
</button>
|
||||||
|
<button @click="disableBluetooth" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
|
||||||
|
Disable
|
||||||
|
</button>
|
||||||
|
<button @click="startBluetoothPairing" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
|
||||||
|
Start Pairing
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="border-t px-2 py-1">
|
||||||
|
<div class="text-sm space-x-1">
|
||||||
|
Bluetooth is not supported on all devices.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="border bg-gray-50 rounded shadow">
|
<div class="border bg-gray-50 rounded shadow">
|
||||||
|
|
||||||
<div class="border-b px-2 py-1">
|
<div class="border-b px-2 py-1">
|
||||||
@@ -1317,6 +1347,119 @@
|
|||||||
await rnode.close();
|
await rnode.close();
|
||||||
alert("TNC mode has been disabled!");
|
alert("TNC mode has been disabled!");
|
||||||
|
|
||||||
|
},
|
||||||
|
async enableBluetooth() {
|
||||||
|
|
||||||
|
// ask for serial port
|
||||||
|
const serialPort = await this.askForSerialPort();
|
||||||
|
if(!serialPort){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if device is an rnode
|
||||||
|
const rnode = await RNode.fromSerialPort(serialPort);
|
||||||
|
const isRNode = await rnode.detect();
|
||||||
|
if(!isRNode){
|
||||||
|
alert("Selected device is not an RNode!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if device has been provisioned
|
||||||
|
const rom = await rnode.getRomAsObject();
|
||||||
|
const details = rom.parse();
|
||||||
|
if(!details || !details.is_provisioned){
|
||||||
|
alert("Eeprom is not provisioned. You must do this first!");
|
||||||
|
await rnode.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable bluetooth
|
||||||
|
console.log("enabling bluetooth");
|
||||||
|
await rnode.enableBluetooth();
|
||||||
|
console.log("enabling bluetooth: done");
|
||||||
|
|
||||||
|
await Utils.sleepMillis(1000);
|
||||||
|
|
||||||
|
// done
|
||||||
|
await rnode.close();
|
||||||
|
alert("Bluetooth has been enabled!");
|
||||||
|
|
||||||
|
},
|
||||||
|
async disableBluetooth() {
|
||||||
|
|
||||||
|
// ask for serial port
|
||||||
|
const serialPort = await this.askForSerialPort();
|
||||||
|
if(!serialPort){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if device is an rnode
|
||||||
|
const rnode = await RNode.fromSerialPort(serialPort);
|
||||||
|
const isRNode = await rnode.detect();
|
||||||
|
if(!isRNode){
|
||||||
|
alert("Selected device is not an RNode!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if device has been provisioned
|
||||||
|
const rom = await rnode.getRomAsObject();
|
||||||
|
const details = rom.parse();
|
||||||
|
if(!details || !details.is_provisioned){
|
||||||
|
alert("Eeprom is not provisioned. You must do this first!");
|
||||||
|
await rnode.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable bluetooth
|
||||||
|
console.log("disabling bluetooth");
|
||||||
|
await rnode.disableBluetooth();
|
||||||
|
console.log("disabling bluetooth: done");
|
||||||
|
|
||||||
|
await Utils.sleepMillis(1000);
|
||||||
|
|
||||||
|
// done
|
||||||
|
await rnode.close();
|
||||||
|
alert("Bluetooth has been disabled!");
|
||||||
|
|
||||||
|
},
|
||||||
|
async startBluetoothPairing() {
|
||||||
|
|
||||||
|
// ask for serial port
|
||||||
|
const serialPort = await this.askForSerialPort();
|
||||||
|
if(!serialPort){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if device is an rnode
|
||||||
|
const rnode = await RNode.fromSerialPort(serialPort);
|
||||||
|
const isRNode = await rnode.detect();
|
||||||
|
if(!isRNode){
|
||||||
|
alert("Selected device is not an RNode!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if device has been provisioned
|
||||||
|
const rom = await rnode.getRomAsObject();
|
||||||
|
const details = rom.parse();
|
||||||
|
if(!details || !details.is_provisioned){
|
||||||
|
alert("Eeprom is not provisioned. You must do this first!");
|
||||||
|
await rnode.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start bluetooth pairing
|
||||||
|
try {
|
||||||
|
console.log("start bluetooth pairing");
|
||||||
|
const pin = await rnode.startBluetoothPairing();
|
||||||
|
console.log("start bluetooth pairing: done");
|
||||||
|
alert(`Bluetooth Pairing Pin: ${pin}`);
|
||||||
|
} catch(error) {
|
||||||
|
alert(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
await rnode.close();
|
||||||
|
|
||||||
},
|
},
|
||||||
async readAsBinaryString(blob) {
|
async readAsBinaryString(blob) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|||||||
84
js/rnode.js
84
js/rnode.js
@@ -147,32 +147,48 @@ class RNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async readFromSerialPort() {
|
async readFromSerialPort(timeoutMillis) {
|
||||||
const reader = this.readable.getReader();
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
|
||||||
let buffer = [];
|
// create reader
|
||||||
while(true){
|
const reader = this.readable.getReader();
|
||||||
const { value, done } = await reader.read();
|
|
||||||
if(done){
|
// timeout after provided millis
|
||||||
break;
|
if(timeoutMillis != null){
|
||||||
}
|
setTimeout(() => {
|
||||||
if(value){
|
reader.releaseLock();
|
||||||
for(let byte of value){
|
reject("timeout");
|
||||||
buffer.push(byte);
|
}, timeoutMillis);
|
||||||
if(byte === this.KISS_FEND){
|
}
|
||||||
if(buffer.length > 1){
|
|
||||||
return this.handleKISSFrame(buffer);
|
// attempt to read kiss frame
|
||||||
|
try {
|
||||||
|
let buffer = [];
|
||||||
|
while(true){
|
||||||
|
const { value, done } = await reader.read();
|
||||||
|
if(done){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(value){
|
||||||
|
for(let byte of value){
|
||||||
|
buffer.push(byte);
|
||||||
|
if(byte === this.KISS_FEND){
|
||||||
|
if(buffer.length > 1){
|
||||||
|
resolve(this.handleKISSFrame(buffer));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer = [this.KISS_FEND]; // Start new frame
|
||||||
}
|
}
|
||||||
buffer = [this.KISS_FEND]; // Start new frame
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error reading from serial port: ', error);
|
||||||
|
} finally {
|
||||||
|
reader.releaseLock();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error('Error reading from serial port: ', error);
|
});
|
||||||
} finally {
|
|
||||||
reader.releaseLock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKISSFrame(frame) {
|
handleKISSFrame(frame) {
|
||||||
@@ -515,10 +531,36 @@ class RNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async startBluetoothPairing() {
|
async startBluetoothPairing() {
|
||||||
|
|
||||||
|
// enable pairing
|
||||||
await this.sendKissCommand([
|
await this.sendKissCommand([
|
||||||
this.CMD_BT_CTRL,
|
this.CMD_BT_CTRL,
|
||||||
0x02, // enable pairing
|
0x02, // enable pairing
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// attempt to get bluetooth pairing pin
|
||||||
|
try {
|
||||||
|
|
||||||
|
// read response from device
|
||||||
|
const [ command, ...pinBytes ] = await this.readFromSerialPort(5000);
|
||||||
|
if(command !== this.CMD_BT_PIN){
|
||||||
|
throw `unexpected command response: ${command}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert 4 bytes to 32bit integer
|
||||||
|
const pin = pinBytes[0] << 24 | pinBytes[1] << 16 | pinBytes[2] << 8 | pinBytes[3];
|
||||||
|
|
||||||
|
// todo: remove logs
|
||||||
|
console.log(pinBytes);
|
||||||
|
console.log(pin);
|
||||||
|
|
||||||
|
// todo: convert to string
|
||||||
|
return pin;
|
||||||
|
|
||||||
|
} catch(error) {
|
||||||
|
throw `failed to get bluetooth pin: ${error}`;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async setFrequency(frequencyInHz) {
|
async setFrequency(frequencyInHz) {
|
||||||
|
|||||||
Reference in New Issue
Block a user