From 2659b824ede7718df24564f6dd0c74004c4a97b6 Mon Sep 17 00:00:00 2001 From: MultiMote <contact@mmote.ru> Date: Wed, 8 Jan 2025 11:56:25 +0300 Subject: [PATCH] Move raw packet processing to the base class --- src/client/abstract_client.ts | 38 +++++++++++++++++++++++++++++ src/client/bluetooth_impl.ts | 18 +++----------- src/client/capacitor_ble_impl.ts | 42 +++----------------------------- src/client/serial_impl.ts | 26 ++------------------ 4 files changed, 47 insertions(+), 77 deletions(-) diff --git a/src/client/abstract_client.ts b/src/client/abstract_client.ts index efa748f..5bb8b9e 100644 --- a/src/client/abstract_client.ts +++ b/src/client/abstract_client.ts @@ -19,6 +19,7 @@ import { HeartbeatEvent, HeartbeatFailedEvent, PacketReceivedEvent, + RawPacketReceivedEvent, } from "../events"; import { findPrintTask, PrintTaskName } from "../print_tasks"; import { Utils, Validators } from "../utils"; @@ -65,6 +66,7 @@ export abstract class NiimbotAbstractClient extends EventEmitter<ClientEventMap> private heartbeatIntervalMs: number = 2_000; protected mutex: Mutex = new Mutex(); protected debug: boolean = false; + private packetBuf = new Uint8Array(); /** @see https://github.com/MultiMote/niimblue/issues/5 */ protected packetIntervalMs: number = 10; @@ -145,6 +147,42 @@ export abstract class NiimbotAbstractClient extends EventEmitter<ClientEventMap> }); } + /** + * Convert raw bytes to packet objects and fire events. Defragmentation included. + * @param data Bytes to process. + */ + protected processRawPacket(data: DataView | Uint8Array) { + if (data.byteLength === 0) { + return; + } + + console.log("processRawPacket") + + if (data instanceof DataView) { + data = new Uint8Array(data.buffer); + } + + this.packetBuf = Utils.u8ArrayAppend(this.packetBuf, data); + + try { + const packets: NiimbotPacket[] = NiimbotPacket.fromBytesMultiPacket(this.packetBuf); + + if (packets.length > 0) { + this.emit("rawpacketreceived", new RawPacketReceivedEvent(this.packetBuf)); + + packets.forEach((p) => { + this.emit("packetreceived", new PacketReceivedEvent(p)); + }); + + this.packetBuf = new Uint8Array(); + } + } catch (_e) { + if (this.debug) { + console.info(`Incomplete packet, ignoring:${Utils.bufToHex(this.packetBuf)}`); + } + } + } + /** * Send raw bytes to the printer port. * diff --git a/src/client/bluetooth_impl.ts b/src/client/bluetooth_impl.ts index a32f37f..cbd3151 100644 --- a/src/client/bluetooth_impl.ts +++ b/src/client/bluetooth_impl.ts @@ -1,7 +1,6 @@ -import { ConnectEvent, DisconnectEvent, PacketReceivedEvent, RawPacketReceivedEvent, RawPacketSentEvent } from "../events"; +import { ConnectEvent, DisconnectEvent, RawPacketSentEvent } from "../events"; import { ConnectionInfo, NiimbotAbstractClient } from "."; -import { NiimbotPacket } from "../packets/packet"; -import { ConnectResult, ResponseCommandId } from "../packets"; +import { ConnectResult } from "../packets"; import { Utils } from "../utils"; class BleConfiguration { @@ -65,18 +64,7 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient { channel.addEventListener("characteristicvaluechanged", (event: Event) => { const target = event.target as BluetoothRemoteGATTCharacteristic; - - const data = new Uint8Array(target.value!.buffer); - - this.emit("rawpacketreceived", new RawPacketReceivedEvent(data)); - - const packet = NiimbotPacket.fromBytes(data); - - this.emit("packetreceived", new PacketReceivedEvent(packet)); - - if (!(packet.command in ResponseCommandId)) { - console.warn(`Unknown response command: 0x${Utils.numberToHex(packet.command)}`); - } + this.processRawPacket(target.value!); }); await channel.startNotifications(); diff --git a/src/client/capacitor_ble_impl.ts b/src/client/capacitor_ble_impl.ts index cad8077..ffa25c4 100644 --- a/src/client/capacitor_ble_impl.ts +++ b/src/client/capacitor_ble_impl.ts @@ -1,19 +1,12 @@ -import { - ConnectEvent, - DisconnectEvent, - PacketReceivedEvent, - RawPacketReceivedEvent, - RawPacketSentEvent, -} from "../events"; +import { ConnectEvent, DisconnectEvent, RawPacketSentEvent } from "../events"; import { ConnectionInfo, NiimbotAbstractClient } from "."; -import { NiimbotPacket } from "../packets/packet"; import { ConnectResult } from "../packets"; import { Utils } from "../utils"; import { BleCharacteristic, BleClient, BleDevice, BleService } from "@capacitor-community/bluetooth-le"; /** - * @category Client - */ + * @category Client + */ export interface NiimbotCapacitorBleClientConnectOptions { /** * Skip device picker dialog and connect to given device ID. @@ -34,7 +27,6 @@ export class NiimbotCapacitorBleClient extends NiimbotAbstractClient { private deviceId?: string; private serviceUUID?: string; private characteristicUUID?: string; - private packetBuf = new Uint8Array(); public async connect(options?: NiimbotCapacitorBleClientConnectOptions): Promise<ConnectionInfo> { await this.disconnect(); @@ -73,7 +65,7 @@ export class NiimbotCapacitorBleClient extends NiimbotAbstractClient { } await BleClient.startNotifications(this.deviceId, this.serviceUUID, this.characteristicUUID, (value: DataView) => { - this.onBlePacketReceived(value); + this.processRawPacket(value); }); try { @@ -116,32 +108,6 @@ export class NiimbotCapacitorBleClient extends NiimbotAbstractClient { throw new Error("Unable to find suitable channel characteristic"); } - private onBlePacketReceived(dv: DataView) { - if (dv.byteLength === 0) { - return; - } - - this.packetBuf = Utils.u8ArrayAppend(this.packetBuf, new Uint8Array(dv.buffer)); - - try { - const packets: NiimbotPacket[] = NiimbotPacket.fromBytesMultiPacket(this.packetBuf); - - if (packets.length > 0) { - this.emit("rawpacketreceived", new RawPacketReceivedEvent(this.packetBuf)); - - packets.forEach((p) => { - this.emit("packetreceived", new PacketReceivedEvent(p)); - }); - - this.packetBuf = new Uint8Array(); - } - } catch (_e) { - if (this.debug) { - console.info(`Incomplete packet, ignoring:${Utils.bufToHex(this.packetBuf)}`); - } - } - } - private onBleDisconnect() { this.deviceId = undefined; this.serviceUUID = undefined; diff --git a/src/client/serial_impl.ts b/src/client/serial_impl.ts index 812e042..63bf7d7 100644 --- a/src/client/serial_impl.ts +++ b/src/client/serial_impl.ts @@ -1,6 +1,5 @@ -import { ConnectEvent, DisconnectEvent, PacketReceivedEvent, RawPacketReceivedEvent, RawPacketSentEvent } from "../events"; +import { ConnectEvent, DisconnectEvent, RawPacketSentEvent } from "../events"; import { ConnectionInfo, NiimbotAbstractClient } from "."; -import { NiimbotPacket } from "../packets/packet"; import { ConnectResult } from "../packets"; import { Utils } from "../utils"; @@ -63,8 +62,6 @@ export class NiimbotSerialClient extends NiimbotAbstractClient { } private async waitSerialData() { - let buf = new Uint8Array(); - while (true) { try { const result = await this.reader!.read(); @@ -72,8 +69,7 @@ export class NiimbotSerialClient extends NiimbotAbstractClient { if (this.debug) { console.info(`<< serial chunk ${Utils.bufToHex(result.value)}`); } - - buf = Utils.u8ArrayAppend(buf, result.value); + this.processRawPacket(result.value); } if (result.done) { @@ -83,24 +79,6 @@ export class NiimbotSerialClient extends NiimbotAbstractClient { } catch (_e) { break; } - - try { - const packets: NiimbotPacket[] = NiimbotPacket.fromBytesMultiPacket(buf); - - if (packets.length > 0) { - this.emit("rawpacketreceived", new RawPacketReceivedEvent(buf)); - - packets.forEach((p) => { - this.emit("packetreceived", new PacketReceivedEvent(p)); - }); - - buf = new Uint8Array(); - } - } catch (_e) { - if (this.debug) { - console.info(`Incomplete packet, ignoring:${Utils.bufToHex(buf)}`); - } - } } }