Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
4d6e98a
fix(ignore): Changes for new ZHC `configureKey`
Koenkk Dec 30, 2025
8000247
fix(ignore): bump zigbee2mqtt-windfront from 2.6.1 to 2.6.2 in the mi…
dependabot[bot] Dec 31, 2025
5e5f1e9
fix(ignore): update zigbee-herdsman-converters to 25.98.0 (#30417)
Koenkk Jan 1, 2026
94da137
chore(dev): release 2.7.2 (#30051)
Koenkk Jan 1, 2026
f84ec1b
chore: promote to dev
github-actions[bot] Jan 1, 2026
cdc3d31
fix(ignore): update zigbee-herdsman to 8.0.2 (#30480)
Koenkk Jan 3, 2026
ec97844
fix(ignore): update zigbee-herdsman-converters to 25.99.0 (#30481)
Koenkk Jan 4, 2026
0c6444f
fix: Log error before renaming failed to load converters (#30436)
rhysfred Jan 4, 2026
aea8368
fix: Home Assisant: set state class to `measurement` for `illuminane_…
Koenkk Jan 4, 2026
8eba575
fix(ignore): update zigbee-herdsman-converters to 25.100.0 (#30499)
Koenkk Jan 4, 2026
0b67084
fix(ignore): bump @biomejs/biome from 2.3.10 to 2.3.11 in the minor-p…
dependabot[bot] Jan 5, 2026
c49c6d2
fix(ignore): update zigbee-herdsman-converters to 25.101.0 (#30520)
Koenkk Jan 5, 2026
3d7b6aa
fix(ignore): update zigbee-herdsman-converters to 25.102.0 (#30537)
Koenkk Jan 6, 2026
bf9ecb7
fix(ignore): update zigbee-herdsman-converters to 25.103.0 (#30552)
Koenkk Jan 7, 2026
2950648
fix: Home Assistant: mark `load_estimate` as `state_class` `measureme…
Koenkk Jan 8, 2026
72a0a2a
fix(ignore): update zigbee-herdsman-converters to 25.104.0 (#30564)
Koenkk Jan 8, 2026
a7c1d0d
fix(ignore): update zigbee-herdsman-converters to 25.105.0 (#30605)
Koenkk Jan 11, 2026
2b9c76b
fix(ignore): bump the minor-patch group with 2 updates (#30617)
dependabot[bot] Jan 12, 2026
99aa7c5
fix(ignore): update zigbee-herdsman-converters to 25.106.0 (#30631)
Koenkk Jan 13, 2026
f5e850a
fix(ignore): update zigbee-herdsman to 8.0.3 (#30632)
Koenkk Jan 13, 2026
bf08e59
fix(ignore): update zigbee-herdsman-converters to 25.107.0 (#30662)
Koenkk Jan 15, 2026
5bf2018
fix(ignore): update zigbee-herdsman-converters to 25.108.0 (#30672)
Koenkk Jan 16, 2026
d7af81d
fix: Home Assistant: expose group settings override (#30627)
Nardol Jan 17, 2026
fdff0fe
fix: Home Assistant: add `gas` device class (#30653)
IgnacioHR Jan 18, 2026
d44d0bb
fix(ignore): update zigbee-herdsman-converters to 25.109.0 (#30709)
Koenkk Jan 18, 2026
8703f67
fix(ignore): bump @types/node from 24.10.7 to 24.10.9 in the minor-pa…
dependabot[bot] Jan 20, 2026
208182f
fix(ignore): update zigbee-herdsman to 8.1.0 (#30725)
Koenkk Jan 20, 2026
103adfd
fix: Home Assistant: treat `Area1-4Occupancy` as `occupancy` (#30712)
rohankapoorcom Jan 20, 2026
9a9966e
fix(ignore): update zigbee-herdsman-converters to 25.110.0 (#30726)
Koenkk Jan 20, 2026
5c10e31
fix(ignore): update zigbee-herdsman-converters to 25.111.0 (#30739)
Koenkk Jan 21, 2026
8d4ce91
fix(ignore): Replace multiple area occupancy fields with camelCase in…
rohankapoorcom Jan 23, 2026
a1335fa
fix(ignore): update zigbee-herdsman-converters to 25.112.0 (#30767)
Koenkk Jan 23, 2026
ee1c18f
fix(ignore): update zigbee-herdsman to 9.0.0 (#30787)
Koenkk Jan 24, 2026
9e9d7af
fix: Home Assistant: Use `temperature_delta` for calibration (#30784)
burmistrzak Jan 24, 2026
c77fb35
fix(ignore): update zigbee-herdsman to 9.0.1 (#30788)
Koenkk Jan 24, 2026
a585d11
feat: Improve OTA (#30566)
Nerivec Jan 24, 2026
be42ec0
fix(ignore): update zigbee-herdsman-converters to 25.113.0 (#30789)
Koenkk Jan 24, 2026
7858f6b
fix(ignore): bump the minor-patch group with 2 updates (#30790)
dependabot[bot] Jan 24, 2026
2af9869
fix(ignore): update zigbee-herdsman-converters to 25.114.0 (#30803)
Koenkk Jan 25, 2026
8052a2d
fix(ignore): bump @biomejs/biome from 2.3.12 to 2.3.13 in the minor-p…
dependabot[bot] Jan 26, 2026
a199fc6
fix: Network map: escape double-quotes and backslashes in device attr…
stephanGarland Jan 27, 2026
1c8d8ce
fix(ignore): update zigbee-herdsman to 9.0.2
Koenkk Jan 27, 2026
4a00aee
fix: OTA availability detection (#30815)
Nerivec Jan 27, 2026
04df181
fix(ignore): update zigbee-herdsman-converters to 25.115.0 (#30826)
Koenkk Jan 27, 2026
0ca051a
fix(ignore): bump zigbee2mqtt-windfront in the minor-patch group
dependabot[bot] Jan 27, 2026
546a5da
fix: Home Assistant: discover temperature sensor for thermostats (#30…
burmistrzak Jan 28, 2026
b732057
fix(ignore): update zigbee-herdsman-converters to 25.116.0 (#30839)
Koenkk Jan 28, 2026
d71916c
fix: Home Assistant: Change `device_class` of `eco2` to `volatile_org…
burmistrzak Jan 29, 2026
4db1052
fix(ignore): update zigbee-herdsman-converters to 25.117.0 (#30849)
Koenkk Jan 29, 2026
7a14c9f
fix(ignore): update zigbee-herdsman-converters to 25.118.0 (#30865)
Koenkk Jan 30, 2026
83f7973
fix(ignore): update zigbee-herdsman-converters to 25.119.0 (#30874)
Koenkk Jan 31, 2026
908ae4a
fix(ignore): update zigbee-herdsman-converters to 25.120.0 (#30876)
Koenkk Jan 31, 2026
c9f096d
fix(ignore): bump zigbee2mqtt-windfront from 2.8.0 to 2.8.1 in the mi…
dependabot[bot] Feb 1, 2026
f9b473c
chore(dev): release 2.8.0 (#30420)
Koenkk Feb 1, 2026
96736d4
chore: promote to dev
github-actions[bot] Feb 1, 2026
855460a
fix(ignore): update zigbee-herdsman-converters to 25.121.0 (#30898)
Koenkk Feb 1, 2026
06f36f6
fix: Home Assistant: discover `temperature_probe` as `temperature` `d…
Koenkk Feb 2, 2026
f58e76a
fix(ignore): bump mqtt from 5.14.1 to 5.15.0 in the minor-patch group…
dependabot[bot] Feb 2, 2026
9bb1c7c
chore: readme: update integration logos and add links (#30926)
andrei-lazarov Feb 3, 2026
a665a38
fix(ignore): update zigbee-herdsman-converters to 25.122.0 (#30935)
Koenkk Feb 3, 2026
49fa35e
updates
Koenkk Feb 3, 2026
c85f799
Merge remote-tracking branch 'origin/dev' into fix/configure-key
Koenkk Feb 3, 2026
65fa998
Fixes
Koenkk Feb 3, 2026
5050a8c
Apply suggestion from @Nerivec
Koenkk Feb 5, 2026
dfea192
feedback
Koenkk Feb 5, 2026
dc750b0
Merge branch 'deps/zigbee-herdsman-converters' into fix/configure-key
Koenkk Feb 5, 2026
43d24af
u
Koenkk Feb 5, 2026
63bcd41
Merge branch 'deps/zigbee-herdsman-converters' into fix/configure-key
Koenkk Feb 5, 2026
a897700
fix
Koenkk Feb 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions lib/extension/configure.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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") {
Comment thread
Koenkk marked this conversation as resolved.
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;
}
}
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion test/extensions/bind.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
54 changes: 51 additions & 3 deletions test/extensions/configure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand All @@ -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();
Expand All @@ -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 => {
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion test/extensions/otaUpdate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"});
Expand Down
Loading