update rnode flasher

This commit is contained in:
liamcottle 2025-02-08 13:14:48 +13:00
commit 6f321741d7
2 changed files with 413 additions and 294 deletions

View file

@ -110,7 +110,7 @@
<div class="border-t px-2 py-1 text-sm">
<div>
<span>Download Firmware</span>
<span v-if="selectedProduct && selectedModel && recommendedFirmwareFilename">: {{ recommendedFirmwareFilename }}</span>
<span v-if="selectedProduct && selectedModel && recommendedFirmwareFilename">: <a target="_blank" :href="`https://github.com/markqvist/RNode_Firmware/releases/latest/download/${recommendedFirmwareFilename}`" class="text-blue-500 hover:underline">{{ recommendedFirmwareFilename }}</a></span>
</div>
<div class="space-x-1">
<a target="_blank" href="https://github.com/markqvist/RNode_Firmware/releases" class="text-blue-500 hover:underline">Official Firmware</a>
@ -312,6 +312,48 @@
</div>
<div class="border bg-gray-50 rounded shadow">
<div class="border-b px-2 py-1">
Configure Display (optional)
</div>
<div class="p-3 space-y-2">
<div class="flex space-x-1">
<div class="my-auto">Rotation</div>
<button @click="setDisplayRotation(0)" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
0
</button>
<button @click="setDisplayRotation(1)" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
1
</button>
<button @click="setDisplayRotation(2)" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
2
</button>
<button @click="setDisplayRotation(3)" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
3
</button>
</div>
<div class="flex space-x-1">
<div class="my-auto">Reconditioning</div>
<button @click="startDisplayReconditioning" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
Start
</button>
<button @click="reboot" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
Stop
</button>
</div>
</div>
<div class="border-t px-2 py-1 text-sm">
<div>Setting display rotation requires firmware v1.80+</div>
</div>
</div>
</div>
<!-- setup web-serial-polyfill -->
@ -334,6 +376,8 @@
data() {
return {
rnode: null,
isFlashing: false,
flashingProgress: 0,
@ -397,6 +441,22 @@
},
},
},
{
name: "Heltec T114",
id: ROM.PRODUCT_HELTEC_T114,
platform: ROM.PLATFORM_NRF52,
models: [
{
id: ROM.MODEL_C6,
name: "470-510 MHz (HT-n5262-LF)",
},
{
id: ROM.MODEL_C7,
name: "863-928 MHz (HT-n5262-HF)",
},
],
firmware_filename: "rnode_firmware_heltec_t114.zip",
},
{
name: "LilyGO LoRa32 v1.0",
id: ROM.PRODUCT_T32_10,
@ -587,6 +647,21 @@
},
},
},
{
id: ROM.MODEL_AC,
name: "2.4 GHz (with SX1280 chip)",
firmware_filename: "rnode_firmware_t3s3_sx1280_pa.zip",
flash_config: {
flash_size: "4MB",
flash_files: {
"0xe000": "rnode_firmware_t3s3_sx1280_pa.boot_app0",
"0x0": "rnode_firmware_t3s3_sx1280_pa.bootloader",
"0x10000": "rnode_firmware_t3s3_sx1280_pa.bin",
"0x210000": "console_image.bin",
"0x8000": "rnode_firmware_t3s3_sx1280_pa.partitions",
},
},
},
],
},
{
@ -714,11 +789,11 @@
platform: ROM.PLATFORM_NRF52,
models: [
{
id: ROM.MODEL_T4,
id: ROM.MODEL_16,
name: "433 MHz",
},
{
id: ROM.MODEL_T9,
id: ROM.MODEL_17,
name: "868 MHz / 915 MHz / 923 MHz",
},
],
@ -858,11 +933,37 @@
return null;
}
// close any existing rnode connection
if(this.rnode){
await this.rnode.close();
this.rnode = null;
}
// ask user to select device
return await navigator.serial.requestPort({
filters: [],
});
},
async askForRNode() {
// ask for serial port
const serialPort = await this.askForSerialPort();
if(!serialPort){
return false;
}
// check if device is an rnode
this.rnode = await RNode.fromSerialPort(serialPort);
const isRNode = await this.rnode.detect();
if(!isRNode){
await this.rnode.close();
alert("Selected device is not an RNode!");
return false;
}
return this.rnode;
},
async enterDfuMode() {
@ -1069,17 +1170,9 @@
},
async detect() {
// 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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1122,17 +1215,9 @@
},
async reboot() {
// 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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1210,17 +1295,9 @@
},
async readDisplay() {
// 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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1236,17 +1313,9 @@
},
async dumpEeprom() {
// 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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1264,22 +1333,15 @@
},
async wipeEeprom() {
// ask for serial port
const serialPort = await this.askForSerialPort();
if(!serialPort){
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
// ask user to confirm
if(!confirm("Are you sure you want to wipe the eeprom on this device? This will take about 30 seconds. An alert will show when the eeprom wipe has finished.")){
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!");
await rnode.close();
return;
}
@ -1298,18 +1360,9 @@
},
async provision() {
// 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!");
await rnode.close();
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1489,17 +1542,9 @@
},
async setFirmwareHash() {
// 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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1546,17 +1591,9 @@
},
async enableTncMode() {
// 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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1602,17 +1639,9 @@
},
async disableTncMode() {
// 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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1643,17 +1672,9 @@
},
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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1671,26 +1692,18 @@
await rnode.enableBluetooth();
console.log("enabling bluetooth: done");
await Utils.sleepMillis(1000);
alert("Bluetooth has been enabled!");
// done
await Utils.sleepMillis(1000);
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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1707,27 +1720,18 @@
console.log("disabling bluetooth");
await rnode.disableBluetooth();
console.log("disabling bluetooth: done");
await Utils.sleepMillis(1000);
alert("Bluetooth has been disabled!");
// done
await Utils.sleepMillis(1000);
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!");
// ask for rnode
const rnode = await this.askForRNode();
if(!rnode){
return;
}
@ -1743,13 +1747,72 @@
// start bluetooth pairing
try {
console.log("start bluetooth pairing");
const pin = await rnode.startBluetoothPairing();
await rnode.startBluetoothPairing(async (pin) => {
alert("Bluetooth Pairing Pin: " + pin);
await rnode.close();
});
console.log("start bluetooth pairing: done");
} catch(error) {
alert(error);
}
alert("RNode should now be in Bluetooth Pairing mode. A pin will be shown on the screen when you pair with it from Android bluetooth settings.");
// tell user device is in pairing mode, and how to pair
alert([
"- RNode is in Bluetooth Pairing Mode for 30 seconds.",
"- Close this alert before performing the next steps.",
"- Open bluetooth settings on your Android device.",
"- Click pair on the RNode device that shows up.",
"- Bluetooth pin will shown on your RNode screen and on this page.",
].join("\n"));
},
async setDisplayRotation(rotation) {
// ask for rnode
const rnode = await this.askForRNode();
if(!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;
}
// configure
console.log("setting display rotation");
await rnode.setDisplayRotation(rotation);
console.log("setting display rotation: done");
// done
await rnode.close();
},
async startDisplayReconditioning() {
// ask for rnode
const rnode = await this.askForRNode();
if(!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;
}
// configure
console.log("starting display reconditioning");
await rnode.startDisplayReconditioning();
console.log("starting display reconditioning: done");
// done
await rnode.close();

View file

@ -79,6 +79,8 @@ class RNode {
ROM_UNLOCK_BYTE = 0xF8;
CMD_HASHES = 0x60;
CMD_FW_UPD = 0x61;
CMD_DISP_ROT = 0x67;
CMD_DISP_RCND = 0x68;
CMD_BT_CTRL = 0x46;
CMD_BT_PIN = 0x62;
@ -121,8 +123,10 @@ class RNode {
constructor(serialPort) {
this.serialPort = serialPort;
this.readable = serialPort.readable;
this.reader = serialPort.readable.getReader();
this.writable = serialPort.writable;
this.callbacks = {};
this.readLoop();
}
static async fromSerialPort(serialPort) {
@ -137,11 +141,21 @@ class RNode {
}
async close() {
// release reader lock
try {
this.reader.releaseLock();
} catch(e) {
//console.log("failed to release lock on serial port readable, ignoring...", e);
}
// close serial port
try {
await this.serialPort.close();
} catch(e) {
console.log("failed to close serial port, ignoring...", e);
//console.log("failed to close serial port, ignoring...", e);
}
}
async write(bytes) {
@ -153,79 +167,100 @@ class RNode {
}
}
async readFromSerialPort(timeoutMillis) {
return new Promise(async (resolve, reject) => {
async readLoop() {
try {
let buffer = [];
let inFrame = false;
while(true){
// create reader
const reader = this.readable.getReader();
// read kiss frames until reader indicates it's done
const { value, done } = await this.reader.read();
if(done){
break;
}
// timeout after provided millis
if(timeoutMillis != null){
setTimeout(() => {
reader.releaseLock();
reject("timeout");
}, timeoutMillis);
}
// 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
// read kiss frames
for(const byte of value){
if(byte === this.KISS_FEND){
if(inFrame){
// End of frame
const decodedFrame = this.decodeKissFrame(buffer);
if(decodedFrame){
this.onCommandReceived(decodedFrame);
} else {
console.warn("Invalid frame ignored.");
}
buffer = [];
}
inFrame = !inFrame;
} else if(inFrame) {
buffer.push(byte);
}
}
} catch (error) {
console.error('Error reading from serial port: ', error);
} finally {
reader.releaseLock();
}
} catch(error) {
// ignore error if reader was released
if(error instanceof TypeError){
return;
}
});
console.error('Error reading from serial port: ', error);
} finally {
this.reader.releaseLock();
}
}
handleKISSFrame(frame) {
onCommandReceived(data) {
try {
let data = [];
// get received command and bytes from data
const [ command, ...bytes ] = data;
console.log("onCommandReceived", "0x" + command.toString(16), bytes);
// find callback for received command
const callback = this.callbacks[command];
if(!callback){
return;
}
// fire callback
callback(bytes);
// forget callback
delete this.callbacks[command];
} catch(e) {
console.log("failed to handle received command", data, e);
}
}
decodeKissFrame(frame) {
const data = [];
let escaping = false;
// Skip the initial 0xC0 and process the rest
for(let i = 1; i < frame.length; i++){
let byte = frame[i];
if (escaping) {
if (byte === this.KISS_TFEND) {
for(const byte of frame){
if(escaping){
if(byte === this.KISS_TFEND){
data.push(this.KISS_FEND);
} else if (byte === this.KISS_TFESC) {
} else if(byte === this.KISS_TFESC) {
data.push(this.KISS_FESC);
} else {
return null; // Invalid escape sequence
}
escaping = false;
} else if(byte === this.KISS_FESC) {
escaping = true;
} else {
if (byte === this.KISS_FESC) {
escaping = true;
} else if (byte === this.KISS_FEND) {
// Ignore the end frame delimiter
break;
} else {
data.push(byte);
}
data.push(byte);
}
}
//console.log('Received KISS frame data:', new Uint8Array(data));
return data;
// return null if incomplete escape at end
return escaping ? null : data;
}
@ -248,6 +283,28 @@ class RNode {
await this.write(this.createKissFrame(data));
}
// sends a command to the rnode, and resolves the promise with the result
async sendCommand(command, data) {
return new Promise(async (resolve, reject) => {
try {
// listen for response
this.callbacks[command] = (response) => {
resolve(response);
};
// send command
await this.sendKissCommand([
command,
...data,
]);
} catch(e) {
reject(e);
}
});
}
async reset() {
await this.sendKissCommand([
this.CMD_RESET,
@ -256,30 +313,42 @@ class RNode {
}
async detect() {
return new Promise(async (resolve) => {
try {
// ask if device is rnode
await this.sendKissCommand([
this.CMD_DETECT,
this.DETECT_REQ,
]);
// timeout after provided millis
const timeout = setTimeout(() => {
resolve(false);
}, 2000);
// read response from device
const [ command, responseByte ] = await this.readFromSerialPort();
// detect rnode
const response = await this.sendCommand(this.CMD_DETECT, [
this.DETECT_REQ,
]);
// device is an rnode if response is as expected
return command === this.CMD_DETECT && responseByte === this.DETECT_RESP;
// we no longer want to timeout
clearTimeout(timeout);
// device is an rnode if response is as expected
const [ responseByte ] = response;
const isRnode = responseByte === this.DETECT_RESP;
resolve(isRnode);
} catch(e) {
resolve(false);
}
});
}
async getFirmwareVersion() {
await this.sendKissCommand([
this.CMD_FW_VERSION,
const response = await this.sendCommand(this.CMD_FW_VERSION, [
0x00,
]);
// read response from device
var [ command, majorVersion, minorVersion ] = await this.readFromSerialPort();
var [ majorVersion, minorVersion ] = response;
if(minorVersion.length === 1){
minorVersion = "0" + minorVersion;
}
@ -291,99 +360,91 @@ class RNode {
async getPlatform() {
await this.sendKissCommand([
this.CMD_PLATFORM,
const response = await this.sendCommand(this.CMD_PLATFORM, [
0x00,
]);
// read response from device
const [ command, platformByte ] = await this.readFromSerialPort();
const [ platformByte ] = response;
return platformByte;
}
async getMcu() {
await this.sendKissCommand([
this.CMD_MCU,
const response = await this.sendCommand(this.CMD_MCU, [
0x00,
]);
// read response from device
const [ command, mcuByte ] = await this.readFromSerialPort();
const [ mcuByte ] = response;
return mcuByte;
}
async getBoard() {
await this.sendKissCommand([
this.CMD_BOARD,
const response = await this.sendCommand(this.CMD_BOARD, [
0x00,
]);
// read response from device
const [ command, boardByte ] = await this.readFromSerialPort();
const [ boardByte ] = response;
return boardByte;
}
async getDeviceHash() {
await this.sendKissCommand([
this.CMD_DEV_HASH,
const response = await this.sendCommand(this.CMD_DEV_HASH, [
0x01, // anything != 0x00
]);
// read response from device
const [ command, ...deviceHash ] = await this.readFromSerialPort();
const [ ...deviceHash ] = response;
return deviceHash;
}
async getTargetFirmwareHash() {
await this.sendKissCommand([
this.CMD_HASHES,
const response = await this.sendCommand(this.CMD_HASHES, [
this.HASH_TYPE_TARGET_FIRMWARE,
]);
// read response from device
const [ command, hashType, ...targetFirmwareHash ] = await this.readFromSerialPort();
const [ hashType, ...targetFirmwareHash ] = response;
return targetFirmwareHash;
}
async getFirmwareHash() {
await this.sendKissCommand([
this.CMD_HASHES,
const response = await this.sendCommand(this.CMD_HASHES, [
this.HASH_TYPE_FIRMWARE,
]);
// read response from device
const [ command, hashType, ...firmwareHash ] = await this.readFromSerialPort();
const [ hashType, ...firmwareHash ] = response;
return firmwareHash;
}
async getRom() {
await this.sendKissCommand([
this.CMD_ROM_READ,
const response = await this.sendCommand(this.CMD_ROM_READ, [
0x00,
]);
// read response from device
const [ command, ...eepromBytes ] = await this.readFromSerialPort();
const [ ...eepromBytes ] = response;
return eepromBytes;
}
async getFrequency() {
await this.sendKissCommand([
this.CMD_FREQUENCY,
const response = await this.sendCommand(this.CMD_FREQUENCY, [
// request frequency by sending zero as 4 bytes
0x00,
0x00,
@ -392,7 +453,7 @@ class RNode {
]);
// read response from device
const [ command, ...frequencyBytes ] = await this.readFromSerialPort();
const [ ...frequencyBytes ] = response;
// convert 4 bytes to 32bit integer representing frequency in hertz
const frequencyInHz = frequencyBytes[0] << 24 | frequencyBytes[1] << 16 | frequencyBytes[2] << 8 | frequencyBytes[3];
@ -402,8 +463,7 @@ class RNode {
async getBandwidth() {
await this.sendKissCommand([
this.CMD_BANDWIDTH,
const response = await this.sendCommand(this.CMD_BANDWIDTH, [
// request bandwidth by sending zero as 4 bytes
0x00,
0x00,
@ -412,7 +472,7 @@ class RNode {
]);
// read response from device
const [ command, ...bandwidthBytes ] = await this.readFromSerialPort();
const [ ...bandwidthBytes ] = response;
// convert 4 bytes to 32bit integer representing bandwidth in hertz
const bandwidthInHz = bandwidthBytes[0] << 24 | bandwidthBytes[1] << 16 | bandwidthBytes[2] << 8 | bandwidthBytes[3];
@ -422,69 +482,60 @@ class RNode {
async getTxPower() {
await this.sendKissCommand([
this.CMD_TXPOWER,
const response = await this.sendCommand(this.CMD_TXPOWER, [
0xFF, // request tx power
]);
// read response from device
const [ command, txPower ] = await this.readFromSerialPort();
const [ txPower ] = response;
return txPower;
}
async getSpreadingFactor() {
await this.sendKissCommand([
this.CMD_SF,
const response = await this.sendCommand(this.CMD_SF, [
0xFF, // request spreading factor
]);
// read response from device
const [ command, spreadingFactor ] = await this.readFromSerialPort();
const [ spreadingFactor ] = response;
return spreadingFactor;
}
async getCodingRate() {
await this.sendKissCommand([
this.CMD_CR,
const response = await this.sendCommand(this.CMD_CR, [
0xFF, // request coding rate
]);
// read response from device
const [ command, codingRate ] = await this.readFromSerialPort();
const [ codingRate ] = response;
return codingRate;
}
async getRadioState() {
await this.sendKissCommand([
this.CMD_RADIO_STATE,
const response = await this.sendCommand(this.CMD_RADIO_STATE, [
0xFF, // request radio state
]);
// read response from device
const [ command, radioState ] = await this.readFromSerialPort();
const [ radioState ] = response;
return radioState;
}
async getRxStat() {
await this.sendKissCommand([
this.CMD_STAT_RX,
const response = await this.sendCommand(this.CMD_STAT_RX, [
0x00,
]);
// read response from device
const [ command, ...statBytes ] = await this.readFromSerialPort();
const [ ...statBytes ] = response;
// convert 4 bytes to 32bit integer
const stat = statBytes[0] << 24 | statBytes[1] << 16 | statBytes[2] << 8 | statBytes[3];
@ -494,13 +545,12 @@ class RNode {
async getTxStat() {
await this.sendKissCommand([
this.CMD_STAT_TX,
const response = await this.sendCommand(this.CMD_STAT_TX, [
0x00,
]);
// read response from device
const [ command, ...statBytes ] = await this.readFromSerialPort();
const [ ...statBytes ] = response;
// convert 4 bytes to 32bit integer
const stat = statBytes[0] << 24 | statBytes[1] << 16 | statBytes[2] << 8 | statBytes[3];
@ -510,14 +560,12 @@ class RNode {
async getRssiStat() {
await this.sendKissCommand([
this.CMD_STAT_RSSI,
const response = await this.sendCommand(this.CMD_STAT_RSSI, [
0x00,
]);
// read response from device
const [ command, rssi ] = await this.readFromSerialPort();
const [ rssi ] = response;
return rssi;
}
@ -536,7 +584,23 @@ class RNode {
]);
}
async startBluetoothPairing() {
async startBluetoothPairing(pinCallback) {
// listen for bluetooth pin
// pin will be available once the user has initiated pairing from an Android device
this.callbacks[this.CMD_BT_PIN] = (response) => {
// read response from device
const [ ...pinBytes ] = response;
// convert 4 bytes to 32bit integer
const pin = pinBytes[0] << 24 | pinBytes[1] << 16 | pinBytes[2] << 8 | pinBytes[3];
// tell user what the bluetooth pin is
console.log("Bluetooth Pairing Pin: " + pin);
pinCallback(pin);
};
// enable pairing
await this.sendKissCommand([
@ -544,43 +608,16 @@ class RNode {
0x02, // enable pairing
]);
// todo: listen for packets, pin will be available once user has initiated pairing from Android device
// // 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 readDisplay() {
await this.sendKissCommand([
this.CMD_DISP_READ,
const response = await this.sendCommand(this.CMD_DISP_READ, [
0x01,
]);
// read response from device
const [ command, ...displayBuffer ] = await this.readFromSerialPort();
const [ ...displayBuffer ] = response;
return displayBuffer;
}
@ -715,6 +752,20 @@ class RNode {
return new ROM(rom);
}
async setDisplayRotation(rotation) {
await this.sendKissCommand([
this.CMD_DISP_ROT,
rotation & 0xFF,
]);
}
async startDisplayReconditioning() {
await this.sendKissCommand([
this.CMD_DISP_RCND,
0x01,
]);
}
}
class ROM {
@ -743,6 +794,7 @@ class ROM {
static MODEL_A7 = 0xA7
static MODEL_A5 = 0xA5;
static MODEL_AA = 0xAA;
static MODEL_AC = 0xAC;
static PRODUCT_T32_10 = 0xB2
static MODEL_BA = 0xBA
@ -766,6 +818,10 @@ class ROM {
static MODEL_C5 = 0xC5
static MODEL_CA = 0xCA
static PRODUCT_HELTEC_T114 = 0xC2
static MODEL_C6 = 0xC6
static MODEL_C7 = 0xC7
static PRODUCT_TBEAM = 0xE0
static MODEL_E4 = 0xE4
static MODEL_E9 = 0xE9
@ -781,8 +837,8 @@ class ROM {
static MODEL_D9 = 0xD9;
static PRODUCT_TECHO = 0x15;
static MODEL_T4 = 0x16;
static MODEL_T9 = 0x17;
static MODEL_16 = 0x16;
static MODEL_17 = 0x17;
static PRODUCT_HMBRW = 0xF0
static MODEL_FF = 0xFF