From 4c8e93402220e193b5f38991de499b3ca99f0170 Mon Sep 17 00:00:00 2001 From: Nerivec <62446222+Nerivec@users.noreply.github.com> Date: Wed, 5 Mar 2025 03:45:49 +0100 Subject: [PATCH] feedback --- src/controller/model/device.ts | 2 +- src/controller/model/endpoint.ts | 27 ++++++++++----------------- test/controller.test.ts | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/controller/model/device.ts b/src/controller/model/device.ts index db9534966f..6d46b9af49 100755 --- a/src/controller/model/device.ts +++ b/src/controller/model/device.ts @@ -476,7 +476,7 @@ export class Device extends Entity { const commandHasResponse = frame.command.response != undefined; const disableDefaultResponse = frame.header.frameControl.disableDefaultResponse; /* v8 ignore next */ - const disableTuyaDefaultResponse = endpoint.getDevice()!.manufacturerName?.startsWith('_TZ') && process.env['DISABLE_TUYA_DEFAULT_RESPONSE']; + const disableTuyaDefaultResponse = endpoint.getDevice().manufacturerName?.startsWith('_TZ') && process.env['DISABLE_TUYA_DEFAULT_RESPONSE']; // Sometimes messages are received twice, prevent responding twice const alreadyResponded = this._lastDefaultResponseSequenceNumber === frame.header.transactionSequenceNumber; diff --git a/src/controller/model/endpoint.ts b/src/controller/model/endpoint.ts index 46f95c2070..85527388c3 100644 --- a/src/controller/model/endpoint.ts +++ b/src/controller/model/endpoint.ts @@ -119,7 +119,6 @@ export class Endpoint extends Entity { get configuredReportings(): ConfiguredReporting[] { const device = this.getDevice(); - assert(device, `Cannot get configured reportings for unknown/deleted device ${this.deviceIeeeAddress}`); return this._configuredReportings.map((entry, index) => { const cluster = Zcl.Utils.getCluster(entry.cluster, entry.manufacturerCode, device.customClusters); @@ -168,8 +167,15 @@ export class Endpoint extends Entity { /** * Get device of this endpoint */ - public getDevice(): Device | undefined { - return Device.byIeeeAddr(this.deviceIeeeAddress); + public getDevice(): Device { + const device = Device.byIeeeAddr(this.deviceIeeeAddress); + + if (!device) { + logger.error(`Tried to get unknown/deleted device ${this.deviceIeeeAddress} from endpoint ${this.ID}.`, NS); + logger.debug(new Error().stack!, NS); + } + + return device!; } /** @@ -312,8 +318,6 @@ export class Endpoint extends Entity { ): Promise { const logPrefix = `Request Queue (${this.deviceIeeeAddress}/${this.ID}): `; const device = this.getDevice(); - assert(device, `Cannot send to unknown/deleted device ${this.deviceIeeeAddress}`); - const request = new Request(func, frame, device.pendingRequestTimeout, options.sendPolicy); if (request.sendPolicy !== 'bulk') { @@ -433,8 +437,6 @@ export class Endpoint extends Entity { public async read(clusterKey: number | string, attributes: (string | number)[], options?: Options): Promise { const device = this.getDevice(); - assert(device, `Cannot read from unknown/deleted device ${this.deviceIeeeAddress}`); - const cluster = this.getCluster(clusterKey, device); const optionsWithDefaults = this.getOptionsWithDefaults(options, true, Zcl.Direction.CLIENT_TO_SERVER, cluster.manufacturerCode); optionsWithDefaults.manufacturerCode = this.ensureManufacturerCodeIsUniqueAndGet( @@ -582,7 +584,7 @@ export class Endpoint extends Entity { } public save(): void { - this.getDevice()?.save(); + this.getDevice().save(); } public async unbind(clusterKey: number | string, target: Endpoint | Group | number): Promise { @@ -741,8 +743,6 @@ export class Endpoint extends Entity { assert(options?.transactionSequenceNumber === undefined, 'Use parameter'); const device = this.getDevice(); - assert(device, `Cannot respond to unknown/deleted device ${this.deviceIeeeAddress}`); - const cluster = this.getCluster(clusterKey, device); const command = cluster.getCommandResponse(commandKey); transactionSequenceNumber = transactionSequenceNumber || ZclTransactionSequenceNumber.next(); @@ -799,8 +799,6 @@ export class Endpoint extends Entity { timeout: number, ): {promise: Promise<{header: Zcl.Header; payload: KeyValue}>; cancel: () => void} { const device = this.getDevice(); - assert(device, `Cannot wait for unknown/deleted device ${this.deviceIeeeAddress}`); - const cluster = this.getCluster(clusterKey, device); const command = cluster.getCommand(commandKey); const waiter = Entity.adapter!.waitFor( @@ -896,7 +894,6 @@ export class Endpoint extends Entity { private getCluster(clusterKey: number | string, device: Device | undefined = undefined): ZclTypes.Cluster { if (!device) { device = this.getDevice(); - assert(device, `Cannot get cluster for unknown/deleted device ${this.deviceIeeeAddress}`); } return Zcl.Utils.getCluster(clusterKey, device.manufacturerID, device.customClusters); @@ -937,8 +934,6 @@ export class Endpoint extends Entity { frameType: Zcl.FrameType = Zcl.FrameType.GLOBAL, ): Promise { const device = this.getDevice(); - assert(device, `Cannot send to unknown/deleted device ${this.deviceIeeeAddress}`); - const cluster = this.getCluster(clusterKey, device); const command = frameType == Zcl.FrameType.GLOBAL ? Zcl.Utils.getGlobalCommand(commandKey) : cluster.getCommand(commandKey); const hasResponse = frameType == Zcl.FrameType.GLOBAL ? true : command.response != undefined; @@ -989,8 +984,6 @@ export class Endpoint extends Entity { options?: Options, ): Promise { const device = this.getDevice(); - assert(device, `Cannot send to unknown/deleted device ${this.deviceIeeeAddress}`); - const cluster = this.getCluster(clusterKey, device); const command = cluster.getCommand(commandKey); const optionsWithDefaults = this.getOptionsWithDefaults(options, true, Zcl.Direction.CLIENT_TO_SERVER, cluster.manufacturerCode); diff --git a/test/controller.test.ts b/test/controller.test.ts index 1c74943c80..76e585f808 100755 --- a/test/controller.test.ts +++ b/test/controller.test.ts @@ -5279,6 +5279,22 @@ describe('Controller', () => { }); }); + it('Try to get deleted device from endpoint', async () => { + await controller.start(); + await mockAdapterEvents['deviceJoined']({networkAddress: 129, ieeeAddr: '0x129'}); + const device = controller.getDeviceByIeeeAddr('0x129')!; + const endpoint = device.getEndpoint(1)!; + await mockAdapterEvents['deviceLeave']({networkAddress: 129, ieeeAddr: '0x129'}); + // @ts-expect-error private + expect(Device.devices.size).toStrictEqual(1); + // @ts-expect-error private + expect(Device.deletedDevices.size).toStrictEqual(1); + const delDevice = endpoint.getDevice(); + + expect(delDevice).toBeUndefined(); + expect(mockLogger.error).toHaveBeenCalledWith('Tried to get unknown/deleted device 0x129 from endpoint 1.', 'zh:controller:endpoint'); + }); + it('Command response', async () => { await controller.start(); await mockAdapterEvents['deviceJoined']({networkAddress: 129, ieeeAddr: '0x129'});