diff --git a/src/adapter/ezsp/adapter/ezspAdapter.ts b/src/adapter/ezsp/adapter/ezspAdapter.ts index 80795748b9..ea00940948 100644 --- a/src/adapter/ezsp/adapter/ezspAdapter.ts +++ b/src/adapter/ezsp/adapter/ezspAdapter.ts @@ -13,7 +13,7 @@ import {Driver, EmberIncomingMessage} from '../driver'; import {EmberZDOCmd, EmberApsOption, uint16_t, EmberEUI64, EmberStatus, EmberKeyData} from '../driver/types'; import {ZclFrame, FrameType, Direction, Foundation} from '../../../zcl'; import * as Events from '../../events'; -import {Waitress, Wait, RealpathSync} from '../../../utils'; +import {Queue, Waitress, Wait, RealpathSync} from '../../../utils'; import * as Models from "../../../models"; import SerialPortUtils from '../../serialPortUtils'; import SocketPortUtils from '../../socketPortUtils'; @@ -40,6 +40,8 @@ class EZSPAdapter extends Adapter { private waitress: Waitress; private interpanLock: boolean; private backupMan: EZSPAdapterBackup; + private queue: Queue; + public constructor(networkOptions: NetworkOptions, serialPortOptions: SerialPortOptions, backupPath: string, adapterOptions: AdapterOptions) { @@ -49,6 +51,11 @@ class EZSPAdapter extends Adapter { this.waitressValidator, this.waitressTimeoutFormatter ); this.interpanLock = false; + + const concurrent = adapterOptions && adapterOptions.concurrent ? adapterOptions.concurrent : 8; + debug(`Adapter concurrent: ${concurrent}`); + this.queue = new Queue(concurrent); + this.driver = new Driver(); this.driver.on('deviceJoined', this.handleDeviceJoin.bind(this)); this.driver.on('deviceLeft', this.handleDeviceLeft.bind(this)); @@ -197,7 +204,7 @@ class EZSPAdapter extends Adapter { } public async getCoordinator(): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.checkInterpanLock(); const networkAddress = 0x0000; const message = await this.driver.zdoRequest( @@ -231,7 +238,7 @@ class EZSPAdapter extends Adapter { } public async permitJoin(seconds: number, networkAddress: number): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.checkInterpanLock(); if (seconds) { this.driver.preJoining(); @@ -267,7 +274,7 @@ class EZSPAdapter extends Adapter { } public async lqi(networkAddress: number): Promise { - return this.driver.queue.execute(async (): Promise => { + return this.queue.execute(async (): Promise => { this.checkInterpanLock(); const neighbors: LQINeighbor[] = []; @@ -313,7 +320,7 @@ class EZSPAdapter extends Adapter { } public async routingTable(networkAddress: number): Promise { - return this.driver.queue.execute(async (): Promise => { + return this.queue.execute(async (): Promise => { this.checkInterpanLock(); const table: RoutingTableEntry[] = []; @@ -356,7 +363,7 @@ class EZSPAdapter extends Adapter { } public async nodeDescriptor(networkAddress: number): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.checkInterpanLock(); try { debug(`Requesting 'Node Descriptor' for '${networkAddress}'`); @@ -383,7 +390,7 @@ class EZSPAdapter extends Adapter { public async activeEndpoints(networkAddress: number): Promise { debug(`Requesting 'Active endpoints' for '${networkAddress}'`); - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { const endpoints = await this.driver.zdoRequest( networkAddress, EmberZDOCmd.Active_EP_req, EmberZDOCmd.Active_EP_rsp, {dstaddr: networkAddress} @@ -394,7 +401,7 @@ class EZSPAdapter extends Adapter { public async simpleDescriptor(networkAddress: number, endpointID: number): Promise { debug(`Requesting 'Simple Descriptor' for '${networkAddress}' endpoint ${endpointID}`); - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.checkInterpanLock(); const descriptor = await this.driver.zdoRequest( networkAddress, EmberZDOCmd.Simple_Desc_req, EmberZDOCmd.Simple_Desc_rsp, @@ -414,11 +421,13 @@ class EZSPAdapter extends Adapter { ieeeAddr: string, networkAddress: number, endpoint: number, zclFrame: ZclFrame, timeout: number, disableResponse: boolean, disableRecovery: boolean, sourceEndpoint?: number, ): Promise { - this.checkInterpanLock(); - return this.sendZclFrameToEndpointInternal( - ieeeAddr, networkAddress, endpoint, sourceEndpoint || 1, zclFrame, timeout, disableResponse, - disableRecovery, 0, 0, false, false, false, null - ); + return this.queue.execute(async () => { + this.checkInterpanLock(); + return this.sendZclFrameToEndpointInternal( + ieeeAddr, networkAddress, endpoint, sourceEndpoint || 1, zclFrame, timeout, disableResponse, + disableRecovery, 0, 0, false, false, false, null + ); + }, networkAddress); } private async sendZclFrameToEndpointInternal( @@ -431,7 +440,7 @@ class EZSPAdapter extends Adapter { ieeeAddr = `0x${this.driver.ieee.toString()}`; } debug('sendZclFrameToEndpointInternal %s:%i/%i (%i,%i,%i)', - ieeeAddr, networkAddress, endpoint, responseAttempt, dataRequestAttempt, this.driver.queue.count()); + ieeeAddr, networkAddress, endpoint, responseAttempt, dataRequestAttempt, this.queue.count()); let response = null; const command = zclFrame.getCommand(); if (command.hasOwnProperty('response') && disableResponse === false) { @@ -483,7 +492,7 @@ class EZSPAdapter extends Adapter { } public async sendZclFrameToGroup(groupID: number, zclFrame: ZclFrame): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.checkInterpanLock(); const frame = this.driver.makeApsFrame(zclFrame.Cluster.ID, false); frame.profileId = 0x0104; @@ -501,7 +510,7 @@ class EZSPAdapter extends Adapter { } public async sendZclFrameToAll(endpoint: number, zclFrame: ZclFrame, sourceEndpoint: number): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.checkInterpanLock(); const frame = this.driver.makeApsFrame(zclFrame.Cluster.ID, false); frame.profileId = sourceEndpoint === 242 && endpoint === 242 ? 0xA1E0 : 0x0104; @@ -524,7 +533,7 @@ class EZSPAdapter extends Adapter { clusterID: number, destinationAddressOrGroup: string | number, type: 'endpoint' | 'group', destinationEndpoint?: number ): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.checkInterpanLock(); const ieee = new EmberEUI64(sourceIeeeAddress); let destAddr; @@ -555,7 +564,7 @@ class EZSPAdapter extends Adapter { clusterID: number, destinationAddressOrGroup: string | number, type: 'endpoint' | 'group', destinationEndpoint: number ): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.checkInterpanLock(); const ieee = new EmberEUI64(sourceIeeeAddress); let destAddr; @@ -582,7 +591,7 @@ class EZSPAdapter extends Adapter { } public removeDevice(networkAddress: number, ieeeAddr: string): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.checkInterpanLock(); const ieee = new EmberEUI64(ieeeAddr); this.driver.setNode(networkAddress, ieee); @@ -610,7 +619,7 @@ class EZSPAdapter extends Adapter { } public async restoreChannelInterPAN(): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { const channel = (await this.getNetworkParameters()).channel; await this.driver.setChannel(channel); // Give adapter some time to restore, otherwise stuff crashes @@ -626,7 +635,7 @@ class EZSPAdapter extends Adapter { } public async sendZclFrameInterPANToIeeeAddr(zclFrame: ZclFrame, ieeeAddr: string): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { debug(`sendZclFrameInterPANToIeeeAddr to ${ieeeAddr}`); try { const frame = this.driver.makeEmberIeeeRawFrame(); @@ -647,7 +656,7 @@ class EZSPAdapter extends Adapter { } public async sendZclFrameInterPANBroadcast(zclFrame: ZclFrame, timeout: number): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { debug(`sendZclFrameInterPANBroadcast`); const command = zclFrame.getCommand(); if (!command.hasOwnProperty('response')) { @@ -681,13 +690,13 @@ class EZSPAdapter extends Adapter { public async setTransmitPower(value: number): Promise { debug(`setTransmitPower to ${value}`); - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { await this.driver.setRadioPower(value); }); } public async setChannelInterPAN(channel: number): Promise { - return this.driver.queue.execute(async () => { + return this.queue.execute(async () => { this.interpanLock = true; await this.driver.setChannel(channel); }); diff --git a/src/adapter/ezsp/driver/driver.ts b/src/adapter/ezsp/driver/driver.ts index a8147e8df9..6bd0251d7d 100644 --- a/src/adapter/ezsp/driver/driver.ts +++ b/src/adapter/ezsp/driver/driver.ts @@ -19,7 +19,7 @@ import { EmberKeyType } from './types/named'; import {Multicast} from './multicast'; -import {Queue, Waitress, Wait} from '../../../utils'; +import {Waitress, Wait} from '../../../utils'; import Debug from "debug"; import equals from 'fast-deep-equal/es6'; import {ParamsDesc} from './commands'; @@ -87,7 +87,6 @@ export class Driver extends EventEmitter { public ieee: EmberEUI64; private multicast: Multicast; private waitress: Waitress; - public queue: Queue; private transactionID = 1; private port: string; /* eslint-disable-next-line @typescript-eslint/no-explicit-any*/ @@ -95,7 +94,7 @@ export class Driver extends EventEmitter { constructor() { super(); - this.queue = new Queue(8); + this.waitress = new Waitress( this.waitressValidator, this.waitressTimeoutFormatter); } diff --git a/src/adapter/ezsp/driver/multicast.ts b/src/adapter/ezsp/driver/multicast.ts index 76557f26b1..b1a29bad70 100644 --- a/src/adapter/ezsp/driver/multicast.ts +++ b/src/adapter/ezsp/driver/multicast.ts @@ -41,15 +41,13 @@ export class Multicast { /* eslint-disable-next-line @typescript-eslint/no-explicit-any*/ async startup(enpoints: Array): Promise { - return this.driver.queue.execute(async () => { - await this._initialize(); - for (const ep of enpoints) { - if (!ep.id) continue; - for (const group_id of ep.member_of) { - await this.subscribe(group_id, ep.id); - } + await this._initialize(); + for (const ep of enpoints) { + if (!ep.id) continue; + for (const group_id of ep.member_of) { + await this.subscribe(group_id, ep.id); } - }); + } } public async subscribe(group_id: number, endpoint: number): Promise {