Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 49 additions & 10 deletions src/js/protocols/CapacitorSerial.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ class CapacitorSerial extends EventTarget {
constructor() {
super();

if (!BetaflightSerial) {
this.pluginAvailable = !!BetaflightSerial;

if (!this.pluginAvailable) {
console.error(`${logHead} Native BetaflightSerial plugin is not available`);
return;
}

this.connected = false;
Expand All @@ -36,15 +37,15 @@ class CapacitorSerial extends EventTarget {
this.handleDeviceAttached = this.handleDeviceAttached.bind(this);
this.handleDeviceDetached = this.handleDeviceDetached.bind(this);

// Listen for data received from native plugin
BetaflightSerial.addListener("dataReceived", this.handleDataReceived);
// Listen for data received from native plugin and load devices if plugin is available
if (this.pluginAvailable) {
BetaflightSerial.addListener("dataReceived", this.handleDataReceived);
BetaflightSerial.addListener("deviceAttached", this.handleDeviceAttached);
BetaflightSerial.addListener("deviceDetached", this.handleDeviceDetached);

// Listen for device attach/detach events
BetaflightSerial.addListener("deviceAttached", this.handleDeviceAttached);
BetaflightSerial.addListener("deviceDetached", this.handleDeviceDetached);

// Load initial device list
this.loadDevices();
// Load initial device list
this.loadDevices();
}

console.log(`${logHead} CapacitorSerial initialized`);
}
Expand Down Expand Up @@ -125,6 +126,10 @@ class CapacitorSerial extends EventTarget {
}

async loadDevices() {
if (!this.pluginAvailable) {
return;
}

try {
const result = await BetaflightSerial.getDevices();
this.ports = result.devices.map((device) => this.createPort(device));
Expand All @@ -137,6 +142,10 @@ class CapacitorSerial extends EventTarget {

async requestPermissionDevice() {
let newPermissionPort = null;
if (!this.pluginAvailable) {
return null;
}

try {
console.log(`${logHead} Requesting USB permissions...`);
const userSelectedPort = await BetaflightSerial.requestPermission();
Expand All @@ -159,6 +168,10 @@ class CapacitorSerial extends EventTarget {
}

async connect(path, options) {
if (!this.pluginAvailable) {
return false;
}

const baudRate = options?.baudRate ?? 115200;
// Prevent double connections
if (this.connected) {
Expand Down Expand Up @@ -232,6 +245,10 @@ class CapacitorSerial extends EventTarget {
}

async disconnect() {
if (!this.pluginAvailable) {
return true;
}

if (!this.connected) {
return true;
}
Expand All @@ -255,6 +272,13 @@ class CapacitorSerial extends EventTarget {
}

async send(data, callback) {
if (!this.pluginAvailable) {
if (callback) {
callback({ bytesSent: 0 });
}
return { bytesSent: 0 };
}

if (!this.connected) {
console.error(`${logHead} Failed to send data, not connected`);
if (callback) {
Expand Down Expand Up @@ -295,6 +319,21 @@ class CapacitorSerial extends EventTarget {
return new Uint8Array(0);
}

// Strip 0x prefix
if (hexString.startsWith("0x") || hexString.startsWith("0X")) {
hexString = hexString.slice(2);
}

// Validate characters
if (!/^[0-9a-fA-F]+$/.test(hexString)) {
throw new Error(`Invalid hex string: contains non-hex characters`);
}

// Validate length
if (hexString.length % 2 !== 0) {
throw new Error(`Invalid hex string: odd length (${hexString.length})`);
}

const bytes = new Uint8Array(hexString.length / 2);
for (let i = 0; i < hexString.length; i += 2) {
bytes[i / 2] = Number.parseInt(hexString.substring(i, i + 2), 16);
Expand Down