zigbee-herdsman-converters 25.10.0 → 25.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [25.11.0](https://github.com/Koenkk/zigbee-herdsman-converters/compare/v25.10.0...v25.11.0) (2025-08-28)
4
+
5
+
6
+ ### Features
7
+
8
+ * **add:** AE 287 C ([#9864](https://github.com/Koenkk/zigbee-herdsman-converters/issues/9864)) ([5f927fd](https://github.com/Koenkk/zigbee-herdsman-converters/commit/5f927fd292fbba0953c5a637002d7ffe952489bb))
9
+ * **add:** Drivent ([#9874](https://github.com/Koenkk/zigbee-herdsman-converters/issues/9874)) ([c8dcb6f](https://github.com/Koenkk/zigbee-herdsman-converters/commit/c8dcb6f2bedef654698bd2840beaaf79005d596d))
10
+ * **add:** m5NanoC6 ([#9866](https://github.com/Koenkk/zigbee-herdsman-converters/issues/9866)) ([95ca5db](https://github.com/Koenkk/zigbee-herdsman-converters/commit/95ca5db499581c2687ec830e1f98fa5a2ae3e055))
11
+ * Bosch `BSP-FZ2` (Plug compact II): Support reset of energy meter and lower min value change on electricityMeter reporting ([#9865](https://github.com/Koenkk/zigbee-herdsman-converters/issues/9865)) ([0615f2d](https://github.com/Koenkk/zigbee-herdsman-converters/commit/0615f2d6999ab011ef22b7ee9414ae1181b6df24))
12
+ * Onokom: various improvements ([#9869](https://github.com/Koenkk/zigbee-herdsman-converters/issues/9869)) ([15acfc4](https://github.com/Koenkk/zigbee-herdsman-converters/commit/15acfc4f8e148e5b09546541608e2c1822ee8ec4))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * Create inovelliMMWave modern extend to relocate mmWave commands and support future expansion ([#9870](https://github.com/Koenkk/zigbee-herdsman-converters/issues/9870)) ([a88b08c](https://github.com/Koenkk/zigbee-herdsman-converters/commit/a88b08ca0093d38d9bffeeecd9ad55b5cfbc793f))
18
+ * **detect:** Detect `_TZ3000_fawk5xjv` and `_TZ3000_ok0ggpk7` as a Detect _TZ3000_fawk5xjv and _TZ3000_ok0ggpk7 as a TS0003_switch_3_gang_with_backlight ([#9861](https://github.com/Koenkk/zigbee-herdsman-converters/issues/9861)) ([1b539d2](https://github.com/Koenkk/zigbee-herdsman-converters/commit/1b539d2a9309432fcaf34236feddc523e56027a0))
19
+ * **detect:** Detect `_TZE200_jfw0a4aa` as ZG-102ZM and `_TZE200_hdih4foa` as ZG-204ZH ([#9872](https://github.com/Koenkk/zigbee-herdsman-converters/issues/9872)) ([8437961](https://github.com/Koenkk/zigbee-herdsman-converters/commit/8437961b762ce769cd10fadd0dd2a731aac2a5ed))
20
+ * **detect:** Detect `_TZE284_1lvln0x6` as iHsenso_TS0601_human_presence https://github.com/Koenkk/zigbee2mqtt/issues/28398 ([b60f84f](https://github.com/Koenkk/zigbee-herdsman-converters/commit/b60f84fd14036c12a380f6f04e2b91681c2d5ec0))
21
+ * **detect:** Detect `lumi.light.agl002` as Aqara T2_E26 https://github.com/Koenkk/zigbee2mqtt/issues/26182 ([e221d02](https://github.com/Koenkk/zigbee-herdsman-converters/commit/e221d023ec8d188c4f25ba3b19bdd87c0154b3a0))
22
+ * **ignore:** Bosch `BMCT-SLZ` (Light/shutter control unit II): Only expose attributes compatible with the selected switch type ([#9862](https://github.com/Koenkk/zigbee-herdsman-converters/issues/9862)) ([7eecc4e](https://github.com/Koenkk/zigbee-herdsman-converters/commit/7eecc4e751812a27ce65f38565199dcd63cac809))
23
+
3
24
  ## [25.10.0](https://github.com/Koenkk/zigbee-herdsman-converters/compare/v25.9.0...v25.10.0) (2025-08-27)
4
25
 
5
26
 
@@ -1 +1 @@
1
- {"version":3,"file":"bosch.d.ts","sourceRoot":"","sources":["../../src/devices/bosch.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,oBAAoB,EAAyC,MAAM,cAAc,CAAC;AAk3C/F,eAAO,MAAM,WAAW,EAAE,oBAAoB,EAwoC7C,CAAC"}
1
+ {"version":3,"file":"bosch.d.ts","sourceRoot":"","sources":["../../src/devices/bosch.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,oBAAoB,EAA6C,MAAM,cAAc,CAAC;AA44CnG,eAAO,MAAM,WAAW,EAAE,oBAAoB,EAmsC7C,CAAC"}
@@ -891,7 +891,12 @@ const boschExtend = {
891
891
  }
892
892
  }
893
893
  if (data.switchType !== undefined) {
894
- result.switch_type = Object.keys(stateSwitchType).find((key) => stateSwitchType[key] === msg.data.switchType);
894
+ const switchType = msg.data.switchType;
895
+ result.switch_type = Object.keys(stateSwitchType).find((key) => stateSwitchType[key] === switchType);
896
+ if (switchType !== meta.device.meta.switchType) {
897
+ meta.device.meta.switchType = switchType;
898
+ meta.deviceExposesChanged();
899
+ }
895
900
  }
896
901
  if (data.switchMode !== undefined) {
897
902
  const property = utils.postfixWithEndpointName("switch_mode", msg, model, meta);
@@ -964,8 +969,23 @@ const boschExtend = {
964
969
  return { state: { device_mode: value } };
965
970
  }
966
971
  if (key === "switch_type") {
967
- const index = utils.getFromLookup(value, stateSwitchType);
968
- await entity.write("boschSpecific", { switchType: index });
972
+ const applyDefaultForSwitchModeAndChildLock = async (endpoint) => {
973
+ const switchModeDefault = utils.getFromLookup("coupled", stateSwitchMode);
974
+ const childLockDefault = utils.getFromLookup("OFF", stateOffOn);
975
+ await endpoint.write("boschSpecific", {
976
+ switchMode: switchModeDefault,
977
+ childLock: childLockDefault,
978
+ });
979
+ await endpoint.read("boschSpecific", ["switchMode", "childLock"]);
980
+ };
981
+ const switchType = utils.getFromLookup(value, stateSwitchType);
982
+ await entity.write("boschSpecific", { switchType: switchType });
983
+ await entity.read("boschSpecific", ["switchType"]);
984
+ await applyDefaultForSwitchModeAndChildLock(entity);
985
+ const leftEndpoint = meta.device.getEndpoint(2);
986
+ await applyDefaultForSwitchModeAndChildLock(leftEndpoint);
987
+ const rightEndpoint = meta.device.getEndpoint(3);
988
+ await applyDefaultForSwitchModeAndChildLock(rightEndpoint);
969
989
  return { state: { switch_type: value } };
970
990
  }
971
991
  if (key === "switch_mode") {
@@ -1878,7 +1898,17 @@ exports.definitions = [
1878
1898
  model: "BSP-FZ2",
1879
1899
  vendor: "Bosch",
1880
1900
  description: "Plug compact EU",
1881
- extend: [m.onOff(), m.electricityMeter({ voltage: false, current: false })],
1901
+ extend: [
1902
+ m.onOff(),
1903
+ m.electricityMeter({
1904
+ voltage: false,
1905
+ current: false,
1906
+ power: { change: 1 },
1907
+ energy: { change: 1 },
1908
+ }),
1909
+ boschExtend.seMeteringCluster(),
1910
+ boschExtend.resetEnergyReading(),
1911
+ ],
1882
1912
  ota: true,
1883
1913
  whiteLabel: [
1884
1914
  { vendor: "Bosch", model: "BSP-EZ2", description: "Plug compact FR", fingerprint: [{ modelID: "RBSH-SP-ZB-FR" }] },
@@ -2100,106 +2130,119 @@ exports.definitions = [
2100
2130
  only_short_press_decoupled: 0x02,
2101
2131
  only_long_press_decoupled: 0x03,
2102
2132
  };
2103
- const commonExposes = [
2104
- e.enum("switch_type", ea.ALL, Object.keys(stateSwitchType)).withDescription("Module controlled by a rocker switch or a button"),
2105
- e.action([
2106
- "press_released_left",
2107
- "press_released_right",
2108
- "hold_left",
2109
- "hold_right",
2110
- "hold_released_left",
2111
- "hold_released_right",
2112
- "opened_left",
2113
- "opened_right",
2114
- "closed_left",
2115
- "closed_right",
2116
- ]),
2117
- e.action_duration(),
2118
- ];
2119
- const lightExposes = [
2120
- e.switch().withEndpoint("left"),
2121
- e.switch().withEndpoint("right"),
2122
- e.power_on_behavior().withEndpoint("left"),
2123
- e.power_on_behavior().withEndpoint("right"),
2124
- e
2125
- .enum("switch_mode", ea.ALL, Object.keys(stateSwitchMode))
2126
- .withEndpoint("left")
2127
- .withDescription("Decouple the switch from the corresponding output to use it for other purposes. Please keep in mind that not all options may work depending on your switch type."),
2128
- e
2129
- .enum("switch_mode", ea.ALL, Object.keys(stateSwitchMode))
2130
- .withEndpoint("right")
2131
- .withDescription("Decouple the switch from the corresponding output to use it for other purposes. Please keep in mind that not all options may work depending on your switch type."),
2132
- e
2133
- .binary("auto_off_enabled", ea.ALL, "ON", "OFF")
2134
- .withEndpoint("left")
2135
- .withDescription("Enable/Disable the automatic turn-off feature"),
2136
- e
2133
+ const commonExposes = (switchType) => {
2134
+ const exposeList = [];
2135
+ exposeList.push(e.enum("switch_type", ea.ALL, Object.keys(stateSwitchType)).withDescription("Module controlled by a rocker switch or a button"));
2136
+ if (switchType !== "none") {
2137
+ let supportedActionTypes;
2138
+ switch (switchType) {
2139
+ case "button":
2140
+ case "button_key_change":
2141
+ supportedActionTypes = [
2142
+ "press_released_left",
2143
+ "press_released_right",
2144
+ "hold_left",
2145
+ "hold_right",
2146
+ "hold_released_left",
2147
+ "hold_released_right",
2148
+ ];
2149
+ break;
2150
+ case "rocker_switch":
2151
+ case "rocker_switch_key_change":
2152
+ supportedActionTypes = ["opened_left", "opened_right", "closed_left", "closed_right"];
2153
+ break;
2154
+ }
2155
+ exposeList.push(e.action(supportedActionTypes), e.action_duration());
2156
+ }
2157
+ return exposeList;
2158
+ };
2159
+ const lightExposes = (endpoint, switchType) => {
2160
+ const exposeList = [];
2161
+ exposeList.push(e.switch().withEndpoint(endpoint), e.power_on_behavior().withEndpoint(endpoint), e
2137
2162
  .binary("auto_off_enabled", ea.ALL, "ON", "OFF")
2138
- .withEndpoint("right")
2139
- .withDescription("Enable/Disable the automatic turn-off feature"),
2140
- e
2163
+ .withEndpoint(endpoint)
2164
+ .withDescription("Enable/Disable the automatic turn-off feature"), e
2141
2165
  .numeric("auto_off_time", ea.ALL)
2142
2166
  .withValueMin(0)
2143
2167
  .withValueMax(720)
2144
2168
  .withValueStep(1)
2145
2169
  .withUnit("min")
2146
2170
  .withDescription("Turn off the output after the specified amount of time. Only in action when the automatic turn-off is enabled.")
2147
- .withEndpoint("left"),
2148
- e
2149
- .numeric("auto_off_time", ea.ALL)
2150
- .withValueMin(0)
2151
- .withValueMax(720)
2152
- .withValueStep(1)
2153
- .withUnit("min")
2154
- .withDescription("Turn off the output after the specified amount of time. Only in action when the automatic turn-off is enabled.")
2155
- .withEndpoint("right"),
2156
- e.binary("child_lock", ea.ALL, "ON", "OFF").withEndpoint("left").withDescription("Enable/Disable child lock"),
2157
- e.binary("child_lock", ea.ALL, "ON", "OFF").withEndpoint("right").withDescription("Enable/Disable child lock"),
2158
- ];
2159
- const coverExposes = [
2160
- e.cover_position(),
2161
- e.enum("motor_state", ea.STATE, Object.keys(stateMotor)).withDescription("Current shutter motor state"),
2162
- e.binary("child_lock", ea.ALL, "ON", "OFF").withDescription("Enable/Disable child lock"),
2163
- e
2164
- .enum("switch_mode", ea.ALL, Object.keys(stateSwitchMode).filter((switchMode) => switchMode === "coupled" || switchMode === "only_long_press_decoupled"))
2165
- .withDescription("Decouple the switch from the corresponding output to use it for other purposes. Please keep in mind that not all options may work depending on your switch type."),
2166
- e
2171
+ .withEndpoint(endpoint));
2172
+ if (switchType !== "none") {
2173
+ let supportedSwitchModes;
2174
+ switch (switchType) {
2175
+ case "button":
2176
+ case "button_key_change":
2177
+ supportedSwitchModes = Object.keys(stateSwitchMode);
2178
+ break;
2179
+ case "rocker_switch":
2180
+ case "rocker_switch_key_change":
2181
+ supportedSwitchModes = Object.keys(stateSwitchMode).filter((switchMode) => switchMode === "coupled" || switchMode === "decoupled");
2182
+ break;
2183
+ }
2184
+ exposeList.push(e
2185
+ .enum("switch_mode", ea.ALL, supportedSwitchModes)
2186
+ .withEndpoint(endpoint)
2187
+ .withDescription("Decouple the switch from the corresponding output to use it for other purposes. Please keep in mind that the available options depend on the used switch type."), e.binary("child_lock", ea.ALL, "ON", "OFF").withEndpoint(endpoint).withDescription("Enable/Disable child lock"));
2188
+ }
2189
+ return exposeList;
2190
+ };
2191
+ const coverExposes = (switchType) => {
2192
+ const exposeList = [];
2193
+ exposeList.push(e.cover_position(), e.enum("motor_state", ea.STATE, Object.keys(stateMotor)).withDescription("Current shutter motor state"), e
2167
2194
  .numeric("calibration_closing_time", ea.ALL)
2168
2195
  .withUnit("s")
2169
2196
  .withDescription("Calibrate shutter closing time")
2170
2197
  .withValueMin(1)
2171
2198
  .withValueMax(90)
2172
- .withValueStep(0.1),
2173
- e
2199
+ .withValueStep(0.1), e
2174
2200
  .numeric("calibration_opening_time", ea.ALL)
2175
2201
  .withUnit("s")
2176
2202
  .withDescription("Calibrate shutter opening time")
2177
2203
  .withValueMin(1)
2178
2204
  .withValueMax(90)
2179
- .withValueStep(0.1),
2180
- e
2205
+ .withValueStep(0.1), e
2181
2206
  .numeric("calibration_button_hold_time", ea.ALL)
2182
2207
  .withUnit("s")
2183
2208
  .withDescription("Time to hold for long press")
2184
2209
  .withValueMin(0.1)
2185
2210
  .withValueMax(2)
2186
- .withValueStep(0.1),
2187
- e
2211
+ .withValueStep(0.1), e
2188
2212
  .numeric("calibration_motor_start_delay", ea.ALL)
2189
2213
  .withUnit("s")
2190
2214
  .withDescription("Delay between command and motor start")
2191
2215
  .withValueMin(0)
2192
2216
  .withValueMax(20)
2193
- .withValueStep(0.1),
2194
- ];
2217
+ .withValueStep(0.1));
2218
+ if (switchType !== "none") {
2219
+ let supportedSwitchModes;
2220
+ switch (switchType) {
2221
+ case "button":
2222
+ case "button_key_change":
2223
+ supportedSwitchModes = Object.keys(stateSwitchMode).filter((switchMode) => switchMode === "coupled" || switchMode === "only_long_press_decoupled");
2224
+ break;
2225
+ case "rocker_switch":
2226
+ case "rocker_switch_key_change":
2227
+ supportedSwitchModes = Object.keys(stateSwitchMode).filter((switchMode) => switchMode === "coupled");
2228
+ break;
2229
+ }
2230
+ exposeList.push(e
2231
+ .enum("switch_mode", ea.ALL, supportedSwitchModes)
2232
+ .withDescription("Decouple the switch from the corresponding output to use it for other purposes. Please keep in mind that the available options depend on the used switch type."), e.binary("child_lock", ea.ALL, "ON", "OFF").withDescription("Enable/Disable child lock"));
2233
+ }
2234
+ return exposeList;
2235
+ };
2195
2236
  if (!utils.isDummyDevice(device)) {
2196
2237
  const deviceModeKey = device.getEndpoint(1).getClusterAttributeValue("boschSpecific", "deviceMode");
2197
2238
  const deviceMode = Object.keys(stateDeviceMode).find((key) => stateDeviceMode[key] === deviceModeKey);
2239
+ const switchTypeKey = device.getEndpoint(1).getClusterAttributeValue("boschSpecific", "switchType");
2240
+ const switchType = Object.keys(stateSwitchType).find((key) => stateSwitchType[key] === switchTypeKey);
2198
2241
  if (deviceMode === "light") {
2199
- return [...commonExposes, ...lightExposes];
2242
+ return [...commonExposes(switchType), ...lightExposes("left", switchType), ...lightExposes("right", switchType)];
2200
2243
  }
2201
2244
  if (deviceMode === "shutter") {
2202
- return [...commonExposes, ...coverExposes];
2245
+ return [...commonExposes(switchType), ...coverExposes(switchType)];
2203
2246
  }
2204
2247
  }
2205
2248
  return [e.enum("device_mode", ea.ALL, Object.keys(stateDeviceMode)).withDescription("Device mode")];