Compare commits

...
51 Commits
Author SHA1 Message Date
Koen Kanters d2d7ebeed9 chore(dev): release 2.1.2 (#26217) 2025-03-01 21:37:52 +01:00
Koen Kanters 9f72c5c455 fix(ignore): update zigbee-herdsman-converters to 23.2.0 (#26549) 2025-03-01 20:19:30 +00:00
Koen Kanters e050e209b0 fix: Fix Docker build hanging (#26547) 2025-03-01 21:13:30 +01:00
Koen Kanters 29d25aed66 fix: Make compatible with pnpm 10 (#26546) 2025-03-01 20:56:46 +01:00
Koen Kanters 063aba1b6c fix: Home Assistant: add brightness to supported_color_modes (#26545) 2025-03-01 20:11:41 +01:00
Tom Davis e8031efd2d fix: Add Home Assistant device class to external_temperature_input entity (#26535) 2025-03-01 17:43:30 +01:00
Koen Kanters 102857a7fe fix(ignore): update zigbee-herdsman-converters to 23.1.1 (#26510) 2025-02-26 06:57:43 +00:00
Koen Kanters db7b51ac80 fix(ignore): update zigbee-herdsman-converters to 23.1.0 (#26509) 2025-02-25 21:32:49 +00:00
Koen Kanters d2166f2f4f fix(ignore): update dependencies (#26478) 2025-02-24 21:31:56 +00:00
ghozandKoen Kanters 07145accba fix(ignore): Add publish to meta of toZigbee converters (#26490)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2025-02-24 22:29:00 +01:00
Koenkk 44f9fe7a14 fix(ignore): update zigbee-herdsman-converters to 23.0.0 2025-02-24 22:29:00 +01:00
Koen Kanters d522d2cd18 fix(ignore): remove obsolete @types/eslint__js 2025-02-24 22:21:55 +01:00
Koen Kanters 4e650b72cd fix(ignore): update zigbee-herdsman to 3.2.7 (#26498) 2025-02-24 19:45:59 +00:00
ghoz a6072adcd0 chore: exclude cache, editor tmp files (#26497) 2025-02-24 20:40:25 +01:00
Koen Kanters 0d193ebac2 Revert "chore: bump pnpm"
This reverts commit 24779e3476.
2025-02-23 10:05:39 +01:00
Koen Kanters ede1a470dd chore: bump node version in workflows 2025-02-22 21:09:34 +01:00
Koen Kanters 24779e3476 chore: bump pnpm 2025-02-22 21:07:31 +01:00
Koen Kanters 67e1a02525 fix(ignore): update zigbee-herdsman-converters to 22.2.0 (#26469) 2025-02-22 13:08:17 +00:00
Lorenz Brun 7ce5b581aa fix: Home Assistant: support speed-controlled fans (#24483) 2025-02-21 20:24:08 +01:00
Koen Kanters 40f41477e7 fix(ignore): update zigbee-herdsman-converters to 22.1.0 (#26445) 2025-02-20 12:42:13 +00:00
Koen Kanters 382c89c49e chore: fix changelog generator 2025-02-18 16:15:46 +01:00
Koen KantersandNerivec 7d63a9a0f2 fix(ignore): update zigbee-herdsman-converters to 22.0.1 (#26418)
Co-authored-by: Nerivec <62446222+Nerivec@users.noreply.github.com>
2025-02-18 14:50:01 +00:00
Koen Kanters 93af062a9b fix(ignore): update zigbee-herdsman-converters to 21.38.0 (#26400) 2025-02-17 13:36:53 +00:00
Koen Kanters 758c56647d fix(ignore): update dependencies (#26383) 2025-02-17 14:30:20 +01:00
FilipandFilip Vilicic 845e03e48a fix: Allow configuring number of folders of old logs to keep (#26398)
Co-authored-by: Filip Vilicic <kusefin@hotmail.com>
2025-02-17 14:04:39 +01:00
Koen Kanters dec5ca8b3a fix(ignore): update zigbee-herdsman-converters to 21.37.0 (#26367) 2025-02-14 20:09:39 +00:00
XS400DOHC 1e656c2114 fix: Home Assistant: add missing device_class for some current and power entities (#26324) 2025-02-13 17:52:27 +01:00
Koen Kanters ba76533c2f fix(ignore): update zigbee-herdsman-converters to 21.36.0 (#26333) 2025-02-12 20:41:22 +00:00
Koen Kanters 30d13d6e5e fix(ignore): update zigbee-herdsman-converters to 21.35.0 (#26305) 2025-02-10 20:46:28 +00:00
Koen Kanters 49fe147921 fix(ignore): update zigbee-herdsman to 3.2.6 (#26303) 2025-02-10 19:57:41 +00:00
Koen Kanters 7a0964ebc9 fix(ignore): update zigbee-herdsman-converters to 21.34.0 (#26285) 2025-02-09 20:18:19 +00:00
Rob Coleman b35cdc3474 fix: Fix HA MQTT dict entry indicating that an update is progress (#26267) 2025-02-09 14:59:08 +01:00
Evaldas Auryla 5e55ef0454 fix: Support FreeBSD for update.sh (#26261) 2025-02-09 14:50:36 +01:00
Koen Kanters 3e3cefff1b fix(ignore): update dependencies (#26266) 2025-02-09 14:48:11 +01:00
Koen Kanters 97c74852c9 fix(ignore): update zigbee-herdsman-converters to 21.33.0 (#26258) 2025-02-08 14:06:29 +00:00
Koen Kanters 8542b35706 fix(ignore): update zigbee-herdsman-converters to 21.32.0 (#26245) 2025-02-07 19:32:33 +00:00
ramon18 1eda69a50a fix: Home Assistant: add is_updating attribute (#26231) 2025-02-07 20:06:28 +01:00
github-actions[bot] 16cecd917e chore: promote to dev 2025-02-06 19:43:25 +00:00
Koen Kanters 1accb8b66b chore(dev): release 2.1.1 (#26135) 2025-02-06 20:33:58 +01:00
Koen Kanters a3682b5fc7 chore: fix update_dep 2025-02-06 20:31:47 +01:00
Koen Kanters cfea8b76e2 Update zigbee-herdsman-converters to 21.31.0 (#26216) 2025-02-06 19:23:29 +00:00
Koen Kanters 9e28818c53 Update zigbee-herdsman-converters to 21.30.0 (#26203) 2025-02-05 20:38:05 +00:00
Koen Kanters bfbbfcda37 Update zigbee-herdsman-converters to 21.29.0 (#26183) 2025-02-04 20:25:50 +00:00
Rohan KapoorandKoen Kanters e4e4f16ec8 fix: Rename internal_temperature to internalTemperature to correct typo (#26114)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
2025-02-03 20:09:24 +01:00
Koen Kanters 75c3c5e57f chore: Update release_please.yml 2025-02-02 21:11:51 +01:00
Koen Kanters 6a15328001 Update zigbee-herdsman-converters to 21.28.0 (#26134) 2025-02-02 20:08:59 +00:00
Koen Kanters b960775160 fix(ignore): update dependencies (#26126) 2025-02-02 15:06:40 +01:00
Koen Kanters 41ba32db49 chore: merge master to dev 2025-02-02 15:03:46 +01:00
Koen Kanters 83ff4a7684 chore: Add packageManager to package.json (#26106) 2025-02-02 15:03:26 +01:00
Koen Kanters 98b5a60886 chore: Add packageManager to package.json (#26106) 2025-02-01 22:14:03 +01:00
github-actions[bot] b34723db36 chore: promote to dev 2025-02-01 20:34:39 +00:00
29 changed files with 649 additions and 501 deletions
+1 -5
View File
@@ -20,12 +20,10 @@ jobs:
if: ((github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')) && github.event_name == 'push') == false
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
registry-url: https://registry.npmjs.org/
cache: pnpm
@@ -183,8 +181,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
- uses: googleapis/release-please-action@v4
id: release
+2 -4
View File
@@ -18,11 +18,9 @@ jobs:
ref: dev
token: ${{ secrets.GH_TOKEN }}
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: pnpm
- run: |
pnpm install ${{ github.event.client_payload.package }}@${{ github.event.client_payload.version }} --save-exact
@@ -32,7 +30,7 @@ jobs:
with:
commit-message: 'fix(ignore): update ${{ github.event.client_payload.package }} to ${{ github.event.client_payload.version }}'
branch: 'deps/${{ github.event.client_payload.package }}'
title: Update ${{ github.event.client_payload.package }} to ${{ github.event.client_payload.version }}
title: 'fix(ignore): update ${{ github.event.client_payload.package }} to ${{ github.event.client_payload.version }}'
token: ${{ secrets.GH_TOKEN }}
- run: sleep 5 # Otherwise pull request may not exist yet causing automerge to fail
- run: gh pr merge --squash --auto "${{ steps.cpr.outputs.pull-request-number }}"
+1 -3
View File
@@ -19,11 +19,9 @@ jobs:
ref: dev
token: ${{ secrets.GH_TOKEN }}
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: pnpm
- run: |
pnpm up --latest
+4
View File
@@ -45,6 +45,9 @@ typings/
# Optional npm cache directory
.npm
# Optional pnpm cache directory
.pnpm-store
# Optional eslint cache
.eslintcache
@@ -68,6 +71,7 @@ tsconfig.tsbuildinfo
# IDE specific folders
.idea
.*.swp
# Ignore config
data/*
+1 -1
View File
@@ -1,3 +1,3 @@
{
".": "2.1.0"
".": "2.1.2"
}
+45
View File
@@ -1,5 +1,50 @@
# Changelog
## [2.1.2](https://github.com/Koenkk/zigbee2mqtt/compare/2.1.1...2.1.2) (2025-03-01)
### Bug Fixes
* Add Home Assistant device class to external_temperature_input entity ([#26535](https://github.com/Koenkk/zigbee2mqtt/issues/26535)) ([e8031ef](https://github.com/Koenkk/zigbee2mqtt/commit/e8031efd2d95658c5f3fe72ee6e2f95dd584b5e8))
* Allow configuring number of folders of old logs to keep ([#26398](https://github.com/Koenkk/zigbee2mqtt/issues/26398)) ([845e03e](https://github.com/Koenkk/zigbee2mqtt/commit/845e03e48acf1367feadeaae986f3c987bbc164d))
* Fix Docker build hanging ([#26547](https://github.com/Koenkk/zigbee2mqtt/issues/26547)) ([e050e20](https://github.com/Koenkk/zigbee2mqtt/commit/e050e209b0d273cad6ad0efcf20761f33963da7b))
* Fix HA MQTT dict entry indicating that an update is progress ([#26267](https://github.com/Koenkk/zigbee2mqtt/issues/26267)) ([b35cdc3](https://github.com/Koenkk/zigbee2mqtt/commit/b35cdc347423b219722c9f9dd0d2a82ded8eb24f))
* Home Assistant: add `brightness` to `supported_color_modes` ([#26545](https://github.com/Koenkk/zigbee2mqtt/issues/26545)) ([063aba1](https://github.com/Koenkk/zigbee2mqtt/commit/063aba1b6c72901ed2d51a367485092691c358da))
* Home Assistant: add `is_updating` attribute ([#26231](https://github.com/Koenkk/zigbee2mqtt/issues/26231)) ([1eda69a](https://github.com/Koenkk/zigbee2mqtt/commit/1eda69a50a8f92c3471acdbdc82b41055d5992f2))
* Home Assistant: add missing `device_class` for some `current` and `power` entities ([#26324](https://github.com/Koenkk/zigbee2mqtt/issues/26324)) ([1e656c2](https://github.com/Koenkk/zigbee2mqtt/commit/1e656c2114d58b96fd7b7750e2e7d255a9175653))
* Home Assistant: support speed-controlled fans ([#24483](https://github.com/Koenkk/zigbee2mqtt/issues/24483)) ([7ce5b58](https://github.com/Koenkk/zigbee2mqtt/commit/7ce5b581aa57d828043a1ca75ef7efe7b7bf1619))
* **ignore:** Add `publish` to `meta` of toZigbee converters ([#26490](https://github.com/Koenkk/zigbee2mqtt/issues/26490)) ([07145ac](https://github.com/Koenkk/zigbee2mqtt/commit/07145accbae6c481f6d6740e66e27ab1baf5eb6d))
* **ignore:** remove obsolete @types/eslint__js ([d522d2c](https://github.com/Koenkk/zigbee2mqtt/commit/d522d2cd18b8cb77fa50cd457823cfa573622cb7))
* **ignore:** update dependencies ([#26266](https://github.com/Koenkk/zigbee2mqtt/issues/26266)) ([3e3ceff](https://github.com/Koenkk/zigbee2mqtt/commit/3e3cefff1b7f85f59b6bf529f6593339498561a1))
* **ignore:** update dependencies ([#26383](https://github.com/Koenkk/zigbee2mqtt/issues/26383)) ([758c566](https://github.com/Koenkk/zigbee2mqtt/commit/758c56647d353e81ea22a34c2fa2665ed76dc149))
* **ignore:** update dependencies ([#26478](https://github.com/Koenkk/zigbee2mqtt/issues/26478)) ([d2166f2](https://github.com/Koenkk/zigbee2mqtt/commit/d2166f2f4fa1e1e286face994ec4825a70144908))
* **ignore:** update zigbee-herdsman to 3.2.6 ([#26303](https://github.com/Koenkk/zigbee2mqtt/issues/26303)) ([49fe147](https://github.com/Koenkk/zigbee2mqtt/commit/49fe1479213c928786c64adeb3031ca6fe91250d))
* **ignore:** update zigbee-herdsman to 3.2.7 ([#26498](https://github.com/Koenkk/zigbee2mqtt/issues/26498)) ([4e650b7](https://github.com/Koenkk/zigbee2mqtt/commit/4e650b72cd187488893213018b619e933835a58e))
* **ignore:** update zigbee-herdsman-converters to 21.32.0 ([#26245](https://github.com/Koenkk/zigbee2mqtt/issues/26245)) ([8542b35](https://github.com/Koenkk/zigbee2mqtt/commit/8542b35706cefc87c9ec9dccb2980302ea25f100))
* **ignore:** update zigbee-herdsman-converters to 21.33.0 ([#26258](https://github.com/Koenkk/zigbee2mqtt/issues/26258)) ([97c7485](https://github.com/Koenkk/zigbee2mqtt/commit/97c74852c95536945e33d0388dc5fcd0b132cd7e))
* **ignore:** update zigbee-herdsman-converters to 21.34.0 ([#26285](https://github.com/Koenkk/zigbee2mqtt/issues/26285)) ([7a0964e](https://github.com/Koenkk/zigbee2mqtt/commit/7a0964ebc905903b4ca5b168d9bd1041b004b4cf))
* **ignore:** update zigbee-herdsman-converters to 21.35.0 ([#26305](https://github.com/Koenkk/zigbee2mqtt/issues/26305)) ([30d13d6](https://github.com/Koenkk/zigbee2mqtt/commit/30d13d6e5ee9678f7da812bd287128824a535d48))
* **ignore:** update zigbee-herdsman-converters to 21.36.0 ([#26333](https://github.com/Koenkk/zigbee2mqtt/issues/26333)) ([ba76533](https://github.com/Koenkk/zigbee2mqtt/commit/ba76533c2f241c8362f43ad07d10b2fe084479a0))
* **ignore:** update zigbee-herdsman-converters to 21.37.0 ([#26367](https://github.com/Koenkk/zigbee2mqtt/issues/26367)) ([dec5ca8](https://github.com/Koenkk/zigbee2mqtt/commit/dec5ca8b3a3703e6289652192657af9a035fe026))
* **ignore:** update zigbee-herdsman-converters to 21.38.0 ([#26400](https://github.com/Koenkk/zigbee2mqtt/issues/26400)) ([93af062](https://github.com/Koenkk/zigbee2mqtt/commit/93af062a9b84358c866a5a1191ae5895fc6e866f))
* **ignore:** update zigbee-herdsman-converters to 22.0.1 ([#26418](https://github.com/Koenkk/zigbee2mqtt/issues/26418)) ([7d63a9a](https://github.com/Koenkk/zigbee2mqtt/commit/7d63a9a0f29445044bcfe0f3a4b629266db37654))
* **ignore:** update zigbee-herdsman-converters to 22.1.0 ([#26445](https://github.com/Koenkk/zigbee2mqtt/issues/26445)) ([40f4147](https://github.com/Koenkk/zigbee2mqtt/commit/40f41477e776b4e75434251d03bf2844fceb7b13))
* **ignore:** update zigbee-herdsman-converters to 22.2.0 ([#26469](https://github.com/Koenkk/zigbee2mqtt/issues/26469)) ([67e1a02](https://github.com/Koenkk/zigbee2mqtt/commit/67e1a0252517da28629a4c97b4dd610624d451a1))
* **ignore:** update zigbee-herdsman-converters to 23.0.0 ([44f9fe7](https://github.com/Koenkk/zigbee2mqtt/commit/44f9fe7a1494a9450e247ad353ce788c621f901c))
* **ignore:** update zigbee-herdsman-converters to 23.1.0 ([#26509](https://github.com/Koenkk/zigbee2mqtt/issues/26509)) ([db7b51a](https://github.com/Koenkk/zigbee2mqtt/commit/db7b51ac801829801656d978aff2605d8bd7b56a))
* **ignore:** update zigbee-herdsman-converters to 23.1.1 ([#26510](https://github.com/Koenkk/zigbee2mqtt/issues/26510)) ([102857a](https://github.com/Koenkk/zigbee2mqtt/commit/102857a7fec60e3f65887d92b6fe7a2d81add110))
* **ignore:** update zigbee-herdsman-converters to 23.2.0 ([#26549](https://github.com/Koenkk/zigbee2mqtt/issues/26549)) ([9f72c5c](https://github.com/Koenkk/zigbee2mqtt/commit/9f72c5c4555bda5b347a6a5406f619b9668813ec))
* Make compatible with pnpm 10 ([#26546](https://github.com/Koenkk/zigbee2mqtt/issues/26546)) ([29d25ae](https://github.com/Koenkk/zigbee2mqtt/commit/29d25aed66a66912fb55ede8751ba8056efb673f))
* Support FreeBSD for `update.sh` ([#26261](https://github.com/Koenkk/zigbee2mqtt/issues/26261)) ([5e55ef0](https://github.com/Koenkk/zigbee2mqtt/commit/5e55ef045427f78b410e3d292387c3592366f698))
## [2.1.1](https://github.com/Koenkk/zigbee2mqtt/compare/2.1.0...2.1.1) (2025-02-06)
### Bug Fixes
* **ignore:** update dependencies ([#26126](https://github.com/Koenkk/zigbee2mqtt/issues/26126)) ([b960775](https://github.com/Koenkk/zigbee2mqtt/commit/b960775160b33dcd276376efaa7dc1ca3f791a53))
* Rename `internal_temperature` to `internalTemperature` to correct typo ([#26114](https://github.com/Koenkk/zigbee2mqtt/issues/26114)) ([e4e4f16](https://github.com/Koenkk/zigbee2mqtt/commit/e4e4f16ec8994a63ba148b36d7e18a09f49ac298))
## [2.1.0](https://github.com/Koenkk/zigbee2mqtt/compare/2.0.0...2.1.0) (2025-02-01)
+1 -1
View File
@@ -20,7 +20,7 @@ FROM base AS deps
COPY package.json pnpm-lock.yaml ./
# Make and such are needed to compile serialport for riscv64
RUN apk add make gcc g++ python3 linux-headers npm && \
npm install -g pnpm && \
npm install -g pnpm@10.4.1 && \
pnpm install --frozen-lockfile --no-optional && \
# serialport has outdated prebuilds that appear to fail on some archs, force build on target platform
rm -rf `find ./node_modules/.pnpm/ -wholename "*/@serialport/bindings-cpp/prebuilds" -type d` && \
+2
View File
@@ -243,6 +243,8 @@ export default class Availability extends Extension {
options,
state,
device: device.zh,
/* v8 ignore next */
publish: (payload: KeyValue) => this.publishEntityState(device, payload),
};
try {
+5 -8
View File
@@ -1,11 +1,11 @@
import type * as zhc from 'zigbee-herdsman-converters';
import {addDefinition, removeExternalDefinitions} from 'zigbee-herdsman-converters';
import {addExternalDefinition, removeExternalDefinitions} from 'zigbee-herdsman-converters';
import logger from '../util/logger';
import ExternalJSExtension from './externalJS';
type ModuleExports = zhc.Definition | zhc.Definition[];
type ModuleExports = zhc.ExternalDefinitionWithExtend | zhc.ExternalDefinitionWithExtend[];
export default class ExternalConverters extends ExternalJSExtension<ModuleExports> {
constructor(
@@ -43,10 +43,11 @@ export default class ExternalConverters extends ExternalJSExtension<ModuleExport
try {
removeExternalDefinitions(name);
for (const definition of this.getDefinitions(module)) {
const definitions = Array.isArray(module) ? module : [module];
for (const definition of definitions) {
definition.externalConverterName = name;
addDefinition(definition);
addExternalDefinition(definition);
logger.info(`Loaded external converter '${name}'.`);
}
@@ -61,8 +62,4 @@ export default class ExternalConverters extends ExternalJSExtension<ModuleExport
throw error;
}
}
private getDefinitions(module: ModuleExports): zhc.Definition[] {
return Array.isArray(module) ? module : [module];
}
}
+43 -21
View File
@@ -1,10 +1,10 @@
import type * as zhc from 'zigbee-herdsman-converters';
import assert from 'node:assert';
import bind from 'bind-decorator';
import stringify from 'json-stable-stringify-without-jsonify';
import * as zhc from 'zigbee-herdsman-converters';
import logger from '../util/logger';
import * as settings from '../util/settings';
import utils, {assertBinaryExpose, assertEnumExpose, assertNumericExpose, isBinaryExpose, isEnumExpose, isNumericExpose} from '../util/utils';
@@ -170,7 +170,7 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
eco2: {device_class: 'carbon_dioxide', state_class: 'measurement'},
eco_temperature: {entity_category: 'config', icon: 'mdi:thermometer'},
energy: {device_class: 'energy', state_class: 'total_increasing'},
external_temperature_input: {icon: 'mdi:thermometer'},
external_temperature_input: {device_class: 'temperature', icon: 'mdi:thermometer'},
formaldehyd: {state_class: 'measurement'},
flow: {device_class: 'volume_flow_rate', state_class: 'measurement'},
gas_density: {icon: 'mdi:google-circles-communities', state_class: 'measurement'},
@@ -181,7 +181,7 @@ const NUMERIC_DISCOVERY_LOOKUP: {[s: string]: KeyValue} = {
humidity_min: {entity_category: 'config', icon: 'mdi:water-percent'},
illuminance_calibration: {entity_category: 'config', icon: 'mdi:wrench-clock'},
illuminance: {device_class: 'illuminance', state_class: 'measurement'},
internal_temperature: {
internalTemperature: {
device_class: 'temperature',
entity_category: 'diagnostic',
state_class: 'measurement',
@@ -536,16 +536,13 @@ export default class HomeAssistant extends Extension {
},
};
const colorModes = [
discoveryEntry.discovery_payload.supported_color_modes = [
'brightness',
hasColorXY && !preferHS ? 'xy' : null,
(!hasColorXY || preferHS) && hasColorHS ? 'hs' : null,
hasColorTemp ? 'color_temp' : null,
].filter((c) => c);
if (colorModes.length) {
discoveryEntry.discovery_payload.supported_color_modes = colorModes;
}
if (hasColorTemp) {
const colorTemps = (exposes as zhc.Light[])
.map((expose) => expose.features.find((e) => e.name === 'color_temp'))
@@ -872,15 +869,17 @@ export default class HomeAssistant extends Extension {
discovery_payload: {
name: null,
state_topic: true,
state_value_template: '{{ value_json.fan_state }}',
command_topic: true,
command_topic_postfix: 'fan_state',
},
};
const speed = (firstExpose as zhc.Fan).features.filter(isEnumExpose).find((e) => e.name === 'mode');
const modeEmulatedSpeed = (firstExpose as zhc.Fan).features.filter(isEnumExpose).find((e) => e.name === 'mode');
const nativeSpeed = (firstExpose as zhc.Fan).features.filter(isNumericExpose).find((e) => e.name === 'speed');
if (speed) {
// Exactly one mode needs to be active (logical xor)
assert(!modeEmulatedSpeed != !nativeSpeed, 'Fans need to be either mode- or speed-controlled');
if (modeEmulatedSpeed) {
// A fan entity in Home Assistant 2021.3 and above may have a speed,
// controlled by a percentage from 1 to 100, and/or non-speed presets.
// The MQTT Fan integration allows the speed percentage to be mapped
@@ -894,9 +893,9 @@ export default class HomeAssistant extends Extension {
// ZCL. This supports a generic ZCL HVAC Fan Control fan. "Off" is
// always a valid speed.
let speeds = ['off'].concat(
['low', 'medium', 'high', '1', '2', '3', '4', '5', '6', '7', '8', '9'].filter((s) => speed.values.includes(s)),
['low', 'medium', 'high', '1', '2', '3', '4', '5', '6', '7', '8', '9'].filter((s) => modeEmulatedSpeed.values.includes(s)),
);
let presets = ['on', 'auto', 'smart'].filter((s) => speed.values.includes(s));
let presets = ['on', 'auto', 'smart'].filter((s) => modeEmulatedSpeed.values.includes(s));
if (['99432'].includes(definition!.model)) {
// The Hampton Bay 99432 fan implements 4 speeds using the ZCL
@@ -908,22 +907,37 @@ export default class HomeAssistant extends Extension {
}
const allowed = [...speeds, ...presets];
speed.values.forEach((s) => assert(allowed.includes(s.toString())));
modeEmulatedSpeed.values.forEach((s) => assert(allowed.includes(s.toString())));
const percentValues = speeds.map((s, i) => `'${s}':${i}`).join(', ');
const percentCommands = speeds.map((s, i) => `${i}:'${s}'`).join(', ');
const presetList = presets.map((s) => `'${s}'`).join(', ');
discoveryEntry.discovery_payload.percentage_state_topic = true;
discoveryEntry.discovery_payload.percentage_command_topic = true;
discoveryEntry.discovery_payload.percentage_value_template = `{{ {${percentValues}}[value_json.${speed.property}] | default('None') }}`;
discoveryEntry.discovery_payload.percentage_command_topic = 'fan_mode';
discoveryEntry.discovery_payload.percentage_value_template = `{{ {${percentValues}}[value_json.${modeEmulatedSpeed.property}] | default('None') }}`;
discoveryEntry.discovery_payload.percentage_command_template = `{{ {${percentCommands}}[value] | default('') }}`;
discoveryEntry.discovery_payload.speed_range_min = 1;
discoveryEntry.discovery_payload.speed_range_max = speeds.length - 1;
assert(presets.length !== 0);
discoveryEntry.discovery_payload.preset_mode_state_topic = true;
discoveryEntry.discovery_payload.preset_mode_command_topic = 'fan_mode';
discoveryEntry.discovery_payload.preset_mode_value_template = `{{ value_json.${speed.property} if value_json.${speed.property} in [${presetList}] else 'None' | default('None') }}`;
discoveryEntry.discovery_payload.preset_mode_value_template = `{{ value_json.${modeEmulatedSpeed.property} if value_json.${modeEmulatedSpeed.property} in [${presetList}] else 'None' | default('None') }}`;
discoveryEntry.discovery_payload.preset_modes = presets;
// Emulate state based on mode
discoveryEntry.discovery_payload.state_value_template = '{{ value_json.fan_state }}';
discoveryEntry.discovery_payload.command_topic_postfix = 'fan_state';
} else if (nativeSpeed) {
discoveryEntry.discovery_payload.percentage_state_topic = true;
discoveryEntry.discovery_payload.percentage_command_topic = 'speed';
discoveryEntry.discovery_payload.percentage_value_template = `{{ value_json.${nativeSpeed.property} | default('None') }}`;
discoveryEntry.discovery_payload.percentage_command_template = `{{ value | default('') }}`;
discoveryEntry.discovery_payload.speed_range_min = nativeSpeed.value_min;
discoveryEntry.discovery_payload.speed_range_max = nativeSpeed.value_max;
// Speed-controlled fans generally have an onOff cluster, use that for state
discoveryEntry.discovery_payload.state_value_template = '{{ value_json.state }}';
discoveryEntry.discovery_payload.command_topic_postfix = 'state';
}
discoveryEntries.push(discoveryEntry);
@@ -1019,6 +1033,14 @@ export default class HomeAssistant extends Extension {
if (firstExpose.unit && ['Wh', 'kWh'].includes(firstExpose.unit)) {
Object.assign(extraAttrs, {device_class: 'energy', state_class: 'total_increasing'});
}
// If a variable includes A or mA, mark it as current
else if (firstExpose.unit && ['A', 'mA'].includes(firstExpose.unit)) {
Object.assign(extraAttrs, {device_class: 'current', state_class: 'measurement'});
}
// If a variable includes mW, W, kW mark it as power
else if (firstExpose.unit && ['mW', 'W', 'kW'].includes(firstExpose.unit)) {
Object.assign(extraAttrs, {device_class: 'power', state_class: 'measurement'});
}
let key = firstExpose.name;
@@ -1411,7 +1433,7 @@ export default class HomeAssistant extends Extension {
entity_category: 'config',
command_topic: `${settings.get().mqtt.base_topic}/bridge/request/device/ota_update/update`,
payload_install: `{"id": "${entity.ieeeAddr}"}`,
value_template: `{"latest_version":"{{ value_json['update']['latest_version'] }}","installed_version":"{{ value_json['update']['installed_version'] }}","update_percentage":{{ value_json['update'].get('progress', 'null') }}}`,
value_template: `{"latest_version":"{{ value_json['update']['latest_version'] }}","installed_version":"{{ value_json['update']['installed_version'] }}","update_percentage":{{ value_json['update'].get('progress', 'null') }},"in_progress":{{ (value_json['update']['state'] == 'updating')|lower }}}`,
},
};
configs.push(updateSensor);
@@ -1621,7 +1643,7 @@ export default class HomeAssistant extends Extension {
}
if (payload.percentage_command_topic) {
payload.percentage_command_topic = `${baseTopic}/${commandTopicPrefix}set/fan_mode`;
payload.percentage_command_topic = `${baseTopic}/${commandTopicPrefix}set/${payload.percentage_command_topic}`;
}
if (payload.preset_mode_state_topic) {
+2
View File
@@ -231,6 +231,8 @@ export default class Publish extends Extension {
state: entityState,
membersState,
mapped: definition,
/* v8 ignore next */
publish: (payload: KeyValue) => this.publishEntityState(re, payload),
};
// Strip endpoint name from meta.message properties.
+1
View File
@@ -178,6 +178,7 @@ declare global {
log_syslog: KeyValue;
log_debug_to_mqtt_frontend: boolean;
log_debug_namespace_ignore: string;
log_directories_to_keep: number;
pan_id: number | 'GENERATE';
ext_pan_id: number[] | 'GENERATE';
channel: number;
+1 -1
View File
@@ -232,7 +232,7 @@ class Logger {
});
directories.sort((a: KeyValue, b: KeyValue) => b.birth - a.birth);
directories = directories.slice(10, directories.length);
directories = directories.slice(settings.get().advanced.log_directories_to_keep, directories.length);
directories.forEach((dir) => {
this.debug(`Removing old log directory '${dir.path}'`);
rimrafSync(dir.path);
+8
View File
@@ -525,6 +525,14 @@
"default": "",
"examples": ["^zhc:legacy:fz:(tuya|moes)", "^zhc:legacy:fz:(tuya|moes)|^zh:ember:uart:|^zh:controller"]
},
"log_directories_to_keep": {
"type": "number",
"title": "Number of past log folders to keep",
"description": "Number of log directories to keep before deleting the oldest one",
"default": 10,
"minimum": 5,
"maximum": 1000
},
"log_syslog": {
"requiresRestart": true,
"oneOf": [
+1
View File
@@ -96,6 +96,7 @@ export const defaults: RecursivePartial<Settings> = {
log_syslog: {},
log_debug_to_mqtt_frontend: false,
log_debug_namespace_ignore: '',
log_directories_to_keep: 10,
pan_id: 0x1a62,
ext_pan_id: [0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd],
channel: 11,
+21 -15
View File
@@ -1,8 +1,9 @@
{
"name": "zigbee2mqtt",
"version": "2.1.0",
"version": "2.1.2",
"description": "Zigbee to MQTT bridge using Zigbee-herdsman",
"main": "index.js",
"packageManager": "pnpm@10.4.1",
"repository": {
"type": "git",
"url": "git+https://github.com/Koenkk/zigbee2mqtt.git"
@@ -54,44 +55,49 @@
"mqtt": "^5.10.3",
"object-assign-deep": "^0.4.0",
"rimraf": "^6.0.1",
"semver": "^7.6.3",
"semver": "^7.7.1",
"source-map-support": "^0.5.21",
"throttleit": "^2.1.0",
"winston": "^3.17.0",
"winston-syslog": "^2.7.1",
"winston-transport": "^4.9.0",
"ws": "^8.18.0",
"zigbee-herdsman": "3.2.5",
"zigbee-herdsman-converters": "21.27.1",
"ws": "^8.18.1",
"zigbee-herdsman": "3.2.7",
"zigbee-herdsman-converters": "23.2.0",
"zigbee2mqtt-frontend": "0.9.4"
},
"devDependencies": {
"@eslint/core": "^0.10.0",
"@eslint/js": "^9.19.0",
"@eslint/core": "^0.12.0",
"@eslint/js": "^9.21.0",
"@ianvs/prettier-plugin-sort-imports": "^4.4.1",
"@types/eslint__js": "^8.42.3",
"@types/finalhandler": "^1.2.3",
"@types/humanize-duration": "^3.27.4",
"@types/js-yaml": "^4.0.9",
"@types/node": "^22.10.10",
"@types/node": "^22.13.5",
"@types/object-assign-deep": "^0.4.3",
"@types/readable-stream": "4.0.18",
"@types/sd-notify": "^2.8.2",
"@types/serve-static": "^1.15.7",
"@types/ws": "8.5.14",
"@vitest/coverage-v8": "^3.0.4",
"eslint": "^9.19.0",
"@vitest/coverage-v8": "^3.0.7",
"eslint": "^9.21.0",
"eslint-config-prettier": "^10.0.1",
"prettier": "^3.4.2",
"prettier": "^3.5.2",
"tmp": "^0.2.3",
"typescript": "^5.7.3",
"typescript-eslint": "^8.21.0",
"vitest": "^3.0.4"
"typescript-eslint": "^8.25.0",
"vitest": "^3.0.7"
},
"pnpm": {
"overrides": {
"zigbee-herdsman": "$zigbee-herdsman"
}
},
"onlyBuiltDependencies": [
"@serialport/bindings-cpp",
"esbuild",
"sd-notify",
"unix-dgram"
]
},
"bin": {
"zigbee2mqtt": "cli.js"
+384 -409
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -49,7 +49,8 @@ if (fs.existsSync(commitUserFile)) {
commitUserLookup = JSON.parse(fs.readFileSync(commitUserFile, 'utf8'));
}
const whiteLabels = zhc.definitions.filter((d) => d.whiteLabel).flatMap((d) => d.whiteLabel);
const definitions = require('zigbee-herdsman-converters/devices/index').default.map((d) => zhc.prepareDefinition(d));
const whiteLabels = definitions.filter((d) => d.whiteLabel).flatMap((d) => d.whiteLabel);
const capitalizeFirstChar = (str) => str.charAt(0).toUpperCase() + str.slice(1);
for (const changelog of changelogs) {
@@ -97,7 +98,7 @@ for (const changelog of changelogs) {
if (localContext === 'add') {
for (const model of message.split(',')) {
const definition = zhc.definitions.find((d) => d.model === model.trim());
const definition = definitions.find((d) => d.model === model.trim());
const whiteLabel = whiteLabels.find((d) => d.model === model.trim());
const match = definition || whiteLabel;
if (match) {
+2
View File
@@ -122,6 +122,7 @@ describe('Extension: Bridge', () => {
log_rotation: true,
log_symlink_current: false,
log_syslog: {},
log_directories_to_keep: 10,
output: 'json',
pan_id: 6754,
timestamp_format: 'YYYY-MM-DD HH:mm:ss',
@@ -141,6 +142,7 @@ describe('Extension: Bridge', () => {
retain: false,
},
'0x000b57fffec6a5b7': {friendly_name: 'bulb_2', retain: false},
'0x00124b00cfcf3298': {friendly_name: 'fanbee', retain: true},
'0x0017880104a44559': {friendly_name: 'J1_cover'},
'0x0017880104e43559': {friendly_name: 'U202DST600ZB'},
'0x0017880104e44559': {friendly_name: '3157100_thermostat'},
+7 -7
View File
@@ -28,7 +28,7 @@ describe('Extension: ExternalConverters', () => {
const rmSyncSpy = vi.spyOn(fs, 'rmSync');
const writeFileSyncSpy = vi.spyOn(fs, 'writeFileSync');
const zhcAddDefinitionSpy = vi.spyOn(zhc, 'addDefinition');
const zhcAddExternalDefinitionSpy = vi.spyOn(zhc, 'addExternalDefinition');
const zhcRemoveExternalDefinitionsSpy = vi.spyOn(zhc, 'removeExternalDefinitions');
const mocksClear = [
@@ -43,7 +43,7 @@ describe('Extension: ExternalConverters', () => {
mkdirSyncSpy,
rmSyncSpy,
writeFileSyncSpy,
zhcAddDefinitionSpy,
zhcAddExternalDefinitionSpy,
zhcRemoveExternalDefinitionsSpy,
];
@@ -129,7 +129,7 @@ describe('Extension: ExternalConverters', () => {
expect(zhcRemoveExternalDefinitionsSpy).toHaveBeenCalledTimes(2);
expect(zhcRemoveExternalDefinitionsSpy).toHaveBeenNthCalledWith(1, 'mock-external-converter-multiple.js');
expect(zhcRemoveExternalDefinitionsSpy).toHaveBeenNthCalledWith(2, 'mock-external-converter.js');
expect(zhcAddDefinitionSpy).toHaveBeenNthCalledWith(
expect(zhcAddExternalDefinitionSpy).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
mock: 1,
@@ -139,7 +139,7 @@ describe('Extension: ExternalConverters', () => {
description: 'external_1',
}),
);
expect(zhcAddDefinitionSpy).toHaveBeenNthCalledWith(
expect(zhcAddExternalDefinitionSpy).toHaveBeenNthCalledWith(
2,
expect.objectContaining({
mock: 2,
@@ -149,7 +149,7 @@ describe('Extension: ExternalConverters', () => {
description: 'external_2',
}),
);
expect(zhcAddDefinitionSpy).toHaveBeenNthCalledWith(
expect(zhcAddExternalDefinitionSpy).toHaveBeenNthCalledWith(
3,
expect.objectContaining({
mock: true,
@@ -206,7 +206,7 @@ describe('Extension: ExternalConverters', () => {
expect(writeFileSyncSpy).toHaveBeenCalledWith(converterFilePath, converterCode, 'utf8');
expect(zhcRemoveExternalDefinitionsSpy).toHaveBeenCalledTimes(1);
expect(zhcRemoveExternalDefinitionsSpy).toHaveBeenNthCalledWith(1, converterName);
expect(zhcAddDefinitionSpy).toHaveBeenCalledWith(
expect(zhcAddExternalDefinitionSpy).toHaveBeenCalledWith(
expect.objectContaining({
mock: true,
zigbeeModel: ['external_converter_device'],
@@ -288,7 +288,7 @@ describe('Extension: ExternalConverters', () => {
const errorMsg = `Invalid definition`;
zhcAddDefinitionSpy.mockImplementationOnce(() => {
zhcAddExternalDefinitionSpy.mockImplementationOnce(() => {
throw new Error(errorMsg);
});
+2 -2
View File
@@ -6,7 +6,7 @@ import {devices, groups, events as mockZHEvents, resetGroupMembers, returnDevice
import stringify from 'json-stable-stringify-without-jsonify';
import {toZigbee as zhcToZigbee} from 'zigbee-herdsman-converters';
import * as zhcGlobalStore from 'zigbee-herdsman-converters/lib/store';
import {Controller} from '../../lib/controller';
import * as settings from '../../lib/util/settings';
@@ -42,7 +42,7 @@ describe('Extension: Groups', () => {
settings.reRead();
mockMQTTPublishAsync.mockClear();
groups.gledopto_group.command.mockClear();
zhcToZigbee.__clearStore__();
zhcGlobalStore.clear();
// @ts-expect-error private
controller.state.state = {};
});
+53 -9
View File
@@ -9,6 +9,9 @@ import assert from 'node:assert';
import stringify from 'json-stable-stringify-without-jsonify';
import * as zhc from 'zigbee-herdsman-converters';
import {KeyValueAny} from 'zigbee-herdsman-converters/lib/types';
import {Controller} from '../../lib/controller';
import HomeAssistant from '../../lib/extension/homeassistant';
import * as settings from '../../lib/util/settings';
@@ -79,7 +82,12 @@ describe('Extension: HomeAssistant', () => {
it('Should not have duplicate type/object_ids in a mapping', async () => {
const duplicated: string[] = [];
(await import('zigbee-herdsman-converters')).definitions.forEach((d) => {
(await import('zigbee-herdsman-converters/devices/index')).default.forEach((baseDefinition) => {
const d = zhc.prepareDefinition(
// @ts-expect-error inferred type is wrong
baseDefinition,
);
const exposes = typeof d.exposes == 'function' ? d.exposes(undefined, undefined) : d.exposes;
const device = {
definition: d,
@@ -133,7 +141,7 @@ describe('Extension: HomeAssistant', () => {
name: null,
schema: 'json',
state_topic: 'zigbee2mqtt/ha_discovery_group',
supported_color_modes: ['xy', 'color_temp'],
supported_color_modes: ['brightness', 'xy', 'color_temp'],
effect: true,
effect_list: [
'blink',
@@ -373,7 +381,7 @@ describe('Extension: HomeAssistant', () => {
availability: [{topic: 'zigbee2mqtt/bridge/state', value_template: '{{ value_json.state }}'}],
brightness: true,
brightness_scale: 254,
supported_color_modes: ['color_temp'],
supported_color_modes: ['brightness', 'color_temp'],
min_mireds: 250,
max_mireds: 454,
command_topic: 'zigbee2mqtt/bulb/set',
@@ -873,6 +881,42 @@ describe('Extension: HomeAssistant', () => {
});
});
it('Should discover devices with speed-controlled fan', async () => {
const payload = {
state_topic: 'zigbee2mqtt/fanbee',
state_value_template: '{{ value_json.state }}',
command_topic: 'zigbee2mqtt/fanbee/set/state',
percentage_state_topic: 'zigbee2mqtt/fanbee',
percentage_command_topic: 'zigbee2mqtt/fanbee/set/speed',
percentage_value_template: "{{ value_json.speed | default('None') }}",
percentage_command_template: "{{ value | default('') }}",
speed_range_min: 1,
speed_range_max: 254,
name: null,
object_id: 'fanbee',
unique_id: '0x00124b00cfcf3298_fan_zigbee2mqtt',
origin: origin,
device: {
identifiers: ['zigbee2mqtt_0x00124b00cfcf3298'],
name: 'fanbee',
model: 'Fan with valve',
model_id: 'FanBee',
manufacturer: 'Lorenz Brun',
via_device: 'zigbee2mqtt_bridge_0x00124b00120144ae',
},
availability: [
{
topic: 'zigbee2mqtt/bridge/state',
value_template: '{{ value_json.state }}',
},
],
};
const idx = mockMQTTPublishAsync.mock.calls.findIndex((c) => c[0] === 'homeassistant/fan/0x00124b00cfcf3298/fan/config');
expect(idx).not.toBe(-1);
expect(JSON.parse(mockMQTTPublishAsync.mock.calls[idx][1])).toStrictEqual(payload);
});
it('Should discover thermostat devices', async () => {
const payload = {
action_template:
@@ -1589,7 +1633,7 @@ describe('Extension: HomeAssistant', () => {
name: null,
schema: 'json',
state_topic: 'zigbee2mqtt/ha_discovery_group_new',
supported_color_modes: ['xy', 'color_temp'],
supported_color_modes: ['brightness', 'xy', 'color_temp'],
effect: true,
effect_list: [
'blink',
@@ -1681,7 +1725,7 @@ describe('Extension: HomeAssistant', () => {
state_topic: 'zigbee2mqtt/bulb',
unique_id: '0x000b57fffec6a5b2_update_zigbee2mqtt',
value_template:
"{\"latest_version\":\"{{ value_json['update']['latest_version'] }}\",\"installed_version\":\"{{ value_json['update']['installed_version'] }}\",\"update_percentage\":{{ value_json['update'].get('progress', 'null') }}}",
"{\"latest_version\":\"{{ value_json['update']['latest_version'] }}\",\"installed_version\":\"{{ value_json['update']['installed_version'] }}\",\"update_percentage\":{{ value_json['update'].get('progress', 'null') }},\"in_progress\":{{ (value_json['update']['state'] == 'updating')|lower }}}",
};
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('homeassistant/update/0x000b57fffec6a5b2/update/config', stringify(payload), {
@@ -2057,7 +2101,7 @@ describe('Extension: HomeAssistant', () => {
name: null,
schema: 'json',
state_topic: 'zigbee2mqtt/ha_discovery_group',
supported_color_modes: ['xy', 'color_temp'],
supported_color_modes: ['brightness', 'xy', 'color_temp'],
effect: true,
effect_list: [
'blink',
@@ -2101,7 +2145,7 @@ describe('Extension: HomeAssistant', () => {
name: null,
schema: 'json',
state_topic: 'zigbee2mqtt/ha_discovery_group',
supported_color_modes: ['xy', 'color_temp'],
supported_color_modes: ['brightness', 'xy', 'color_temp'],
effect: true,
effect_list: [
'blink',
@@ -2156,7 +2200,7 @@ describe('Extension: HomeAssistant', () => {
name: null,
schema: 'json',
state_topic: 'zigbee2mqtt/bulb',
supported_color_modes: ['color_temp'],
supported_color_modes: ['brightness', 'color_temp'],
object_id: 'bulb',
unique_id: '0x000b57fffec6a5b2_light_zigbee2mqtt',
origin: origin,
@@ -2256,7 +2300,7 @@ describe('Extension: HomeAssistant', () => {
await vi.runOnlyPendingTimersAsync();
await flushPromises();
let payload = {
let payload: KeyValueAny = {
name: 'Chill scene',
command_topic: 'zigbee2mqtt/bulb_color_2/set',
payload_on: '{ "scene_recall": 1 }',
+5 -2
View File
@@ -11,8 +11,6 @@ import * as settings from '../../lib/util/settings';
const mockOnEvent = vi.fn();
const mockLivoloOnEvent = vi.fn();
const mappedLivolo = zhc.findByModel('TI0001')!;
mappedLivolo.onEvent = mockLivoloOnEvent;
// @ts-expect-error mock
zhc.onEvent = mockOnEvent;
@@ -21,6 +19,11 @@ const mocksClear = [mockMQTTPublishAsync, mockLogger.warning, mockLogger.debug];
describe('Extension: OnEvent', () => {
let controller: Controller;
beforeAll(async () => {
const mappedLivolo = (await zhc.findByDevice(devices.LIVOLO))!;
mappedLivolo.onEvent = mockLivoloOnEvent;
});
beforeEach(async () => {
vi.useFakeTimers();
data.writeDefaultConfiguration();
+3 -3
View File
@@ -7,7 +7,7 @@ import {devices, groups, events as mockZHEvents} from '../mocks/zigbeeHerdsman';
import stringify from 'json-stable-stringify-without-jsonify';
import {toZigbee} from 'zigbee-herdsman-converters';
import * as zhcGlobalStore from 'zigbee-herdsman-converters/lib/store';
import {Controller} from '../../lib/controller';
import {loadTopicGetSetRegex} from '../../lib/extension/publish';
@@ -58,7 +58,7 @@ describe('Extension: Publish', () => {
g.command.mockClear();
});
toZigbee.__clearStore__();
zhcGlobalStore.clear();
});
afterAll(async () => {
@@ -1511,7 +1511,7 @@ describe('Extension: Publish', () => {
await mockMQTTEvents.message('zigbee2mqtt/bulb_color/set', stringify({state: 'ON', brightness: 20, transition: 0.0}));
await flushPromises();
toZigbee.__clearStore__();
zhcGlobalStore.clear();
await mockMQTTEvents.message('zigbee2mqtt/bulb_color/set', stringify({state: 'ON', transition: 1.0}));
await flushPromises();
+16 -1
View File
@@ -46,7 +46,7 @@ describe('Logger', () => {
expect(dirs.length).toBe(1);
});
it('Should cleanup', () => {
it('Should cleanup (default setting)', () => {
for (const d of fs.readdirSync(dir.name)) {
rimrafSync(path.join(dir.name, d));
}
@@ -60,6 +60,21 @@ describe('Logger', () => {
expect(fs.readdirSync(dir.name).length).toBe(10);
});
it('Should cleanup (15 folders setting)', () => {
for (const d of fs.readdirSync(dir.name)) {
rimrafSync(path.join(dir.name, d));
}
for (let i = 0; i < 20; i++) {
fs.mkdirSync(path.join(dir.name, `log_${i}`));
}
settings.set(['advanced', 'log_directories_to_keep'], 15);
expect(fs.readdirSync(dir.name).length).toBe(20);
logger.init();
expect(fs.readdirSync(dir.name).length).toBe(15);
});
it('Should not cleanup when there is no timestamp set', () => {
for (const d of fs.readdirSync(dir.name)) {
rimrafSync(path.join(dir.name, d));
+4
View File
@@ -205,6 +205,10 @@ export const DEFAULT_CONFIGURATION = {
'0x000b57cdfec6a5b3': {
friendly_name: 'hue_twilight',
},
'0x00124b00cfcf3298': {
friendly_name: 'fanbee',
retain: true,
},
},
groups: {
1: {
+10
View File
@@ -1136,6 +1136,16 @@ export const devices = {
undefined,
CUSTOM_CLUSTERS,
),
fanbee: new Device(
'Router',
'0x00124b00cfcf3298',
18129,
0xfff1,
[new Endpoint(8, [0, 3, 4, 5, 6, 8], []), new Endpoint(242, [], [33])],
true,
'DC Source',
'FanBee1',
),
};
export const mockController = {
+20 -6
View File
@@ -1,17 +1,27 @@
#!/bin/bash -e
#!/usr/bin/env bash
cd "$(dirname "$0")"
NEED_RESTART=0
if which systemctl 2> /dev/null > /dev/null; then
OSNAME="$(uname -s)"
if [ "$OSNAME" == "FreeBSD" ]; then
echo "Checking Zigbee2MQTT status..."
if systemctl is-active --quiet zigbee2mqtt; then
if service zigbee2mqtt status >/dev/null; then
echo "Stopping Zigbee2MQTT..."
sudo systemctl stop zigbee2mqtt
service zigbee2mqtt stop
NEED_RESTART=1
fi
else
echo "Skipped stopping Zigbee2MQTT, no systemctl found"
if which systemctl 2> /dev/null > /dev/null; then
echo "Checking Zigbee2MQTT status..."
if systemctl is-active --quiet zigbee2mqtt; then
echo "Stopping Zigbee2MQTT..."
sudo systemctl stop zigbee2mqtt
NEED_RESTART=1
fi
else
echo "Skipped stopping Zigbee2MQTT, no systemctl found"
fi
fi
echo "Updating..."
@@ -25,7 +35,11 @@ pnpm run build
if [ $NEED_RESTART -eq 1 ]; then
echo "Starting Zigbee2MQTT..."
sudo systemctl start zigbee2mqtt
if [ "$OSNAME" == "FreeBSD" ]; then
service zigbee2mqtt start
else
sudo systemctl start zigbee2mqtt
fi
fi
echo "Done!"