diff --git a/README.md b/README.md index 27c665c..d4bb916 100644 --- a/README.md +++ b/README.md @@ -28,23 +28,23 @@ import { Utils, RequestCommandId, ResponseCommandId, NiimbotBluetoothClient, Ima const client = new NiimbotBluetoothClient(); -client.addEventListener("packetsent", (e) => { +client.on("packetsent", (e) => { console.log(`>> ${Utils.bufToHex(e.packet.toBytes())} (${RequestCommandId[e.packet.command]})`); }); -client.addEventListener("packetreceived", (e) => { +client.on("packetreceived", (e) => { console.log(`<< ${Utils.bufToHex(e.packet.toBytes())} (${ResponseCommandId[e.packet.command]})`); }); -client.addEventListener("connect", () => { +client.on("connect", () => { console.log("connected"); }); -client.addEventListener("disconnect", () => { +client.on("disconnect", () => { console.log("disconnected"); }); -client.addEventListener("printprogress", (e) => { +client.on("printprogress", (e) => { console.log(`Page ${e.page}/${e.pagesTotal}, Page print ${e.pagePrintProgress}%, Page feed ${e.pageFeedProgress}%`); }); diff --git a/package.json b/package.json index 4d3e25f..e36b8f6 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ }, "dependencies": { "async-mutex": "^0.5.0", - "typescript-event-target": "^1.1.1" + "eventemitter3": "^5.0.1" }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/src/client/bluetooth_impl.ts b/src/client/bluetooth_impl.ts index 45ef205..719cc1d 100644 --- a/src/client/bluetooth_impl.ts +++ b/src/client/bluetooth_impl.ts @@ -5,7 +5,7 @@ import { PacketReceivedEvent, RawPacketReceivedEvent, RawPacketSentEvent, -} from "./events"; +} from "../events"; import { ConnectionInfo, NiimbotAbstractClient } from "."; import { NiimbotPacket } from "../packets/packet"; import { ConnectResult, ResponseCommandId } from "../packets"; @@ -55,7 +55,7 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient { this.gattServer = undefined; this.channel = undefined; this.info = {}; - this.dispatchTypedEvent("disconnect", new DisconnectEvent()); + this.emit("disconnect", new DisconnectEvent()); device.removeEventListener("gattserverdisconnected", disconnectListener); }; @@ -72,8 +72,8 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient { const data = new Uint8Array(target.value!.buffer); const packet = NiimbotPacket.fromBytes(data); - this.dispatchTypedEvent("rawpacketreceived", new RawPacketReceivedEvent(data)); - this.dispatchTypedEvent("packetreceived", new PacketReceivedEvent(packet)); + this.emit("rawpacketreceived", new RawPacketReceivedEvent(data)); + this.emit("packetreceived", new PacketReceivedEvent(packet)); if (!(packet.command in ResponseCommandId)) { console.warn(`Unknown response command: 0x${Utils.numberToHex(packet.command)}`); @@ -98,7 +98,7 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient { result: this.info.connectResult ?? ConnectResult.FirmwareErrors, }; - this.dispatchTypedEvent("connect", new ConnectEvent(result)); + this.emit("connect", new ConnectEvent(result)); return result; } @@ -139,17 +139,17 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient { packet.validResponseIds.includes(evt.packet.command as ResponseCommandId) ) { clearTimeout(timeout); - this.removeEventListener("packetreceived", listener); + this.off("packetreceived", listener); resolve(evt.packet); } }; timeout = setTimeout(() => { - this.removeEventListener("packetreceived", listener); + this.off("packetreceived", listener); reject(new Error(`Timeout waiting response (waited for ${Utils.bufToHex(packet.validResponseIds, ", ")})`)); }, timeoutMs ?? 1000); - this.addEventListener("packetreceived", listener); + this.on("packetreceived", listener); }); }); } @@ -161,7 +161,7 @@ export class NiimbotBluetoothClient extends NiimbotAbstractClient { } await Utils.sleep(this.packetIntervalMs); await this.channel.writeValueWithoutResponse(data); - this.dispatchTypedEvent("rawpacketsent", new RawPacketSentEvent(data)); + this.emit("rawpacketsent", new RawPacketSentEvent(data)); }; if (force) { diff --git a/src/client/index.ts b/src/client/index.ts index 6a9b3ac..aa63927 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,4 +1,4 @@ -import { TypedEventTarget } from "typescript-event-target"; +import { EventEmitter } from "eventemitter3"; import { Abstraction, AutoShutdownTime, @@ -8,7 +8,7 @@ import { NiimbotPacket, } from "../packets"; import { PrinterModelMeta, getPrinterMetaById } from "../printer_models"; -import { ClientEventMap, PacketSentEvent, PrinterInfoFetchedEvent, HeartbeatEvent, HeartbeatFailedEvent } from "./events"; +import { ClientEventMap, PacketSentEvent, PrinterInfoFetchedEvent, HeartbeatEvent, HeartbeatFailedEvent } from "../events"; import { findPrintTask, PrintTaskName } from "../print_tasks"; export type ConnectionInfo = { @@ -29,7 +29,7 @@ export interface PrinterInfo { hardwareVersion?: string; } -export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEventMap> { +export abstract class NiimbotAbstractClient extends EventEmitter<ClientEventMap> { public readonly abstraction: Abstraction; protected info: PrinterInfo = {}; private heartbeatTimer?: NodeJS.Timeout; @@ -42,8 +42,8 @@ export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEvent constructor() { super(); this.abstraction = new Abstraction(this); - this.addEventListener("connect", () => this.startHeartbeat()) - this.addEventListener("disconnect", () => this.stopHeartbeat()) + this.on("connect", () => this.startHeartbeat()); + this.on("disconnect", () => this.stopHeartbeat()); } /** Connect to printer port */ @@ -70,7 +70,7 @@ export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEvent public async sendPacket(packet: NiimbotPacket, force?: boolean) { await this.sendRaw(packet.toBytes(), force); - this.dispatchTypedEvent("packetsent", new PacketSentEvent(packet)); + this.emit("packetsent", new PacketSentEvent(packet)); } /** Send "connect" packet and fetch the protocol version */ @@ -98,7 +98,7 @@ export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEvent this.info.hardwareVersion = await this.abstraction.getHardwareVersion().catch(console.error) ?? undefined; this.info.softwareVersion = await this.abstraction.getSoftwareVersion().catch(console.error) ?? undefined; - this.dispatchTypedEvent("printerinfofetched", new PrinterInfoFetchedEvent(this.info)); + this.emit("printerinfofetched", new PrinterInfoFetchedEvent(this.info)); return this.info; } @@ -115,7 +115,6 @@ export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEvent this.heartbeatIntervalMs = intervalMs; } - /** * Starts the heartbeat timer, "heartbeat" is emitted after packet received. * @@ -131,12 +130,12 @@ export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEvent .heartbeat() .then((data) => { this.heartbeatFails = 0; - this.dispatchTypedEvent("heartbeat", new HeartbeatEvent(data)); + this.emit("heartbeat", new HeartbeatEvent(data)); }) .catch((e) => { console.error(e); this.heartbeatFails++; - this.dispatchTypedEvent("heartbeatfailed", new HeartbeatFailedEvent(this.heartbeatFails)); + this.emit("heartbeatfailed", new HeartbeatFailedEvent(this.heartbeatFails)); }); }, this.heartbeatIntervalMs); } @@ -174,6 +173,5 @@ export abstract class NiimbotAbstractClient extends TypedEventTarget<ClientEvent } } -export * from "./events"; export * from "./bluetooth_impl"; export * from "./serial_impl"; diff --git a/src/client/serial_impl.ts b/src/client/serial_impl.ts index 6beaed7..e5c846f 100644 --- a/src/client/serial_impl.ts +++ b/src/client/serial_impl.ts @@ -5,7 +5,7 @@ import { PacketReceivedEvent, RawPacketReceivedEvent, RawPacketSentEvent, -} from "./events"; +} from "../events"; import { ConnectionInfo, NiimbotAbstractClient } from "."; import { NiimbotPacket } from "../packets/packet"; import { ConnectResult, ResponseCommandId } from "../packets"; @@ -25,7 +25,7 @@ export class NiimbotSerialClient extends NiimbotAbstractClient { _port.addEventListener("disconnect", () => { this.port = undefined; - this.dispatchTypedEvent("disconnect", new DisconnectEvent()); + this.emit("disconnect", new DisconnectEvent()); }); await _port.open({ baudRate: 115200 }); @@ -62,7 +62,7 @@ export class NiimbotSerialClient extends NiimbotAbstractClient { result: this.info.connectResult ?? ConnectResult.FirmwareErrors, }; - this.dispatchTypedEvent("connect", new ConnectEvent(result)); + this.emit("connect", new ConnectEvent(result)); return result; } @@ -93,10 +93,10 @@ export class NiimbotSerialClient extends NiimbotAbstractClient { const packets: NiimbotPacket[] = NiimbotPacket.fromBytesMultiPacket(buf); if (packets.length > 0) { - this.dispatchTypedEvent("rawpacketreceived", new RawPacketReceivedEvent(buf)); + this.emit("rawpacketreceived", new RawPacketReceivedEvent(buf)); packets.forEach((p) => { - this.dispatchTypedEvent("packetreceived", new PacketReceivedEvent(p)); + this.emit("packetreceived", new PacketReceivedEvent(p)); }); buf = new Uint8Array(); @@ -120,7 +120,7 @@ export class NiimbotSerialClient extends NiimbotAbstractClient { if (this.port !== undefined) { await this.port.close(); - this.dispatchTypedEvent("disconnect", new DisconnectEvent()); + this.emit("disconnect", new DisconnectEvent()); } this.port = undefined; @@ -152,17 +152,17 @@ export class NiimbotSerialClient extends NiimbotAbstractClient { packet.validResponseIds.includes(evt.packet.command as ResponseCommandId) ) { clearTimeout(timeout); - this.removeEventListener("packetreceived", listener); + this.off("packetreceived", listener); resolve(evt.packet); } }; timeout = setTimeout(() => { - this.removeEventListener("packetreceived", listener); + this.off("packetreceived", listener); reject(new Error(`Timeout waiting response (waited for ${Utils.bufToHex(packet.validResponseIds, ", ")})`)); }, timeoutMs ?? 1000); - this.addEventListener("packetreceived", listener); + this.on("packetreceived", listener); }); }); } @@ -174,7 +174,7 @@ export class NiimbotSerialClient extends NiimbotAbstractClient { } await Utils.sleep(this.packetIntervalMs); await this.writer.write(data); - this.dispatchTypedEvent("rawpacketsent", new RawPacketSentEvent(data)); + this.emit("rawpacketsent", new RawPacketSentEvent(data)); }; if (force) { diff --git a/src/client/events.ts b/src/events.ts similarity index 53% rename from src/client/events.ts rename to src/events.ts index 42316aa..2d8b80f 100644 --- a/src/client/events.ts +++ b/src/events.ts @@ -1,9 +1,16 @@ import { ConnectionInfo, PrinterInfo } from "."; -import { HeartbeatData } from "../packets/abstraction"; -import { NiimbotPacket } from "../packets/packet"; +import { HeartbeatData } from "./packets/abstraction"; +import { NiimbotPacket } from "./packets/packet"; +export class NiimbotEvent { + readonly type: string; -export class ConnectEvent extends Event { + constructor(type: string) { + this.type = type; + } +} + +export class ConnectEvent extends NiimbotEvent { info: ConnectionInfo; constructor(info: ConnectionInfo) { super("connect"); @@ -11,13 +18,13 @@ export class ConnectEvent extends Event { } } -export class DisconnectEvent extends Event { +export class DisconnectEvent extends NiimbotEvent { constructor() { super("disconnect"); } } -export class PacketReceivedEvent extends Event { +export class PacketReceivedEvent extends NiimbotEvent { packet: NiimbotPacket; constructor(packet: NiimbotPacket) { super("packetreceived"); @@ -25,7 +32,7 @@ export class PacketReceivedEvent extends Event { } } -export class PacketSentEvent extends Event { +export class PacketSentEvent extends NiimbotEvent { packet: NiimbotPacket; constructor(packet: NiimbotPacket) { super("packetsent"); @@ -33,7 +40,7 @@ export class PacketSentEvent extends Event { } } -export class RawPacketSentEvent extends Event { +export class RawPacketSentEvent extends NiimbotEvent { data: Uint8Array; constructor(data: Uint8Array) { super("rawpacketsent"); @@ -41,7 +48,7 @@ export class RawPacketSentEvent extends Event { } } -export class RawPacketReceivedEvent extends Event { +export class RawPacketReceivedEvent extends NiimbotEvent { data: Uint8Array; constructor(data: Uint8Array) { super("rawpacketreceived"); @@ -49,7 +56,7 @@ export class RawPacketReceivedEvent extends Event { } } -export class HeartbeatEvent extends Event { +export class HeartbeatEvent extends NiimbotEvent { data: HeartbeatData; constructor(data: HeartbeatData) { super("heartbeat"); @@ -57,7 +64,7 @@ export class HeartbeatEvent extends Event { } } -export class HeartbeatFailedEvent extends Event { +export class HeartbeatFailedEvent extends NiimbotEvent { failedAttempts: number; constructor(failedAttempts: number) { super("heartbeatfailed"); @@ -65,7 +72,7 @@ export class HeartbeatFailedEvent extends Event { } } -export class PrinterInfoFetchedEvent extends Event { +export class PrinterInfoFetchedEvent extends NiimbotEvent { info: PrinterInfo; constructor(info: PrinterInfo) { super("printerinfofetched"); @@ -73,7 +80,7 @@ export class PrinterInfoFetchedEvent extends Event { } } -export class PrintProgressEvent extends Event { +export class PrintProgressEvent extends NiimbotEvent { /** 0 – n */ page: number; @@ -92,15 +99,15 @@ export class PrintProgressEvent extends Event { } } -export interface ClientEventMap { - connect: ConnectEvent; - disconnect: DisconnectEvent; - rawpacketsent: RawPacketSentEvent; - rawpacketreceived: RawPacketReceivedEvent; - packetreceived: PacketReceivedEvent; - packetsent: PacketSentEvent; - heartbeat: HeartbeatEvent; - heartbeatfailed: HeartbeatFailedEvent; - printerinfofetched: PrinterInfoFetchedEvent; - printprogress: PrintProgressEvent; +export type ClientEventMap = { + connect: (event: ConnectEvent) => void; + disconnect: (event: DisconnectEvent) => void; + rawpacketsent: (event: RawPacketSentEvent) => void; + rawpacketreceived: (event: RawPacketReceivedEvent) => void; + packetreceived: (event: PacketReceivedEvent) => void; + packetsent: (event: PacketSentEvent) => void; + heartbeat: (event: HeartbeatEvent) => void; + heartbeatfailed: (event: HeartbeatFailedEvent) => void; + printerinfofetched: (event: PrinterInfoFetchedEvent) => void; + printprogress: (event: PrintProgressEvent) => void; } diff --git a/src/index.ts b/src/index.ts index 1769d2c..619dcf1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ export * from "./client"; export * from "./packets"; +export * from "./events"; export * from "./image_encoder"; export * from "./utils"; export * from "./printer_models"; diff --git a/src/packets/abstraction.ts b/src/packets/abstraction.ts index 84eadd3..60da90d 100644 --- a/src/packets/abstraction.ts +++ b/src/packets/abstraction.ts @@ -10,7 +10,8 @@ import { SoundSettingsItemType, SoundSettingsType, } from "."; -import { NiimbotAbstractClient, PacketReceivedEvent, PrintProgressEvent } from "../client"; +import { NiimbotAbstractClient } from "../client"; +import { PacketReceivedEvent, PrintProgressEvent } from "../events"; import { PrintTaskName, printTasks } from "../print_tasks"; import { AbstractPrintTask, PrintOptions } from "../print_tasks/AbstractPrintTask"; import { Validators, Utils } from "../utils"; @@ -365,17 +366,17 @@ export class Abstraction { Validators.u8ArrayLengthEquals(evt.packet.data, 2); const page = Utils.bytesToI16(evt.packet.data); - this.client.dispatchTypedEvent("printprogress", new PrintProgressEvent(page, pagesToPrint, 100, 100)); + this.client.emit("printprogress", new PrintProgressEvent(page, pagesToPrint, 100, 100)); clearTimeout(this.statusTimeoutTimer); this.statusTimeoutTimer = setTimeout(() => { - this.client.removeEventListener("packetreceived", listener); + this.client.off("packetreceived", listener); reject(new Error("Timeout waiting print status")); }, timeoutMs ?? 5_000); if (page === pagesToPrint) { clearTimeout(this.statusTimeoutTimer); - this.client.removeEventListener("packetreceived", listener); + this.client.off("packetreceived", listener); resolve(); } } @@ -383,12 +384,12 @@ export class Abstraction { clearTimeout(this.statusTimeoutTimer); this.statusTimeoutTimer = setTimeout(() => { - this.client.removeEventListener("packetreceived", listener); + this.client.off("packetreceived", listener); reject(new Error("Timeout waiting print status")); }, timeoutMs); - this.client.dispatchTypedEvent("printprogress", new PrintProgressEvent(1, pagesToPrint, 0, 0)); - this.client.addEventListener("packetreceived", listener); + this.client.emit("printprogress", new PrintProgressEvent(1, pagesToPrint, 0, 0)); + this.client.on("packetreceived", listener); }); } @@ -402,12 +403,12 @@ export class Abstraction { */ public async waitUntilPrintFinishedByStatusPoll(pagesToPrint: number, pollIntervalMs: number = 300): Promise<void> { return new Promise<void>((resolve, reject) => { - this.client.dispatchTypedEvent("printprogress", new PrintProgressEvent(1, pagesToPrint, 0, 0)); + this.client.emit("printprogress", new PrintProgressEvent(1, pagesToPrint, 0, 0)); this.statusPollTimer = setInterval(() => { this.getPrintStatus() .then((status: PrintStatus) => { - this.client.dispatchTypedEvent( + this.client.emit( "printprogress", new PrintProgressEvent(status.page, pagesToPrint, status.pagePrintProgress, status.pageFeedProgress) ); @@ -437,15 +438,15 @@ export class Abstraction { */ public async waitUntilPrintFinishedByPrintEndPoll(pagesToPrint: number, pollIntervalMs: number = 500): Promise<void> { return new Promise<void>((resolve, reject) => { - this.client.dispatchTypedEvent("printprogress", new PrintProgressEvent(1, pagesToPrint, 0, 0)); + this.client.emit("printprogress", new PrintProgressEvent(1, pagesToPrint, 0, 0)); this.statusPollTimer = setInterval(() => { this.printEnd() .then((printEndDone: boolean) => { if(!printEndDone) { - this.client.dispatchTypedEvent("printprogress", new PrintProgressEvent(1, pagesToPrint, 0, 0)); + this.client.emit("printprogress", new PrintProgressEvent(1, pagesToPrint, 0, 0)); } else { - this.client.dispatchTypedEvent("printprogress", new PrintProgressEvent(pagesToPrint, pagesToPrint, 100, 100)); + this.client.emit("printprogress", new PrintProgressEvent(pagesToPrint, pagesToPrint, 100, 100)); clearInterval(this.statusPollTimer); resolve(); } diff --git a/yarn.lock b/yarn.lock index ca7e47a..c653b1d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,16 +26,16 @@ async-mutex@^0.5.0: dependencies: tslib "^2.4.0" +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + tslib@^2.4.0: version "2.6.3" resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== -typescript-event-target@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/typescript-event-target/-/typescript-event-target-1.1.1.tgz" - integrity sha512-dFSOFBKV6uwaloBCCUhxlD3Pr/P1a/tJdcmPrTXCHlEFD3faj0mztjcGn6VBAhQ0/Bdy8K3VWrrqwbt/ffsYsg== - typescript@^5.4.5: version "5.4.5" resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz"