chore: merge master to dev

This commit is contained in:
Koen Kanters authored and GitHub committed 2023-12-10 21:21:18 +01:00
commit 0a2d9ba952
2 files changed
+38 -1

No files matched your search

+13 -1
View File
@@ -18,6 +18,7 @@ export default class Availability extends Extension {
private retrieveStateDebouncers: {[s: string]: () => void} = {};
private pingQueue: Device[] = [];
private pingQueueExecuting = false;
private stopped = false;
private getTimeout(device: Device): number {
if (typeof device.options.availability === 'object' && device.options.availability?.timeout != null) {
@@ -93,6 +94,11 @@ export default class Availability extends Extension {
}
}
if (this.stopped) {
// Exit here to avoid triggering any follow-up activity (e.g., re-queuing another ping attempt).
return;
}
this.publishAvailability(device, !pingedSuccessfully);
this.resetTimer(device);
this.removeFromPingQueue(device);
@@ -104,6 +110,10 @@ export default class Availability extends Extension {
}
override async start(): Promise<void> {
if (this.stopped) {
throw new Error('This extension cannot be restarted.');
}
this.eventBus.onEntityRenamed(this, (data) => {
if (utils.isAvailabilityEnabledForEntity(data.entity, settings.get())) {
this.mqtt.publish(`${data.from}/availability`, null, {retain: true, qos: 1});
@@ -184,8 +194,10 @@ export default class Availability extends Extension {
}
override async stop(): Promise<void> {
this.stopped = true;
this.pingQueue = [];
Object.values(this.timers).forEach((t) => clearTimeout(t));
super.stop();
await super.stop();
}
private retrieveState(device: Device): void {
+25
View File
@@ -6,6 +6,7 @@ import zigbeeHerdsman from './stub/zigbeeHerdsman';
import utils from '../lib/util/utils';
import * as settings from '../lib/util/settings';
import Controller from '../lib/controller';
import Availability from '../lib/extension/availability';
import flushPromises from './lib/flushPromises';
import stringify from 'json-stable-stringify-without-jsonify';
@@ -344,4 +345,28 @@ describe('Availability', () => {
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/group_tradfri_remote/availability',
'online', {retain: true, qos: 1}, expect.any(Function));
});
it('Should clear the ping queue on stop', async () => {
const availability = controller.extensions.find((extension) => extension instanceof Availability);
const publishAvailabilitySpy = jest.spyOn(availability, 'publishAvailability');
devices.bulb_color.zh = { ping: jest.fn().mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 1000)))};
availability.addToPingQueue(devices.bulb_color);
availability.addToPingQueue(devices.bulb_color_2);
await availability.stop();
await advancedTime(utils.minutes(1));
expect(availability.pingQueue).toEqual([]);
// Validate the stop-interrupt implicitly by checking that it prevents further function invocations
expect(publishAvailabilitySpy).not.toHaveBeenCalled();
});
it('Should prevent instance restart', async () => {
const availability = controller.extensions.find((extension) => extension instanceof Availability);
await availability.stop();
await expect(() => availability.start()).rejects.toThrowError();
});
});