From 3a3958cc9787b2bffd64651d5bc78a72e9b4e33e Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Tue, 10 May 2022 14:11:48 +0200 Subject: [PATCH] * update * (Apollon77) Add experimental flag options.subscriptionsUseSameConnection for HTTP Client to use the same connection for subscriptions and for all other calls to only have one connection from controller to the device. --- README.md | 3 +++ src/transport/ip/http-client.ts | 45 +++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d4312d5..ad49866 100644 --- a/README.md +++ b/README.md @@ -265,6 +265,9 @@ For Issues please consider to directly provide debug loggins (see above). ## Changelog +### __WORK IN PROGRESS__ +* (Apollon77) Add experimental flag options.subscriptionsUseSameConnection for HTTP Client to use the same connection for subscriptions and for all other calls to only have one connection from controller to the device. + ### 0.7.4 (2022-05-06) * (Apollon77) Add Host header to all HTTP calls because some devices seem to require it * (Apollon77) Check that client was initialized before accessing the connected state diff --git a/src/transport/ip/http-client.ts b/src/transport/ip/http-client.ts index 2519716..ba87c4b 100644 --- a/src/transport/ip/http-client.ts +++ b/src/transport/ip/http-client.ts @@ -112,10 +112,17 @@ interface EventCharacteristicsObject { interface HttpClientOptions { /** * Set to true to use persistent connections for normal device interactions - * Without persistent connections a new pairing verification is rerquired + * Without persistent connections a new pairing verification is required * before each call which delays the execution. */ usePersistentConnections: boolean; + + /** + * Set this to true to use the same persistent connection for subscriptions + * as also for normal device interactions. This basically means that only + * one connection to the device ist used + */ + subscriptionsUseSameConnection: boolean; } export default class HttpClient extends EventEmitter { @@ -133,6 +140,8 @@ export default class HttpClient extends EventEmitter { private usePersistentConnections = true; + private subscriptionsUseSameConnection = false; + private subscriptionConnection?: HttpConnection; private subscribedCharacteristics: string[] = []; @@ -162,6 +171,7 @@ export default class HttpClient extends EventEmitter { this.pairingProtocol = new PairingProtocol(pairingData); this.pairingQueue = new OpQueue(); this.usePersistentConnections = options?.usePersistentConnections || false; + this.subscriptionsUseSameConnection = options?.subscriptionsUseSameConnection || false; } /** @@ -195,6 +205,7 @@ export default class HttpClient extends EventEmitter { * Checks if a maybe persistent connection should be closed * * @param {HttpConnection} connection Connection which was returned by getDefaultVerifiedConnection() + * @param {boolean} forceClose - Force close the connection * @private */ private closeMaybePersistentConnection(connection: HttpConnection, forceClose = false): void { @@ -597,13 +608,18 @@ export default class HttpClient extends EventEmitter { * @returns {Promise} Promise */ async subscribeCharacteristics(characteristics: string[]): Promise { - const connection = this.subscriptionConnection || new HttpConnection(this.address, this.port); + let connection: HttpConnection; + if (this.subscriptionsUseSameConnection) { + connection = await this.getDefaultVerifiedConnection(); + } else { + connection = this.subscriptionConnection || new HttpConnection(this.address, this.port); + } const data = { characteristics: [], }; - if (!this.subscriptionConnection) { + if (!this.subscriptionConnection && !this.subscriptionsUseSameConnection) { const keys = await this._pairVerify(connection); connection.setSessionKeys(keys); } @@ -635,7 +651,8 @@ export default class HttpClient extends EventEmitter { this.emit('event', JSON.parse(ev)); }); - connection.on('disconnect', () => { + connection.once('disconnect', () => { + connection.removeAllListeners('event'); delete this.subscriptionConnection; if (this.subscribedCharacteristics.length) { /** @@ -662,7 +679,10 @@ export default class HttpClient extends EventEmitter { if (response.statusCode !== 204 && response.statusCode !== 207) { if (!this.subscribedCharacteristics.length) { - connection.close(); + if (!this.subscriptionsUseSameConnection) { + connection.close(); + } + connection.removeAllListeners('event'); delete this.subscriptionConnection; } throw new HomekitControllerError( @@ -733,7 +753,10 @@ export default class HttpClient extends EventEmitter { }); if (!this.subscribedCharacteristics.length) { - this.subscriptionConnection.close(); + if (!this.subscriptionsUseSameConnection) { + this.subscriptionConnection.close(); + } + this.subscriptionConnection?.removeAllListeners('event'); delete this.subscriptionConnection; } } @@ -812,10 +835,12 @@ export default class HttpClient extends EventEmitter { // ignore } delete this._pairingConnection; - try { - this.subscriptionConnection?.close(); - } catch { - // ignore + if (!this.subscriptionsUseSameConnection) { + try { + this.subscriptionConnection?.close(); + } catch { + // ignore + } } delete this.subscriptionConnection; this.subscribedCharacteristics = [];