diff --git a/lib/extension/availabilityNew.ts b/lib/extension/availabilityNew.ts index e7d560fc3..418f90d45 100644 --- a/lib/extension/availabilityNew.ts +++ b/lib/extension/availabilityNew.ts @@ -128,6 +128,15 @@ class AvailabilityNew extends ExtensionTS { this.zigbee.on('lastSeenChanged', this.lastSeenChanged); } + override onZigbeeEvent(type: ZigbeeEventType, data: ZigbeeEventData, resolvedEntity: ResolvedEntity): void { + resolvedEntity; + + /* istanbul ignore else */ + if (type === 'deviceLeave') { + clearTimeout(this.timers[data.ieeeAddr]); + } + } + private publishAvailability(re: ResolvedEntity, logLastSeen: boolean): void { if (logLastSeen) { const ago = Date.now() - re.device.lastSeen; diff --git a/lib/extension/extensionts.ts b/lib/extension/extensionts.ts index 95c7bff65..d76e31f56 100644 --- a/lib/extension/extensionts.ts +++ b/lib/extension/extensionts.ts @@ -44,7 +44,7 @@ abstract class ExtensionTS { */ /* istanbul ignore next */ /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - onZigbeeEvent(type: string, data: unknown, resolvedEntity: ResolvedEntity): void {} + onZigbeeEvent(type: ZigbeeEventType, data: ZigbeeEventData, resolvedEntity: ResolvedEntity): void {} /** * Is called when a MQTT message is received diff --git a/lib/types/types.ts b/lib/types/types.ts index f8d475249..32cefb43f 100644 --- a/lib/types/types.ts +++ b/lib/types/types.ts @@ -3,6 +3,12 @@ import type {Device as ZHDevice} from 'zigbee-herdsman/dist/controller/model'; declare global { type Device = ZHDevice; + type ZigbeeEventType = 'deviceLeave'; + + interface ZigbeeEventData { + ieeeAddr: string; + } + /* eslint-disable */ // Controller interface KeyValue { diff --git a/test/availabilityNew.test.ts b/test/availabilityNew.test.ts index d8b0b1268..fa1b49884 100644 --- a/test/availabilityNew.test.ts +++ b/test/availabilityNew.test.ts @@ -196,4 +196,18 @@ describe('Availability', () => { await advancedTime(minutes(7)); expect(devices.bulb_color.ping).toHaveBeenCalledTimes(1); }); + + it('Should stop pinging device when it leaves', async () => { + await resetExtension(); + MQTT.publish.mockClear(); + + await advancedTime(minutes(9)); + expect(devices.bulb_color.ping).toHaveBeenCalledTimes(0); + + await zigbeeHerdsman.events.deviceLeave({ieeeAddr: devices.bulb_color.ieeeAddr}); + await flushPromises(); + + await advancedTime(minutes(3)); + expect(devices.bulb_color.ping).toHaveBeenCalledTimes(0); + }); });