mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-08-27 21:20:03 +00:00
fix(ignore): Changes for new ZHC definition.version (#30402)
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: burmistrzak <61958704+burmistrzak@users.noreply.github.com> Co-authored-by: rhysfred <rhysfred@users.noreply.github.com> Co-authored-by: rhys <rhys@frontleftspeaker.com> Co-authored-by: Patrick ZAJDA <patrick@zajda.fr> Co-authored-by: Ignacio Hernandez-Ros <ignacio@hernandez-ros.com> Co-authored-by: Rohan Kapoor <rohan@rohankapoor.com> Co-authored-by: Nerivec <62446222+Nerivec@users.noreply.github.com> Co-authored-by: Stephan Garland <stephan.garland@affirm.com> Co-authored-by: Andrei LAZAROV <andrei_lazarov@yahoo.com>
This commit is contained in:
co-authored by
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
burmistrzak
rhysfred
rhys
Patrick ZAJDA
Ignacio Hernandez-Ros
Rohan Kapoor
Nerivec
Stephan Garland
Andrei LAZAROV
parent
6cce05a514
commit
b71461e03c
@@ -1,6 +1,5 @@
|
||||
import bind from "bind-decorator";
|
||||
import stringify from "json-stable-stringify-without-jsonify";
|
||||
import * as zhc from "zigbee-herdsman-converters";
|
||||
import Device from "../model/device";
|
||||
import type {Zigbee2MQTTAPI} from "../types/api";
|
||||
import logger from "../util/logger";
|
||||
@@ -94,17 +93,25 @@ export default class Configure extends Extension {
|
||||
return;
|
||||
}
|
||||
|
||||
const definitionVersion = device.definition.version;
|
||||
if (!force) {
|
||||
if (device.options.disabled || !device.interviewed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (device.zh.meta?.configured !== undefined) {
|
||||
// Only configure end devices when it is active, otherwise it will likely fails as they are sleeping.
|
||||
if (device.zh.type === "EndDevice" && event !== "zigbee_event") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only configure end devices when it is active, otherwise it will likely fails as they are sleeping.
|
||||
if (device.zh.type === "EndDevice" && event !== "zigbee_event") {
|
||||
const shouldReconfigure =
|
||||
// Should always reconfigure when not configured before
|
||||
device.zh.meta?.configured === undefined ||
|
||||
// Or should reconfigure when definition.version is not '0.0.0' and differs from last `meta.configured`.
|
||||
// In older Z2M versions the stored `meta.configured` was the hash of the configure function.
|
||||
// Since we don't want to reconfigure all devices, we don't re-configure when the definition has the default version of '0.0.0'.
|
||||
(definitionVersion !== "0.0.0" && device.zh.meta?.configured !== definitionVersion);
|
||||
if (!shouldReconfigure) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -122,8 +129,8 @@ export default class Configure extends Extension {
|
||||
logger.info(`Configuring '${device.name}'`);
|
||||
try {
|
||||
await device.definition.configure(device.zh, this.zigbee.firstCoordinatorEndpoint(), device.definition);
|
||||
logger.info(`Successfully configured '${device.name}'`);
|
||||
device.zh.meta.configured = zhc.getConfigureKey(device.definition);
|
||||
logger.info(`Successfully configured '${device.name}' (definition v${definitionVersion})`);
|
||||
device.zh.meta.configured = definitionVersion;
|
||||
device.zh.save();
|
||||
this.eventBus.emitDevicesChanged();
|
||||
} catch (error) {
|
||||
|
||||
@@ -358,7 +358,7 @@ describe("Extension: Bind", () => {
|
||||
{attribute: "currentX", minimumReportInterval: 5, maximumReportInterval: 0xffff, reportableChange: 1},
|
||||
{attribute: "currentY", minimumReportInterval: 5, maximumReportInterval: 0xffff, reportableChange: 1},
|
||||
]);
|
||||
expect(devices.bulb_color.meta.configured).toBe(332242049);
|
||||
expect(devices.bulb_color.meta.configured).toBe("0.0.0");
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
"zigbee2mqtt/bridge/response/device/unbind",
|
||||
stringify({
|
||||
|
||||
@@ -4,13 +4,15 @@ import * as data from "../mocks/data";
|
||||
import {mockLogger} from "../mocks/logger";
|
||||
import {events as mockMQTTEvents, mockMQTTPublishAsync} from "../mocks/mqtt";
|
||||
import {flushPromises} from "../mocks/utils";
|
||||
import {type Device, devices, type Endpoint, events as mockZHEvents} from "../mocks/zigbeeHerdsman";
|
||||
import {devices, type Endpoint, events as mockZHEvents, type Device as ZhDevice} from "../mocks/zigbeeHerdsman";
|
||||
|
||||
import stringify from "json-stable-stringify-without-jsonify";
|
||||
import {InterviewState} from "zigbee-herdsman/dist/controller/model/device";
|
||||
import {Controller} from "../../lib/controller";
|
||||
import Device from "../../lib/model/device";
|
||||
import Configure from "../../lib/extension/configure";
|
||||
import * as settings from "../../lib/util/settings";
|
||||
import assert from "node:assert";
|
||||
|
||||
const mocksClear = [mockMQTTPublishAsync, mockLogger.warning, mockLogger.debug];
|
||||
|
||||
@@ -23,7 +25,7 @@ describe("Extension: Configure", () => {
|
||||
await controller.addExtension(new Configure(...controller.extensionArgs));
|
||||
};
|
||||
|
||||
const mockClear = (device: Device): void => {
|
||||
const mockClear = (device: ZhDevice): void => {
|
||||
for (const endpoint of device.endpoints) {
|
||||
endpoint.read.mockClear();
|
||||
endpoint.write.mockClear();
|
||||
@@ -42,7 +44,7 @@ describe("Extension: Configure", () => {
|
||||
const endpoint2 = device.getEndpoint(2)!;
|
||||
expect(endpoint2.write).toHaveBeenCalledTimes(1);
|
||||
expect(endpoint2.write).toHaveBeenCalledWith("genBasic", {49: {type: 25, value: 11}}, {disableDefaultResponse: true, manufacturerCode: 4107});
|
||||
expect(device.meta.configured).toBe(332242049);
|
||||
expect(device.meta.configured).toBe("0.0.0");
|
||||
};
|
||||
|
||||
const expectBulbConfigured = (): void => {
|
||||
@@ -147,6 +149,52 @@ describe("Extension: Configure", () => {
|
||||
expectBulbConfigured();
|
||||
});
|
||||
|
||||
it("Should re-configure when the version of the definition changes to a different value than the default (0.0.0)", async () => {
|
||||
// Device is initially configured (definition has uses default version of 0.0.0)
|
||||
const device = devices.bulb;
|
||||
expectBulbConfigured();
|
||||
|
||||
// Nothing happens when receiving a Zigbee message
|
||||
mockClear(device);
|
||||
await mockZHEvents.lastSeenChanged({device});
|
||||
await flushPromises();
|
||||
expectBulbNotConfigured();
|
||||
|
||||
// Simulate that the definition version changes
|
||||
const resolvedEntity = controller.zigbee.resolveEntity(device);
|
||||
assert(resolvedEntity instanceof Device && resolvedEntity.definition);
|
||||
assert(resolvedEntity.definition.version === "0.0.0");
|
||||
|
||||
try {
|
||||
// Change the version to a different value
|
||||
resolvedEntity.definition.version = "0.0.1";
|
||||
|
||||
// Now it should re-configure upon receiving a Zigbee message
|
||||
mockClear(device);
|
||||
await mockZHEvents.lastSeenChanged({device});
|
||||
await flushPromises();
|
||||
expectBulbConfigured();
|
||||
} finally {
|
||||
resolvedEntity.definition.version = "0.0.0";
|
||||
}
|
||||
});
|
||||
|
||||
it("Should NOT re-configure when version of the definition is 0.0.0", async () => {
|
||||
// This test the migration from the old configureKey (hash of the configure function) to the new definition version system.
|
||||
// See commment in `configure.ts` -> `shouldReconfigure` for more details.
|
||||
|
||||
// Device is initially configured (definition has uses default version of 0.0.0)
|
||||
const device = devices.bulb;
|
||||
expectBulbConfigured();
|
||||
device.meta.configured = 1321;
|
||||
|
||||
// Nothing happens when receiving a Zigbee message
|
||||
mockClear(device);
|
||||
await mockZHEvents.lastSeenChanged({device});
|
||||
await flushPromises();
|
||||
expectBulbNotConfigured();
|
||||
});
|
||||
|
||||
it("Should allow to configure via MQTT", async () => {
|
||||
mockClear(devices.remote);
|
||||
expectRemoteNotConfigured();
|
||||
|
||||
@@ -143,7 +143,7 @@ describe("Extension: OTAUpdate", () => {
|
||||
expect(infoCalls[7]).toStrictEqual(`Interviewing 'bulb'`);
|
||||
expect(infoCalls[8]).toStrictEqual(`Configuring 'bulb'`);
|
||||
expect(infoCalls[10]).toStrictEqual(`Successfully interviewed 'bulb'`);
|
||||
expect(infoCalls[11]).toStrictEqual(`Successfully configured 'bulb'`);
|
||||
expect(infoCalls[11]).toStrictEqual(`Successfully configured 'bulb' (definition v0.0.0)`);
|
||||
|
||||
expect(devices.bulb.save).toHaveBeenCalledTimes(1);
|
||||
expect(devices.bulb.endpoints[0].read).toHaveBeenCalledWith("genBasic", ["dateCode", "swBuildId"], {sendPolicy: "immediate"});
|
||||
|
||||
Reference in New Issue
Block a user