UNPKG

knx-listener

Version:

A thin client that creates a tunnel to knx gateway to listen to telegrams within knx net

101 lines (99 loc) 2.86 kB
import { createSocket, Socket, RemoteInfo, } from 'dgram'; import { EventEmitter, } from 'events'; import { Subscriber, } from '../interfaces'; /** * Simple promisable udp socket */ export class AsyncSocket { private socket: Socket; protected events: EventEmitter = new EventEmitter(); isConnected() { return this.socket ? true : false; } connect(port: number = 0 /* OS assigned port */) { return new Promise<RemoteInfo>((resolve, reject) => { if (this.isConnected()) { resolve(this.socket.address()); } else { this.socket = createSocket('udp4') .on('message', (raw: Buffer, remote) => { this.events.emit('raw', raw, remote); }) .once('close', () => { this.socket = undefined; // emit disconnect event this.events.emit('disconnect'); // and remove all listeners to prevent any memory leak this.events.removeAllListeners(); }) .once('error', (err) => { reject(err); }) .once('listening', () => { resolve(this.socket.address()); }); this.socket.bind(port); } }); } complete<T>(cb?: () => T) { return new Promise<T>((resolve) => { if (this.isConnected()) { this.socket.once('close', () => { resolve(typeof cb === 'function' ? cb() : undefined); }); } else { resolve(typeof cb === 'function' ? cb() : undefined); } }); } disconnect<T>(cb?: () => T) { return new Promise<T>((resolve) => { if (this.isConnected()) { this.socket.once('close', () => { resolve(typeof cb === 'function' ? cb() : undefined); }); this.socket.close(); } else { resolve(typeof cb === 'function' ? cb() : undefined); } }); } send(host: string, port: number, data) { return new Promise<void>((resolve, reject) => { if (this.isConnected()) { this.socket.send(data, port, host, (err, bytes) => { if (err) { reject(err); } if (bytes !== data.length) { reject(new Error(`Expected to send ${data.length} bytes, but sent ${bytes}`)); } resolve(); }); } else { throw new Error(`No connection`); } }); } on(event: 'disconnect', cb: () => void): Subscriber; on(event: 'raw', cb: (raw: Buffer, sender: RemoteInfo) => void): Subscriber; on<T>(event: string, cb: (query: T, sender: RemoteInfo) => void): Subscriber; on(event: string, cb: (...args: any[]) => void): Subscriber { if (this.events.on(event, cb)) { return { unsubscribe: () => this.events.removeListener(event, cb), }; } else { throw new Error(`Failed to subscribe`); } } }