diff --git a/src/sender.ts b/src/sender.ts index 8161451..d15114a 100644 --- a/src/sender.ts +++ b/src/sender.ts @@ -1,4 +1,5 @@ import { Socket, createSocket } from 'dgram'; +import { EventEmitter } from 'events'; import { multicastGroup } from './util'; import { Packet, Options } from './packet'; @@ -47,9 +48,21 @@ export namespace Sender { */ useUnicastDestination?: string; } + + export interface EventMap { + changedResendStatus: boolean; + error: Error; + } } -export class Sender { +export declare interface Sender { + on( + type: K, + listener: (event: Sender.EventMap[K]) => void, + ): this; +} + +export class Sender extends EventEmitter { private socket: Socket; private readonly port: Sender.Props['port']; @@ -66,6 +79,8 @@ export class Sender { private sequence = 0; + public resendStatus = false; + #loopId: NodeJS.Timeout | undefined; /** @@ -84,6 +99,7 @@ export class Sender { iface, useUnicastDestination, }: Sender.Props) { + super(); this.port = port; this.universe = universe; this.#destinationIp = useUnicastDestination || multicastGroup(universe); @@ -123,7 +139,23 @@ export class Sender { } private reSend() { - if (this.#latestPacketOptions) this.send(this.#latestPacketOptions); + if (this.#latestPacketOptions) { + this.send(this.#latestPacketOptions) + .then(() => { + this.updateResendStatus(true); + }) + .catch((err) => { + this.updateResendStatus(false); + this.emit('error', err); + }); + } + } + + private updateResendStatus(success: boolean) { + if (success !== this.resendStatus) { + this.resendStatus = success; + this.emit('changedResendStatus', success); + } } public close(): this { diff --git a/test/integration.test.ts b/test/integration.test.ts index 1f29ab1..be41510 100644 --- a/test/integration.test.ts +++ b/test/integration.test.ts @@ -48,6 +48,9 @@ describe('Receiver & Sender (integration test)', () => { try { const received: Packet[] = []; const errors: Error[] = []; + const receivedEvents: boolean[] = []; + Tx.on('changedResendStatus', (event) => receivedEvents.push(event)); + Tx.on('error', (ex) => errors.push(ex)); Rx.on('packet', (packet) => received.push(packet)); collectErrors(Rx, errors); @@ -58,6 +61,8 @@ describe('Receiver & Sender (integration test)', () => { assert.strictEqual(errors.length, 0); assert.strictEqual(received.length, 4); // send at 0s, 1s, 2s, 3s. Then at 3.5s we stop + assert.strictEqual(receivedEvents.length, 1); + assert.deepStrictEqual(receivedEvents[0], true); assert.deepStrictEqual(received[0]!.payload, { 1: 100 }); assert.deepStrictEqual(received[1]!.payload, { 1: 100 }); assert.deepStrictEqual(received[2]!.payload, { 1: 100 });