default
+
@switchbot/homebridge-switchbot@switchbot/homebridge-switchbot
diff --git a/package-lock.json b/package-lock.json
index 86e7fe60..b0aec4b7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@switchbot/homebridge-switchbot",
- "version": "4.0.0",
+ "version": "4.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@switchbot/homebridge-switchbot",
- "version": "4.0.0",
+ "version": "4.1.0",
"funding": [
{
"type": "Paypal",
@@ -23,33 +23,33 @@
"async-mqtt": "^2.6.3",
"fakegato-history": "^0.6.5",
"homebridge-lib": "^7.0.9",
- "node-switchbot": "^3.1.1",
+ "node-switchbot": "^3.2.1",
"rxjs": "^7.8.1"
},
"devDependencies": {
- "@antfu/eslint-config": "^3.7.3",
+ "@antfu/eslint-config": "^3.8.0",
"@types/aes-js": "^3.1.4",
"@types/debug": "^4.1.12",
"@types/fs-extra": "^11.0.4",
"@types/mdast": "^4.0.4",
- "@types/node": "^22.7.5",
+ "@types/node": "^22.7.8",
"@types/semver": "^7.5.8",
"@types/source-map-support": "^0.5.10",
- "@vitest/coverage-v8": "^2.1.2",
- "eslint": "^9.12.0",
+ "@vitest/coverage-v8": "^2.1.3",
+ "eslint": "^9.13.0",
"eslint-plugin-format": "^0.1.2",
"homebridge": "^1.8.4",
- "homebridge-config-ui-x": "4.61.0",
+ "homebridge-config-ui-x": "4.62.0",
"nodemon": "^3.1.7",
- "npm-check-updates": "^17.1.3",
+ "npm-check-updates": "^17.1.4",
"shx": "^0.3.4",
"ts-node": "^10.9.2",
- "typedoc": "^0.26.9",
+ "typedoc": "^0.26.10",
"typescript": "^5.6.3",
- "vitest": "^2.1.2"
+ "vitest": "^2.1.3"
},
"engines": {
- "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.11 || ^2.0.0-alpha.10",
+ "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.22 || ^2.0.0-alpha.37",
"node": "^20 || ^22"
}
},
@@ -68,43 +68,43 @@
}
},
"node_modules/@antfu/eslint-config": {
- "version": "3.7.3",
- "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-3.7.3.tgz",
- "integrity": "sha512-vzhKtzQT+f/xBV8T5U8SFy3D7uAqL2CEcjsJVqtA7F8tdKvGuC/96uWeEKMHk5lRfijgj+xRvb+c4qQn60YlIA==",
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-3.8.0.tgz",
+ "integrity": "sha512-O5QSufPHpKTm0wk1OQ5c2mOZVzCqYV3hIDrt5zt+cOWqiG8YXLPkSOD4fFwjomATtOuUbcLUwkcgY5dErM7aIw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@antfu/install-pkg": "^0.4.1",
"@clack/prompts": "^0.7.0",
"@eslint-community/eslint-plugin-eslint-comments": "^4.4.0",
- "@eslint/markdown": "^6.1.0",
- "@stylistic/eslint-plugin": "^2.8.0",
- "@typescript-eslint/eslint-plugin": "^8.7.0",
- "@typescript-eslint/parser": "^8.7.0",
- "@vitest/eslint-plugin": "^1.1.4",
+ "@eslint/markdown": "^6.2.0",
+ "@stylistic/eslint-plugin": "^2.9.0",
+ "@typescript-eslint/eslint-plugin": "^8.9.0",
+ "@typescript-eslint/parser": "^8.9.0",
+ "@vitest/eslint-plugin": "^1.1.7",
"eslint-config-flat-gitignore": "^0.3.0",
"eslint-flat-config-utils": "^0.4.0",
"eslint-merge-processors": "^0.1.0",
"eslint-plugin-antfu": "^2.7.0",
"eslint-plugin-command": "^0.2.6",
- "eslint-plugin-import-x": "^4.3.0",
- "eslint-plugin-jsdoc": "^50.3.0",
+ "eslint-plugin-import-x": "^4.3.1",
+ "eslint-plugin-jsdoc": "^50.4.1",
"eslint-plugin-jsonc": "^2.16.0",
- "eslint-plugin-n": "^17.10.3",
+ "eslint-plugin-n": "^17.11.1",
"eslint-plugin-no-only-tests": "^3.3.0",
- "eslint-plugin-perfectionist": "^3.7.0",
+ "eslint-plugin-perfectionist": "^3.9.0",
"eslint-plugin-regexp": "^2.6.0",
"eslint-plugin-toml": "^0.11.1",
- "eslint-plugin-unicorn": "^55.0.0",
+ "eslint-plugin-unicorn": "^56.0.0",
"eslint-plugin-unused-imports": "^4.1.4",
- "eslint-plugin-vue": "^9.28.0",
+ "eslint-plugin-vue": "^9.29.0",
"eslint-plugin-yml": "^1.14.0",
"eslint-processor-vue-blocks": "^0.1.2",
- "globals": "^15.9.0",
+ "globals": "^15.11.0",
"jsonc-eslint-parser": "^2.4.0",
"local-pkg": "^0.5.0",
"parse-gitignore": "^2.0.0",
- "picocolors": "^1.1.0",
+ "picocolors": "^1.1.1",
"toml-eslint-parser": "^0.10.0",
"vue-eslint-parser": "^9.4.3",
"yaml-eslint-parser": "^1.2.3",
@@ -124,7 +124,7 @@
"eslint": "^9.10.0",
"eslint-plugin-astro": "^1.2.0",
"eslint-plugin-format": ">=0.1.0",
- "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.4",
"eslint-plugin-solid": "^0.14.3",
"eslint-plugin-svelte": ">=2.35.1",
@@ -913,9 +913,9 @@
}
},
"node_modules/@eslint/compat": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.0.tgz",
- "integrity": "sha512-CkPWddN7J9JPrQedEr2X7AjK9y1jaMJtxZ4A/+jTMFA2+n5BWhcKHW/EbJyARqg2zzQfgtWUtVmG3hrG6+nGpg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.1.tgz",
+ "integrity": "sha512-JbHG2TWuCeNzh87fXo+/46Z1LEo9DBA9T188d0fZgGxAD+cNyS6sx9fdiyxjGPBMyQVRlCutTByZ6a5+YMkF7g==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -970,9 +970,9 @@
}
},
"node_modules/@eslint/core": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz",
- "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==",
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz",
+ "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -1041,9 +1041,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.12.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz",
- "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==",
+ "version": "9.13.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz",
+ "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1051,9 +1051,9 @@
}
},
"node_modules/@eslint/markdown": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.2.0.tgz",
- "integrity": "sha512-ZLWZ6RNy5flf1Nk2DBt0V77MQpQEo8snkjVT75P5J0SJkE/QNoqgy7+dBvNjlyZuj664pU43uDXWg3J8AfF0IQ==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.2.1.tgz",
+ "integrity": "sha512-cKVd110hG4ICHmWhIwZJfKmmJBvbiDWyrHODJknAtudKgZtlROGoLX9UEOA0o746zC0hCY4UV4vR+aOGW9S6JQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1077,9 +1077,9 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz",
- "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==",
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz",
+ "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1129,11 +1129,11 @@
}
},
"node_modules/@fastify/ajv-compiler/node_modules/ajv/node_modules/fast-uri": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz",
- "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz",
+ "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==",
"dev": true,
- "license": "MIT"
+ "license": "BSD-3-Clause"
},
"node_modules/@fastify/ajv-compiler/node_modules/json-schema-traverse": {
"version": "1.0.0",
@@ -1561,9 +1561,9 @@
}
},
"node_modules/@nestjs/common": {
- "version": "10.4.4",
- "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.4.tgz",
- "integrity": "sha512-0j2/zqRw9nvHV1GKTktER8B/hIC/Z8CYFjN/ZqUuvwayCH+jZZBhCR2oRyuvLTXdnlSmtCAg2xvQ0ULqQvzqhA==",
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.5.tgz",
+ "integrity": "sha512-N/yUyuYCBMb0+H6jHhntR7PURzji0usID/DByhOfooyk/aPGscI0aQKwOA6edlJlT92hHUvXYLJ5p3npj7KcjQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1590,10 +1590,17 @@
}
}
},
+ "node_modules/@nestjs/common/node_modules/tslib": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "dev": true,
+ "license": "0BSD"
+ },
"node_modules/@nestjs/core": {
- "version": "10.4.4",
- "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.4.tgz",
- "integrity": "sha512-y9tjmAzU6LTh1cC/lWrRsCcOd80khSR0qAHAqwY2svbW+AhsR/XCzgpZrAAKJrm/dDfjLCZKyxJSayeirGcW5Q==",
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.5.tgz",
+ "integrity": "sha512-wk0KJ+6tuidqAdeemsQ40BCp1BgMsSuSLG577aqXLxXYoa8FQYPrdxoSzd05znYLwJYM55fisZWb3FLF9HT2qw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -1629,6 +1636,13 @@
}
}
},
+ "node_modules/@nestjs/core/node_modules/tslib": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "dev": true,
+ "license": "0BSD"
+ },
"node_modules/@nestjs/jwt": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.2.0.tgz",
@@ -1676,9 +1690,9 @@
}
},
"node_modules/@nestjs/platform-fastify": {
- "version": "10.4.4",
- "resolved": "https://registry.npmjs.org/@nestjs/platform-fastify/-/platform-fastify-10.4.4.tgz",
- "integrity": "sha512-3fRt9mhhqe7aS1kF9myAFSUazhW88yrq9w3LrdHbjOTkGh8ZiZckjzKL705xORVJw2d/BHkgP8AqoNthakLJeQ==",
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/@nestjs/platform-fastify/-/platform-fastify-10.4.5.tgz",
+ "integrity": "sha512-5kcLsloaKkG6i46qbHmz6m/XoEtwroBni3uwsNENw4OJ8fptllihOqG3PWKRfljfpH4twyKdtZfKvyjMHXNj4w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1686,7 +1700,7 @@
"@fastify/formbody": "7.4.0",
"@fastify/middie": "8.3.3",
"fastify": "4.28.1",
- "light-my-request": "6.0.0",
+ "light-my-request": "6.1.0",
"path-to-regexp": "3.3.0",
"tslib": "2.7.0"
},
@@ -1709,10 +1723,17 @@
}
}
},
+ "node_modules/@nestjs/platform-fastify/node_modules/tslib": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "dev": true,
+ "license": "0BSD"
+ },
"node_modules/@nestjs/platform-socket.io": {
- "version": "10.4.4",
- "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.4.tgz",
- "integrity": "sha512-5GEYUA3sNbX2jOBP6FmrIK/zv9VCdvpdr4Sef1OKvt1U0qsV1YgmWPWDPumZM77n5DI0VHSJPyo7yjZaEKWOiQ==",
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.5.tgz",
+ "integrity": "sha512-dHkHJQArhrpkX6qBdTW2ghuja3i3cCslwy4QHY6d46u+9UyANQlsNK9wt/lZnmXfCMaci8xAJvUpyODa6YtV7g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1729,6 +1750,13 @@
"rxjs": "^7.1.0"
}
},
+ "node_modules/@nestjs/platform-socket.io/node_modules/tslib": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "dev": true,
+ "license": "0BSD"
+ },
"node_modules/@nestjs/swagger": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.2.tgz",
@@ -1764,9 +1792,9 @@
}
},
"node_modules/@nestjs/websockets": {
- "version": "10.4.4",
- "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.4.tgz",
- "integrity": "sha512-ZHnak04i/iKBS0csjJa7K6D6xdsB0Yz6duJuCR7xGLItchFK+Ne21m9rEF8ffvW74U7UAYkQHBgD5242LBBYiQ==",
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.5.tgz",
+ "integrity": "sha512-LbL/HRLWQUBTUPY7swojOHdvokyVGINIiuP/VmRdhob4T751r+9i09z2RqRpP71psuom9mnRHYI1+vT2FABrAw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1787,6 +1815,13 @@
}
}
},
+ "node_modules/@nestjs/websockets/node_modules/tslib": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "dev": true,
+ "license": "0BSD"
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2697,9 +2732,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.7.5",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
- "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
+ "version": "22.7.8",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.8.tgz",
+ "integrity": "sha512-a922jJy31vqR5sk+kAdIENJjHblqcZ4RmERviFsER4WJcEONqxKcjNOlk0q7OUfrF5sddT+vng070cdfMlrPLg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2752,17 +2787,17 @@
"optional": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz",
- "integrity": "sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz",
+ "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.8.1",
- "@typescript-eslint/type-utils": "8.8.1",
- "@typescript-eslint/utils": "8.8.1",
- "@typescript-eslint/visitor-keys": "8.8.1",
+ "@typescript-eslint/scope-manager": "8.11.0",
+ "@typescript-eslint/type-utils": "8.11.0",
+ "@typescript-eslint/utils": "8.11.0",
+ "@typescript-eslint/visitor-keys": "8.11.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@@ -2786,16 +2821,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.1.tgz",
- "integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz",
+ "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.8.1",
- "@typescript-eslint/types": "8.8.1",
- "@typescript-eslint/typescript-estree": "8.8.1",
- "@typescript-eslint/visitor-keys": "8.8.1",
+ "@typescript-eslint/scope-manager": "8.11.0",
+ "@typescript-eslint/types": "8.11.0",
+ "@typescript-eslint/typescript-estree": "8.11.0",
+ "@typescript-eslint/visitor-keys": "8.11.0",
"debug": "^4.3.4"
},
"engines": {
@@ -2815,14 +2850,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz",
- "integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz",
+ "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.8.1",
- "@typescript-eslint/visitor-keys": "8.8.1"
+ "@typescript-eslint/types": "8.11.0",
+ "@typescript-eslint/visitor-keys": "8.11.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2833,14 +2868,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz",
- "integrity": "sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz",
+ "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.8.1",
- "@typescript-eslint/utils": "8.8.1",
+ "@typescript-eslint/typescript-estree": "8.11.0",
+ "@typescript-eslint/utils": "8.11.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.3.0"
},
@@ -2858,9 +2893,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz",
- "integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz",
+ "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2872,14 +2907,14 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz",
- "integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz",
+ "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "@typescript-eslint/types": "8.8.1",
- "@typescript-eslint/visitor-keys": "8.8.1",
+ "@typescript-eslint/types": "8.11.0",
+ "@typescript-eslint/visitor-keys": "8.11.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -2901,16 +2936,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz",
- "integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz",
+ "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "8.8.1",
- "@typescript-eslint/types": "8.8.1",
- "@typescript-eslint/typescript-estree": "8.8.1"
+ "@typescript-eslint/scope-manager": "8.11.0",
+ "@typescript-eslint/types": "8.11.0",
+ "@typescript-eslint/typescript-estree": "8.11.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2924,13 +2959,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz",
- "integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz",
+ "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.8.1",
+ "@typescript-eslint/types": "8.11.0",
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
@@ -2962,9 +2997,9 @@
"license": "ISC"
},
"node_modules/@vitest/coverage-v8": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.2.tgz",
- "integrity": "sha512-b7kHrFrs2urS0cOk5N10lttI8UdJ/yP3nB4JYTREvR5o18cR99yPpK4gK8oQgI42BVv0ILWYUSYB7AXkAUDc0g==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz",
+ "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2985,8 +3020,8 @@
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "@vitest/browser": "2.1.2",
- "vitest": "2.1.2"
+ "@vitest/browser": "2.1.3",
+ "vitest": "2.1.3"
},
"peerDependenciesMeta": {
"@vitest/browser": {
@@ -3016,14 +3051,14 @@
}
},
"node_modules/@vitest/expect": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.2.tgz",
- "integrity": "sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz",
+ "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "2.1.2",
- "@vitest/utils": "2.1.2",
+ "@vitest/spy": "2.1.3",
+ "@vitest/utils": "2.1.3",
"chai": "^5.1.1",
"tinyrainbow": "^1.2.0"
},
@@ -3032,13 +3067,13 @@
}
},
"node_modules/@vitest/mocker": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.2.tgz",
- "integrity": "sha512-ExElkCGMS13JAJy+812fw1aCv2QO/LBK6CyO4WOPAzLTmve50gydOlWhgdBJPx2ztbADUq3JVI0C5U+bShaeEA==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz",
+ "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "^2.1.0-beta.1",
+ "@vitest/spy": "2.1.3",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.11"
},
@@ -3046,7 +3081,7 @@
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "@vitest/spy": "2.1.2",
+ "@vitest/spy": "2.1.3",
"msw": "^2.3.5",
"vite": "^5.0.0"
},
@@ -3070,9 +3105,9 @@
}
},
"node_modules/@vitest/pretty-format": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.2.tgz",
- "integrity": "sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz",
+ "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3083,13 +3118,13 @@
}
},
"node_modules/@vitest/runner": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.2.tgz",
- "integrity": "sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz",
+ "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "2.1.2",
+ "@vitest/utils": "2.1.3",
"pathe": "^1.1.2"
},
"funding": {
@@ -3097,13 +3132,13 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.2.tgz",
- "integrity": "sha512-xtAeNsZ++aRIYIUsek7VHzry/9AcxeULlegBvsdLncLmNCR6tR8SRjn8BbDP4naxtccvzTqZ+L1ltZlRCfBZFA==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz",
+ "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "2.1.2",
+ "@vitest/pretty-format": "2.1.3",
"magic-string": "^0.30.11",
"pathe": "^1.1.2"
},
@@ -3112,9 +3147,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.2.tgz",
- "integrity": "sha512-GSUi5zoy+abNRJwmFhBDC0yRuVUn8WMlQscvnbbXdKLXX9dE59YbfwXxuJ/mth6eeqIzofU8BB5XDo/Ns/qK2A==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz",
+ "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3125,13 +3160,13 @@
}
},
"node_modules/@vitest/utils": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.2.tgz",
- "integrity": "sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz",
+ "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "2.1.2",
+ "@vitest/pretty-format": "2.1.3",
"loupe": "^3.1.1",
"tinyrainbow": "^1.2.0"
},
@@ -3212,19 +3247,6 @@
"license": "BSD-2-Clause",
"optional": true
},
- "node_modules/abort-controller": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
- "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "event-target-shim": "^5.0.0"
- },
- "engines": {
- "node": ">=6.5"
- }
- },
"node_modules/abstract-logging": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz",
@@ -3247,9 +3269,9 @@
}
},
"node_modules/acorn": {
- "version": "8.12.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
- "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz",
+ "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==",
"dev": true,
"license": "MIT",
"bin": {
@@ -3347,11 +3369,11 @@
}
},
"node_modules/ajv-formats/node_modules/fast-uri": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz",
- "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz",
+ "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==",
"dev": true,
- "license": "MIT"
+ "license": "BSD-3-Clause"
},
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
"version": "1.0.0",
@@ -3699,9 +3721,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
- "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
+ "version": "4.24.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
+ "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
"dev": true,
"funding": [
{
@@ -3719,10 +3741,10 @@
],
"license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001663",
- "electron-to-chromium": "^1.5.28",
+ "caniuse-lite": "^1.0.30001669",
+ "electron-to-chromium": "^1.5.41",
"node-releases": "^2.0.18",
- "update-browserslist-db": "^1.1.0"
+ "update-browserslist-db": "^1.1.1"
},
"bin": {
"browserslist": "cli.js"
@@ -3827,9 +3849,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001668",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz",
- "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==",
+ "version": "1.0.30001669",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz",
+ "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==",
"dev": true,
"funding": [
{
@@ -4278,9 +4300,9 @@
}
},
"node_modules/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4728,9 +4750,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.36",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.36.tgz",
- "integrity": "sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==",
+ "version": "1.5.41",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.41.tgz",
+ "integrity": "sha512-dfdv/2xNjX0P8Vzme4cfzHqnPm5xsZXwsolTYr0eyW18IUmNyG08vL+fttvinTfhKfIKdRoqkDIC9e9iWQCNYQ==",
"dev": true,
"license": "ISC"
},
@@ -4969,18 +4991,18 @@
}
},
"node_modules/eslint": {
- "version": "9.12.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz",
- "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==",
+ "version": "9.13.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz",
+ "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.11.0",
"@eslint/config-array": "^0.18.0",
- "@eslint/core": "^0.6.0",
+ "@eslint/core": "^0.7.0",
"@eslint/eslintrc": "^3.1.0",
- "@eslint/js": "9.12.0",
+ "@eslint/js": "9.13.0",
"@eslint/plugin-kit": "^0.2.0",
"@humanfs/node": "^0.16.5",
"@humanwhocodes/module-importer": "^1.0.1",
@@ -5235,13 +5257,13 @@
}
},
"node_modules/eslint-plugin-jsdoc": {
- "version": "50.3.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.2.tgz",
- "integrity": "sha512-TjgZocG53N3a84PdCFGqVMWLWwDitOUuKjlJftwTu/iTiD7N/Q2Q3eEy/Q4GfJqpM4rTJCkzUYWQfol6RZNDcA==",
+ "version": "50.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.4.3.tgz",
+ "integrity": "sha512-uWtwFxGRv6B8sU63HZM5dAGDhgsatb+LONwmILZJhdRALLOkCX2HFZhdL/Kw2ls8SQMAVEfK+LmnEfxInRN8HA==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
- "@es-joy/jsdoccomment": "~0.48.0",
+ "@es-joy/jsdoccomment": "~0.49.0",
"are-docs-informative": "^0.0.2",
"comment-parser": "1.4.1",
"debug": "^4.3.6",
@@ -5260,6 +5282,21 @@
"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
}
},
+ "node_modules/eslint-plugin-jsdoc/node_modules/@es-joy/jsdoccomment": {
+ "version": "0.49.0",
+ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz",
+ "integrity": "sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "comment-parser": "1.4.1",
+ "esquery": "^1.6.0",
+ "jsdoc-type-pratt-parser": "~4.1.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/eslint-plugin-jsonc": {
"version": "2.16.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.16.0.tgz",
@@ -5366,14 +5403,14 @@
}
},
"node_modules/eslint-plugin-perfectionist": {
- "version": "3.8.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.8.0.tgz",
- "integrity": "sha512-BYJWbQVOjvIGK9V1xUfn790HuvkePjxti8epOi1H6sdzo0N4RehBmQ8coHPbgA/f12BUG1NIoDtQhI9mUm+o2A==",
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.9.1.tgz",
+ "integrity": "sha512-9WRzf6XaAxF4Oi5t/3TqKP5zUjERhasHmLFHin2Yw6ZAp/EP/EVA2dr3BhQrrHWCm5SzTMZf0FcjDnBkO2xFkA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "^8.8.0",
- "@typescript-eslint/utils": "^8.8.0",
+ "@typescript-eslint/types": "^8.9.0",
+ "@typescript-eslint/utils": "^8.9.0",
"minimatch": "^9.0.5",
"natural-compare-lite": "^1.4.0"
},
@@ -5447,19 +5484,19 @@
}
},
"node_modules/eslint-plugin-unicorn": {
- "version": "55.0.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz",
- "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==",
+ "version": "56.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.0.tgz",
+ "integrity": "sha512-aXpddVz/PQMmd69uxO98PA4iidiVNvA0xOtbpUoz1WhBd4RxOQQYqN618v68drY0hmy5uU2jy1bheKEVWBjlPw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.24.5",
+ "@babel/helper-validator-identifier": "^7.24.7",
"@eslint-community/eslint-utils": "^4.4.0",
"ci-info": "^4.0.0",
"clean-regexp": "^1.0.0",
- "core-js-compat": "^3.37.0",
- "esquery": "^1.5.0",
- "globals": "^15.7.0",
+ "core-js-compat": "^3.38.1",
+ "esquery": "^1.6.0",
+ "globals": "^15.9.0",
"indent-string": "^4.0.0",
"is-builtin-module": "^3.2.1",
"jsesc": "^3.0.2",
@@ -5467,7 +5504,7 @@
"read-pkg-up": "^7.0.1",
"regexp-tree": "^0.1.27",
"regjsparser": "^0.10.0",
- "semver": "^7.6.1",
+ "semver": "^7.6.3",
"strip-indent": "^3.0.0"
},
"engines": {
@@ -5497,9 +5534,9 @@
}
},
"node_modules/eslint-plugin-vue": {
- "version": "9.29.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.29.0.tgz",
- "integrity": "sha512-hamyjrBhNH6Li6R1h1VF9KHfshJlKgKEg3ARbGTn72CMNDSMhWbgC7NdkRDEh25AFW+4SDATzyNM+3gWuZii8g==",
+ "version": "9.29.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.29.1.tgz",
+ "integrity": "sha512-MH/MbVae4HV/tM8gKAVWMPJbYgW04CK7SuzYRrlNERpxbO0P3+Zdsa2oAcFBW6xNu7W6lIkGOsFAMCRTYmrlWQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5727,26 +5764,6 @@
"through": "^2.3.8"
}
},
- "node_modules/event-target-shim": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
- "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/events": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
- "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.x"
- }
- },
"node_modules/expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
@@ -5909,11 +5926,11 @@
}
},
"node_modules/fast-json-stringify/node_modules/ajv/node_modules/fast-uri": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz",
- "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz",
+ "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==",
"dev": true,
- "license": "MIT"
+ "license": "BSD-3-Clause"
},
"node_modules/fast-json-stringify/node_modules/json-schema-traverse": {
"version": "1.0.0",
@@ -6015,16 +6032,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/fastify/node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/fastify/node_modules/light-my-request": {
"version": "5.14.0",
"resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.14.0.tgz",
@@ -6809,9 +6816,9 @@
}
},
"node_modules/homebridge-config-ui-x": {
- "version": "4.61.0",
- "resolved": "https://registry.npmjs.org/homebridge-config-ui-x/-/homebridge-config-ui-x-4.61.0.tgz",
- "integrity": "sha512-jmilxafuUxwA7Wm1jJ02zAjNQb1anz2668p63ZpBHahbHYg8kT1sIKLIb53FmlTzVrf+CCoJzXo4EJ2UUqNn0Q==",
+ "version": "4.62.0",
+ "resolved": "https://registry.npmjs.org/homebridge-config-ui-x/-/homebridge-config-ui-x-4.62.0.tgz",
+ "integrity": "sha512-f1k7m90EqGUnHPN8Jo3UhXlVEMN2brJJO8KkysxTU8Wk9qwO2VmE957JJ0LWflQRlgJCMn/iaDW5zt5bR3dkWg==",
"dev": true,
"funding": [
{
@@ -6831,14 +6838,14 @@
"@homebridge/hap-client": "1.10.2",
"@homebridge/node-pty-prebuilt-multiarch": "0.11.14",
"@nestjs/axios": "3.0.3",
- "@nestjs/common": "10.4.4",
- "@nestjs/core": "10.4.4",
+ "@nestjs/common": "10.4.5",
+ "@nestjs/core": "10.4.5",
"@nestjs/jwt": "10.2.0",
"@nestjs/passport": "10.0.3",
- "@nestjs/platform-fastify": "10.4.4",
- "@nestjs/platform-socket.io": "10.4.4",
+ "@nestjs/platform-fastify": "10.4.5",
+ "@nestjs/platform-socket.io": "10.4.5",
"@nestjs/swagger": "7.4.2",
- "@nestjs/websockets": "10.4.4",
+ "@nestjs/websockets": "10.4.5",
"axios": "1.7.7",
"bash-color": "0.0.4",
"buffer-shims": "1.0.0",
@@ -7894,20 +7901,20 @@
}
},
"node_modules/libphonenumber-js": {
- "version": "1.11.11",
- "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.11.tgz",
- "integrity": "sha512-mF3KaORjJQR6JBNcOkluDcJKhtoQT4VTLRMrX1v/wlBayL4M8ybwEDeryyPcrSEJmD0rVwHUbBarpZwN5NfPFQ==",
+ "version": "1.11.12",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.12.tgz",
+ "integrity": "sha512-QkJn9/D7zZ1ucvT++TQSvZuSA2xAWeUytU+DiEQwbPKLyrDpvbul2AFs1CGbRAPpSCCk47aRAb5DX5mmcayp4g==",
"dev": true,
"license": "MIT"
},
"node_modules/light-my-request": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.0.0.tgz",
- "integrity": "sha512-kFkFXrmKCL0EEeOmJybMH5amWFd+AFvlvMlvFTRxCUwbhfapZqDmeLMPoWihntnYY6JpoQDE9k+vOzObF1fDqg==",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.1.0.tgz",
+ "integrity": "sha512-+NFuhlOGoEwxeQfJ/pobkVFxcnKyDtiX847hLjuB/IzBxIl3q4VJeFI8uRCgb3AlTWL1lgOr+u5+8QdUcr33ng==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
- "cookie": "^0.6.0",
+ "cookie": "^0.7.0",
"process-warning": "^4.0.0",
"set-cookie-parser": "^2.6.0"
}
@@ -9360,9 +9367,9 @@
}
},
"node_modules/node-abi": {
- "version": "3.68.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.68.0.tgz",
- "integrity": "sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==",
+ "version": "3.71.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz",
+ "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -9466,14 +9473,14 @@
}
},
"node_modules/node-switchbot": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/node-switchbot/-/node-switchbot-3.1.1.tgz",
- "integrity": "sha512-JqEBHb0BHp5RZCtXPXw3atJiTNracOmmAO1t59vDjd1v12AFpSPiwVRoaZ6zWH6MQ3/IYb5GKtjmIi8YApZ1VQ==",
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/node-switchbot/-/node-switchbot-3.2.1.tgz",
+ "integrity": "sha512-L3zf2BjNmYc+W77yGPaBrYDcuOhFutS7j/Bsp+DZN2dXQu2++6LarsDuj5RK6/B9o4xM4he/P30IdIN5iWTX5w==",
"license": "MIT",
"dependencies": {
"@stoprocent/noble": "^1.15.1",
"async-mutex": "^0.5.0",
- "undici": "^6.20.0"
+ "undici": "^6.20.1"
},
"engines": {
"node": "^20 || ^22"
@@ -9592,9 +9599,9 @@
}
},
"node_modules/npm-check-updates": {
- "version": "17.1.3",
- "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.3.tgz",
- "integrity": "sha512-4uDLBWPuDHT5KLieIJ20FoAB8yqJejmupI42wPyfObgQOBbPAikQSwT73afDwREvhuxYrRDqlRvxTMSfvO+L8A==",
+ "version": "17.1.4",
+ "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.4.tgz",
+ "integrity": "sha512-crOUeN2GngqlkRCFQ/zi1zsneWd9IGZgIfAWYGAuhYiPnfbBTmJBL7Yq1wI0e1dsW8CfWc+h348WmfCREqeOBA==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -10181,9 +10188,9 @@
}
},
"node_modules/picocolors": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
- "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
@@ -10201,16 +10208,16 @@
}
},
"node_modules/pino": {
- "version": "9.4.0",
- "resolved": "https://registry.npmjs.org/pino/-/pino-9.4.0.tgz",
- "integrity": "sha512-nbkQb5+9YPhQRz/BeQmrWpEknAaqjpAqRK8NwJpmrX/JHu7JuZC5G1CeAwJDJfGes4h+YihC6in3Q2nGb+Y09w==",
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/pino/-/pino-9.5.0.tgz",
+ "integrity": "sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==",
"dev": true,
"license": "MIT",
"dependencies": {
"atomic-sleep": "^1.0.0",
"fast-redact": "^3.1.1",
"on-exit-leak-free": "^2.1.0",
- "pino-abstract-transport": "^1.2.0",
+ "pino-abstract-transport": "^2.0.0",
"pino-std-serializers": "^7.0.0",
"process-warning": "^4.0.0",
"quick-format-unescaped": "^4.0.3",
@@ -10224,58 +10231,15 @@
}
},
"node_modules/pino-abstract-transport": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz",
- "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz",
+ "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "readable-stream": "^4.0.0",
"split2": "^4.0.0"
}
},
- "node_modules/pino-abstract-transport/node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "node_modules/pino-abstract-transport/node_modules/readable-stream": {
- "version": "4.5.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
- "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "abort-controller": "^3.0.0",
- "buffer": "^6.0.3",
- "events": "^3.3.0",
- "process": "^0.11.10",
- "string_decoder": "^1.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
"node_modules/pino-abstract-transport/node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
@@ -10440,16 +10404,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/process": {
- "version": "0.11.10",
- "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
- "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6.0"
- }
- },
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -11252,9 +11206,9 @@
"optional": true
},
"node_modules/set-cookie-parser": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.0.tgz",
- "integrity": "sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==",
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"dev": true,
"license": "MIT"
},
@@ -11605,9 +11559,9 @@
}
},
"node_modules/sonic-boom": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.1.0.tgz",
- "integrity": "sha512-NGipjjRicyJJ03rPiZCJYjwlsuP2d1/5QUviozRXC7S3WdVWNK5e3Ojieb9CCyfhq2UC+3+SRd9nG3I2lPRvUw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz",
+ "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -12229,9 +12183,9 @@
"license": "MIT"
},
"node_modules/tinyexec": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz",
- "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==",
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz",
+ "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==",
"dev": true,
"license": "MIT"
},
@@ -12435,9 +12389,9 @@
}
},
"node_modules/tslib": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
- "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
+ "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
"license": "0BSD"
},
"node_modules/tunnel-agent": {
@@ -12490,9 +12444,9 @@
"license": "MIT"
},
"node_modules/typedoc": {
- "version": "0.26.9",
- "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.9.tgz",
- "integrity": "sha512-Rc7QpWL7EtmrT8yxV0GmhOR6xHgFnnhphbD9Suti3fz3um7ZOrou6q/g9d6+zC5PssTLZmjaW4Upmzv8T1rCcQ==",
+ "version": "0.26.10",
+ "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.10.tgz",
+ "integrity": "sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -12561,9 +12515,9 @@
"license": "MIT"
},
"node_modules/undici": {
- "version": "6.20.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-6.20.0.tgz",
- "integrity": "sha512-AITZfPuxubm31Sx0vr8bteSalEbs9wQb/BOBi9FPlD9Qpd6HxZ4Q0+hI742jBhkPb4RT2v5MQzaW5VhRVyj+9A==",
+ "version": "6.20.1",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.20.1.tgz",
+ "integrity": "sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==",
"license": "MIT",
"engines": {
"node": ">=18.17"
@@ -12845,9 +12799,9 @@
}
},
"node_modules/vite": {
- "version": "5.4.8",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
- "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
+ "version": "5.4.9",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz",
+ "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -12905,9 +12859,9 @@
}
},
"node_modules/vite-node": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.2.tgz",
- "integrity": "sha512-HPcGNN5g/7I2OtPjLqgOtCRu/qhVvBxTUD3qzitmL0SrG1cWFzxzhMDWussxSbrRYWqnKf8P2jiNhPMSN+ymsQ==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz",
+ "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -12927,19 +12881,19 @@
}
},
"node_modules/vitest": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.2.tgz",
- "integrity": "sha512-veNjLizOMkRrJ6xxb+pvxN6/QAWg95mzcRjtmkepXdN87FNfxAss9RKe2far/G9cQpipfgP2taqg0KiWsquj8A==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz",
+ "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "2.1.2",
- "@vitest/mocker": "2.1.2",
- "@vitest/pretty-format": "^2.1.2",
- "@vitest/runner": "2.1.2",
- "@vitest/snapshot": "2.1.2",
- "@vitest/spy": "2.1.2",
- "@vitest/utils": "2.1.2",
+ "@vitest/expect": "2.1.3",
+ "@vitest/mocker": "2.1.3",
+ "@vitest/pretty-format": "^2.1.3",
+ "@vitest/runner": "2.1.3",
+ "@vitest/snapshot": "2.1.3",
+ "@vitest/spy": "2.1.3",
+ "@vitest/utils": "2.1.3",
"chai": "^5.1.1",
"debug": "^4.3.6",
"magic-string": "^0.30.11",
@@ -12950,7 +12904,7 @@
"tinypool": "^1.0.0",
"tinyrainbow": "^1.2.0",
"vite": "^5.0.0",
- "vite-node": "2.1.2",
+ "vite-node": "2.1.3",
"why-is-node-running": "^2.3.0"
},
"bin": {
@@ -12965,8 +12919,8 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "2.1.2",
- "@vitest/ui": "2.1.2",
+ "@vitest/browser": "2.1.3",
+ "@vitest/ui": "2.1.3",
"happy-dom": "*",
"jsdom": "*"
},
@@ -13368,9 +13322,9 @@
"license": "ISC"
},
"node_modules/yaml": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz",
- "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
+ "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
"devOptional": true,
"license": "ISC",
"bin": {
diff --git a/package.json b/package.json
index 4b67dcac..f6e2ac4c 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "@switchbot/homebridge-switchbot",
"displayName": "SwitchBot",
"type": "module",
- "version": "4.0.0",
+ "version": "4.1.0",
"description": "The SwitchBot plugin allows you to access your SwitchBot device(s) from HomeKit.",
"author": "SwitchBot
(https://github.com/SwitchBot)",
"contributors": [
@@ -55,7 +55,7 @@
"icon": "https://raw.githubusercontent.com/OpenWonderLabs/homebridge-switchbot/latest/branding/icon.png",
"engineStrict": true,
"engines": {
- "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.11 || ^2.0.0-alpha.10",
+ "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.22 || ^2.0.0-alpha.37",
"node": "^20 || ^22"
},
"scripts": {
@@ -81,30 +81,30 @@
"async-mqtt": "^2.6.3",
"fakegato-history": "^0.6.5",
"homebridge-lib": "^7.0.9",
- "node-switchbot": "^3.1.1",
+ "node-switchbot": "^3.2.1",
"rxjs": "^7.8.1"
},
"devDependencies": {
- "@antfu/eslint-config": "^3.7.3",
+ "@antfu/eslint-config": "^3.8.0",
"@types/aes-js": "^3.1.4",
"@types/debug": "^4.1.12",
"@types/fs-extra": "^11.0.4",
"@types/mdast": "^4.0.4",
- "@types/node": "^22.7.5",
+ "@types/node": "^22.7.8",
"@types/semver": "^7.5.8",
"@types/source-map-support": "^0.5.10",
- "@vitest/coverage-v8": "^2.1.2",
- "eslint": "^9.12.0",
+ "@vitest/coverage-v8": "^2.1.3",
+ "eslint": "^9.13.0",
"eslint-plugin-format": "^0.1.2",
"homebridge": "^1.8.4",
- "homebridge-config-ui-x": "4.61.0",
+ "homebridge-config-ui-x": "4.62.0",
"nodemon": "^3.1.7",
- "npm-check-updates": "^17.1.3",
+ "npm-check-updates": "^17.1.4",
"shx": "^0.3.4",
"ts-node": "^10.9.2",
- "typedoc": "^0.26.9",
+ "typedoc": "^0.26.10",
"typescript": "^5.6.3",
- "vitest": "^2.1.2"
+ "vitest": "^2.1.3"
},
"directories": {
"doc": "docs"
diff --git a/src/device/bot.ts b/src/device/bot.ts
index f5a47d35..03ff4f99 100644
--- a/src/device/bot.ts
+++ b/src/device/bot.ts
@@ -582,10 +582,10 @@ export class Bot extends deviceBase {
parameter: 'default',
commandType: 'command',
}
- this.debugLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)},`)
+ await this.debugLog(`SwitchBot OpenAPI bodyChange: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
- const deviceStatus: any = body
+ const deviceStatus: any = await body
await this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
if (await this.successfulStatusCodes(deviceStatus)) {
await this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
diff --git a/src/device/curtain.ts b/src/device/curtain.ts
index 00b80f78..7c065978 100644
--- a/src/device/curtain.ts
+++ b/src/device/curtain.ts
@@ -504,7 +504,7 @@ export class Curtain extends deviceBase {
await this.debugLog('openAPIRefreshStatus')
try {
const { body } = await this.deviceRefreshStatus()
- const deviceStatus: any = await body
+ const deviceStatus: any = body
await this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
if (await this.successfulStatusCodes(deviceStatus)) {
await this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
diff --git a/src/device/meterpro.ts b/src/device/meterpro.ts
new file mode 100644
index 00000000..0596a2fc
--- /dev/null
+++ b/src/device/meterpro.ts
@@ -0,0 +1,417 @@
+/* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
+ *
+ * MeterPro.ts: @switchbot/homebridge-switchbot.
+ */
+import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
+import type { device, meterProServiceData, meterProStatus, meterProWebhookContext } from 'node-switchbot'
+
+import type { SwitchBotPlatform } from '../platform.js'
+import type { devicesConfig, meterConfig } from '../settings.js'
+
+import { Units } from 'homebridge'
+/*
+* For Testing Locally:
+* import { SwitchBotBLEModel, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
+*/
+import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot'
+import { interval, skipWhile, Subject } from 'rxjs'
+
+import { convertUnits, formatDeviceIdAsMac, validHumidity } from '../utils.js'
+import { deviceBase } from './device.js'
+
+/**
+ * Platform Accessory
+ * An instance of this class is created for each accessory your platform registers
+ * Each accessory may expose multiple services of different service types.
+ */
+export class MeterPro extends deviceBase {
+ // Services
+ private Battery: {
+ Name: CharacteristicValue
+ Service: Service
+ BatteryLevel: CharacteristicValue
+ StatusLowBattery: CharacteristicValue
+ }
+
+ private HumiditySensor?: {
+ Name: CharacteristicValue
+ Service: Service
+ CurrentRelativeHumidity: CharacteristicValue
+ }
+
+ private TemperatureSensor?: {
+ Name: CharacteristicValue
+ Service: Service
+ CurrentTemperature: CharacteristicValue
+ }
+
+ // OpenAPI
+ deviceStatus!: meterProStatus
+
+ // Webhook
+ webhookContext!: meterProWebhookContext
+
+ // BLE
+ serviceData!: meterProServiceData
+
+ // Updates
+ meterUpdateInProgress!: boolean
+ doMeterUpdate: Subject
+
+ constructor(
+ readonly platform: SwitchBotPlatform,
+ accessory: PlatformAccessory,
+ device: device & devicesConfig,
+ ) {
+ super(platform, accessory, device)
+ // Set category
+ accessory.category = this.hap.Categories.SENSOR
+
+ // this is subject we use to track when we need to POST changes to the SwitchBot API
+ this.doMeterUpdate = new Subject()
+ this.meterUpdateInProgress = false
+
+ // Initialize Battery Service
+ accessory.context.Battery = accessory.context.Battery ?? {}
+ this.Battery = {
+ Name: `${accessory.displayName} Battery`,
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
+ StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
+ }
+ accessory.context.Battery = this.Battery as object
+
+ // Initialize Battery Characteristics
+ this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name).setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE).getCharacteristic(this.hap.Characteristic.BatteryLevel).onGet(() => {
+ return this.Battery.BatteryLevel
+ })
+
+ this.Battery.Service.getCharacteristic(this.hap.Characteristic.StatusLowBattery).onGet(() => {
+ return this.Battery.StatusLowBattery
+ })
+
+ // Initialize Temperature Sensor Service
+ if ((device as meterConfig).hide_temperature) {
+ if (this.TemperatureSensor) {
+ this.debugLog('Removing Temperature Sensor Service')
+ this.TemperatureSensor.Service = this.accessory.getService(this.hap.Service.TemperatureSensor) as Service
+ accessory.removeService(this.TemperatureSensor.Service)
+ }
+ } else {
+ accessory.context.TemperatureSensor = accessory.context.TemperatureSensor ?? {}
+ this.TemperatureSensor = {
+ Name: `${accessory.displayName} Temperature Sensor`,
+ Service: accessory.getService(this.hap.Service.TemperatureSensor) ?? this.accessory.addService(this.hap.Service.TemperatureSensor) as Service,
+ CurrentTemperature: accessory.context.CurrentTemperature ?? 30,
+ }
+ accessory.context.TemperatureSensor = this.TemperatureSensor as object
+
+ // Initialize Temperature Sensor Characteristics
+ this.TemperatureSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.TemperatureSensor.Name).getCharacteristic(this.hap.Characteristic.CurrentTemperature).setProps({
+ unit: Units.CELSIUS,
+ validValueRanges: [-273.15, 100],
+ minValue: -273.15,
+ maxValue: 100,
+ minStep: 0.1,
+ }).onGet(() => {
+ return this.TemperatureSensor!.CurrentTemperature!
+ })
+ }
+ // Initialize Humidity Sensor Service
+ if ((device as meterConfig).hide_humidity) {
+ if (this.HumiditySensor) {
+ this.debugLog('Removing Humidity Sensor Service')
+ this.HumiditySensor.Service = this.accessory.getService(this.hap.Service.HumiditySensor) as Service
+ accessory.removeService(this.HumiditySensor.Service)
+ }
+ } else {
+ accessory.context.HumiditySensor = accessory.context.HumiditySensor ?? {}
+ this.HumiditySensor = {
+ Name: `${accessory.displayName} Humidity Sensor`,
+ Service: accessory.getService(this.hap.Service.HumiditySensor) ?? this.accessory.addService(this.hap.Service.HumiditySensor) as Service,
+ CurrentRelativeHumidity: accessory.context.CurrentRelativeHumidity ?? 50,
+ }
+ accessory.context.HumiditySensor = this.HumiditySensor as object
+
+ // Initialize Humidity Sensor Characteristics
+ this.HumiditySensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.HumiditySensor.Name).getCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity).setProps({
+ minStep: 0.1,
+ }).onGet(() => {
+ return this.HumiditySensor!.CurrentRelativeHumidity!
+ })
+ }
+
+ // Retrieve initial values and updateHomekit
+ try {
+ this.debugLog('Retrieve initial values and update Homekit')
+ this.refreshStatus()
+ } catch (e: any) {
+ this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e.message ?? e}`)
+ }
+
+ // regisiter webhook event handler if enabled
+ try {
+ this.debugLog('Registering Webhook Event Handler')
+ this.registerWebhook()
+ } catch (e: any) {
+ this.errorLog(`failed to registerWebhook, Error: ${e.message ?? e}`)
+ }
+
+ // regisiter platform BLE event handler if enabled
+ try {
+ this.debugLog('Registering Platform BLE Event Handler')
+ this.registerPlatformBLE()
+ } catch (e: any) {
+ this.errorLog(`failed to registerPlatformBLE, Error: ${e.message ?? e}`)
+ }
+
+ // Start an update interval
+ interval(this.deviceRefreshRate * 1000)
+ .pipe(skipWhile(() => this.meterUpdateInProgress))
+ .subscribe(async () => {
+ await this.refreshStatus()
+ })
+ }
+
+ async BLEparseStatus(): Promise {
+ await this.debugLog('BLEparseStatus')
+ await this.debugLog(`(temperature, humidity) = BLE:(${this.serviceData.celsius}, ${this.serviceData.humidity}), current:(${this.TemperatureSensor?.CurrentTemperature}, ${this.HumiditySensor?.CurrentRelativeHumidity})`)
+
+ // CurrentRelativeHumidity
+ if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) {
+ this.HumiditySensor.CurrentRelativeHumidity = validHumidity(this.serviceData.humidity, 0, 100)
+ await this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`)
+ }
+ // Current Temperature
+ if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) {
+ const CELSIUS = this.serviceData.celsius < 0 ? 0 : this.serviceData.celsius > 100 ? 100 : this.serviceData.celsius
+ this.TemperatureSensor.CurrentTemperature = CELSIUS
+ await this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`)
+ }
+ // BatteryLevel
+ this.Battery.BatteryLevel = this.serviceData.battery
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
+ // StatusLowBattery
+ this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
+ : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
+ }
+
+ async openAPIparseStatus(): Promise {
+ await this.debugLog('openAPIparseStatus')
+ await this.debugLog(`(temperature, humidity) = OpenAPI:(${this.deviceStatus.temperature}, ${this.deviceStatus.humidity}), current:(${this.TemperatureSensor?.CurrentTemperature}, ${this.HumiditySensor?.CurrentRelativeHumidity})`)
+
+ // CurrentRelativeHumidity
+ if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) {
+ this.HumiditySensor.CurrentRelativeHumidity = this.deviceStatus.humidity
+ await this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`)
+ }
+
+ // CurrentTemperature
+ if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) {
+ this.TemperatureSensor.CurrentTemperature = this.deviceStatus.temperature
+ await this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`)
+ }
+
+ // BatteryLevel
+ this.Battery.BatteryLevel = this.deviceStatus.battery
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
+
+ // StatusLowBattery
+ this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
+ : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
+
+ // FirmwareVersion
+ if (this.deviceStatus.version) {
+ const version = this.deviceStatus.version.toString()
+ this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`)
+ const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0'
+ this.accessory
+ .getService(this.hap.Service.AccessoryInformation)!
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
+ .updateValue(deviceVersion)
+ this.accessory.context.version = deviceVersion
+ this.debugSuccessLog(`v: ${this.accessory.context.version}`)
+ }
+ }
+
+ async parseStatusWebhook(): Promise {
+ await this.debugLog('parseStatusWebhook')
+ await this.debugLog(`(scale, temperature, humidity) = Webhook:(${this.webhookContext.scale}, ${convertUnits(this.webhookContext.temperature, this.webhookContext.scale, (this.device as meterConfig).convertUnitTo)}, ${this.webhookContext.humidity}) current:(${this.TemperatureSensor?.CurrentTemperature}, ${this.HumiditySensor?.CurrentRelativeHumidity})`)
+ // Check if the scale is not CELSIUS
+ if (this.webhookContext.scale !== 'CELSIUS' && (this.device as meterConfig).convertUnitTo === undefined) {
+ await this.warnLog(`received a non-CELSIUS Webhook scale: ${this.webhookContext.scale}, Use the *convertUnitsTo* config under Hub settings, if displaying incorrectly in HomeKit.`)
+ }
+
+ // CurrentRelativeHumidity
+ if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) {
+ this.HumiditySensor.CurrentRelativeHumidity = this.webhookContext.humidity
+ await this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}`)
+ }
+
+ // CurrentTemperature
+ if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) {
+ this.TemperatureSensor.CurrentTemperature = convertUnits(this.webhookContext.temperature, this.webhookContext.scale, (this.device as meterConfig).convertUnitTo)
+ await this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}`)
+ }
+ }
+
+ /**
+ * Asks the SwitchBot API for the latest device information
+ */
+ async refreshStatus(): Promise {
+ if (!this.device.enableCloudService && this.OpenAPI) {
+ await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`)
+ } else if (this.BLE) {
+ await this.BLERefreshStatus()
+ } else if (this.OpenAPI && this.platform.config.credentials?.token) {
+ await this.openAPIRefreshStatus()
+ } else {
+ await this.offlineOff()
+ await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`)
+ }
+ }
+
+ async BLERefreshStatus(): Promise {
+ await this.debugLog('BLERefreshStatus')
+ const switchBotBLE = await this.switchbotBLE()
+ if (switchBotBLE === undefined) {
+ await this.BLERefreshConnection(switchBotBLE)
+ } else {
+ // Start to monitor advertisement packets
+ (async () => {
+ // Start to monitor advertisement packets
+ const serviceData = await this.monitorAdvertisementPackets(switchBotBLE) as meterProServiceData
+ // Update HomeKit
+ if (serviceData.model === SwitchBotBLEModel.MeterPro && serviceData.modelName === SwitchBotBLEModelName.MeterPro) {
+ this.serviceData = serviceData
+ await this.BLEparseStatus()
+ await this.updateHomeKitCharacteristics()
+ } else {
+ await this.errorLog(`failed to get serviceData, serviceData: ${JSON.stringify(serviceData)}`)
+ await this.BLERefreshConnection(switchBotBLE)
+ }
+ })()
+ }
+ }
+
+ async registerPlatformBLE(): Promise {
+ await this.debugLog('registerPlatformBLE')
+ if (this.config.options?.BLE) {
+ await this.debugLog('is listening to Platform BLE.')
+ try {
+ const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId)
+ this.device.bleMac = formattedDeviceId
+ await this.debugLog(`bleMac: ${this.device.bleMac}`)
+ this.platform.bleEventHandler[this.device.bleMac] = async (context: meterProServiceData) => {
+ try {
+ await this.debugLog(`received BLE: ${JSON.stringify(context)}`)
+ this.serviceData = context
+ await this.BLEparseStatus()
+ await this.updateHomeKitCharacteristics()
+ } catch (e: any) {
+ await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`)
+ }
+ }
+ } catch (error) {
+ await this.errorLog(`failed to format device ID as MAC, Error: ${error}`)
+ }
+ } else {
+ await this.debugLog('is not listening to Platform BLE')
+ }
+ }
+
+ async openAPIRefreshStatus(): Promise {
+ await this.debugLog('openAPIRefreshStatus')
+ try {
+ const { body } = await this.deviceRefreshStatus()
+ const deviceStatus: any = await body
+ await this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
+ if (await this.successfulStatusCodes(deviceStatus)) {
+ await this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
+ this.deviceStatus = deviceStatus.body
+ await this.openAPIparseStatus()
+ await this.updateHomeKitCharacteristics()
+ } else {
+ await this.debugWarnLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
+ await this.debugWarnLog(deviceStatus)
+ }
+ } catch (e: any) {
+ await this.apiError(e)
+ await this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
+ }
+ }
+
+ async registerWebhook() {
+ if (this.device.webhook) {
+ await this.debugLog('is listening webhook.')
+ this.platform.webhookEventHandler[this.device.deviceId] = async (context: meterProWebhookContext) => {
+ try {
+ await this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
+ this.webhookContext = context
+ await this.parseStatusWebhook()
+ await this.updateHomeKitCharacteristics()
+ } catch (e: any) {
+ await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`)
+ }
+ }
+ } else {
+ await this.debugLog('is not listening webhook.')
+ }
+ }
+
+ /**
+ * Updates the status for each of the HomeKit Characteristics
+ */
+ async updateHomeKitCharacteristics(): Promise {
+ // CurrentRelativeHumidity
+ if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) {
+ await this.updateCharacteristic(this.HumiditySensor.Service, this.hap.Characteristic.CurrentRelativeHumidity, this.HumiditySensor.CurrentRelativeHumidity, 'CurrentRelativeHumidity')
+ }
+ // CurrentTemperature
+ if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) {
+ await this.updateCharacteristic(this.TemperatureSensor.Service, this.hap.Characteristic.CurrentTemperature, this.TemperatureSensor.CurrentTemperature, 'CurrentTemperature')
+ }
+ // BatteryLevel
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel, 'BatteryLevel')
+ // StatusLowBattery
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery, 'StatusLowBattery')
+ }
+
+ async BLERefreshConnection(switchbot: any): Promise {
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
+ await this.warnLog('Using OpenAPI Connection to Refresh Status')
+ await this.openAPIRefreshStatus()
+ }
+ }
+
+ async offlineOff(): Promise {
+ if (this.device.offline) {
+ if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) {
+ this.HumiditySensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, 50)
+ }
+ if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) {
+ this.TemperatureSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, 30)
+ }
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, 100)
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL)
+ }
+ }
+
+ async apiError(e: any): Promise {
+ if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) {
+ this.HumiditySensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, e)
+ }
+ if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) {
+ this.TemperatureSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, e)
+ }
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e)
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e)
+ }
+}
diff --git a/src/device/motion.ts b/src/device/motion.ts
index ae8900da..06fcd560 100644
--- a/src/device/motion.ts
+++ b/src/device/motion.ts
@@ -120,9 +120,7 @@ export class Motion extends deviceBase {
accessory.context.LightSensor = this.LightSensor as object
// Initialize LightSensor Characteristics
- this.LightSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name).setCharacteristic(this.hap.Characteristic.StatusActive, true).getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel).onGet(() => {
- return this.LightSensor!.CurrentAmbientLightLevel
- })
+ this.LightSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name).setCharacteristic(this.hap.Characteristic.StatusActive, true)
};
// Retrieve initial values and updateHomekit
diff --git a/src/irdevice/airconditioner.ts b/src/irdevice/airconditioner.ts
index 4eab629a..f4c0f440 100644
--- a/src/irdevice/airconditioner.ts
+++ b/src/irdevice/airconditioner.ts
@@ -314,7 +314,7 @@ export class AirConditioner extends irdeviceBase {
async pushChanges(bodyChange: any): Promise {
await this.debugLog('pushChanges')
if (this.device.connectionType === 'OpenAPI' && !this.disablePushDetail) {
- await this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
+ await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
const deviceStatus: any = await body
diff --git a/src/irdevice/airpurifier.ts b/src/irdevice/airpurifier.ts
index a3f98d73..effda98e 100644
--- a/src/irdevice/airpurifier.ts
+++ b/src/irdevice/airpurifier.ts
@@ -211,7 +211,7 @@ export class AirPurifier extends irdeviceBase {
async pushChanges(bodyChange: any): Promise {
await this.debugLog('pushChanges')
if (this.device.connectionType === 'OpenAPI') {
- this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
+ await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
const deviceStatus: any = await body
diff --git a/src/irdevice/camera.ts b/src/irdevice/camera.ts
index e42eee90..96882d06 100644
--- a/src/irdevice/camera.ts
+++ b/src/irdevice/camera.ts
@@ -98,7 +98,7 @@ export class Camera extends irdeviceBase {
async pushChanges(bodyChange: any): Promise {
await this.debugLog('pushChanges')
if (this.device.connectionType === 'OpenAPI') {
- this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
+ await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
const deviceStatus: any = await body
diff --git a/src/irdevice/fan.ts b/src/irdevice/fan.ts
index 929fda97..ac761e15 100644
--- a/src/irdevice/fan.ts
+++ b/src/irdevice/fan.ts
@@ -189,7 +189,7 @@ export class IRFan extends irdeviceBase {
async pushChanges(bodyChange: any): Promise {
await this.debugLog('pushChanges')
if (this.device.connectionType === 'OpenAPI') {
- this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
+ await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
const deviceStatus: any = await body
diff --git a/src/irdevice/irdevice.ts b/src/irdevice/irdevice.ts
index 4c4f2768..2a055fcc 100644
--- a/src/irdevice/irdevice.ts
+++ b/src/irdevice/irdevice.ts
@@ -175,7 +175,7 @@ export abstract class irdeviceBase {
async successfulPushChange(deviceStatus: any, bodyChange: any) {
this.debugSuccessLog(`deviceStatus StatusCode: ${deviceStatus.statusCode}`)
- this.successLog(`request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`)
+ this.successLog(`request to SwitchBot API, body: ${JSON.stringify(bodyChange)} sent successfully`)
}
async pushChangeError(e: Error) {
diff --git a/src/irdevice/light.ts b/src/irdevice/light.ts
index 29b7dc01..e0ba6614 100644
--- a/src/irdevice/light.ts
+++ b/src/irdevice/light.ts
@@ -196,7 +196,7 @@ export class Light extends irdeviceBase {
async pushChanges(bodyChange: any, On: boolean): Promise {
this.debugLog('pushChanges')
if (this.device.connectionType === 'OpenAPI') {
- this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
+ await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
const deviceStatus: any = await body
diff --git a/src/irdevice/other.ts b/src/irdevice/other.ts
index 20898eb1..6ad69fbc 100644
--- a/src/irdevice/other.ts
+++ b/src/irdevice/other.ts
@@ -445,7 +445,7 @@ export class Others extends irdeviceBase {
async pushChanges(bodyChange: any): Promise {
await this.debugLog('pushChanges')
if (this.device.connectionType === 'OpenAPI') {
- this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
+ await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
const deviceStatus: any = await body
diff --git a/src/irdevice/tv.ts b/src/irdevice/tv.ts
index ce4229da..d8737728 100644
--- a/src/irdevice/tv.ts
+++ b/src/irdevice/tv.ts
@@ -344,7 +344,7 @@ export class TV extends irdeviceBase {
async pushTVChanges(bodyChange: any): Promise {
await this.debugLog('pushTVChanges')
if (this.device.connectionType === 'OpenAPI') {
- await this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
+ await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
const deviceStatus: any = await body
diff --git a/src/irdevice/vacuumcleaner.ts b/src/irdevice/vacuumcleaner.ts
index 4d5554c9..08ebbed8 100644
--- a/src/irdevice/vacuumcleaner.ts
+++ b/src/irdevice/vacuumcleaner.ts
@@ -95,7 +95,7 @@ export class VacuumCleaner extends irdeviceBase {
async pushChanges(bodyChange: any): Promise {
await this.debugLog('pushChanges')
if (this.device.connectionType === 'OpenAPI') {
- await this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
+ await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
const deviceStatus: any = await body
diff --git a/src/irdevice/waterheater.ts b/src/irdevice/waterheater.ts
index fc1031b8..41469ac3 100644
--- a/src/irdevice/waterheater.ts
+++ b/src/irdevice/waterheater.ts
@@ -96,7 +96,7 @@ export class WaterHeater extends irdeviceBase {
async pushChanges(bodyChange: any): Promise {
await this.debugLog('pushChanges')
if (this.device.connectionType === 'OpenAPI') {
- this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`)
+ await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`)
try {
const { body } = await this.pushChangeRequest(bodyChange)
const deviceStatus: any = await body
diff --git a/src/platform.ts b/src/platform.ts
index af75e68d..ee9fac31 100644
--- a/src/platform.ts
+++ b/src/platform.ts
@@ -39,6 +39,7 @@ import { StripLight } from './device/lightstrip.js'
import { Lock } from './device/lock.js'
import { Meter } from './device/meter.js'
import { MeterPlus } from './device/meterplus.js'
+import { MeterPro } from './device/meterpro.js'
import { Motion } from './device/motion.js'
import { Plug } from './device/plug.js'
import { RobotVacuumCleaner } from './device/robotvacuumcleaner.js'
@@ -630,6 +631,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
'Meter': this.createMeter.bind(this),
'MeterPlus': this.createMeterPlus.bind(this),
'Meter Plus (JP)': this.createMeterPlus.bind(this),
+ 'Meter Pro': this.createMeterPro.bind(this),
'WoIOSensor': this.createIOSensor.bind(this),
'Water Detector': this.createWaterDetector.bind(this),
'Motion Sensor': this.createMotion.bind(this),
@@ -960,6 +962,69 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
}
}
+ private async createMeterPro(device: device & devicesConfig) {
+ const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)
+
+ // see if an accessory with the same uuid has already been registered and restored from
+ // the cached devices we stored in the `configureAccessory` method above
+ const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid)
+
+ if (existingAccessory) {
+ // the accessory already exists
+ if (await this.registerDevice(device)) {
+ // console.log("existingAccessory", existingAccessory);
+ // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
+ existingAccessory.context.device = device
+ existingAccessory.context.model = SwitchBotModel.MeterPro ?? SwitchBotModel.MeterProCO2
+ existingAccessory.context.deviceId = device.deviceId
+ existingAccessory.context.deviceType = device.deviceType
+ existingAccessory.displayName = device.configDeviceName
+ ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
+ : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
+ existingAccessory.context.connectionType = await this.connectionType(device)
+ existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
+ this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`)
+ this.api.updatePlatformAccessories([existingAccessory])
+ // create the accessory handler for the restored accessory
+ // this is imported from `platformAccessory.ts`
+ new MeterPro(this, existingAccessory, device)
+ await this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`)
+ } else {
+ this.unregisterPlatformAccessories(existingAccessory)
+ }
+ } else if (await this.registerDevice(device)) {
+ // create a new accessory
+ const accessory = new this.api.platformAccessory(device.configDeviceName
+ ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
+ : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid)
+
+ // store a copy of the device object in the `accessory.context`
+ // the `context` property can be used to store any data about the accessory you may need
+ accessory.context.device = device
+ accessory.context.model = SwitchBotModel.MeterPro ?? SwitchBotModel.MeterProCO2
+ accessory.context.deviceId = device.deviceId
+ accessory.context.deviceType = device.deviceType
+ accessory.displayName = device.configDeviceName
+ ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
+ : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName)
+ accessory.context.connectionType = await this.connectionType(device)
+ accessory.context.connectionType = await this.connectionType(device)
+ accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0'
+ const newOrExternal = !device.external ? 'Adding new' : 'Loading external'
+ await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`)
+ // create the accessory handler for the newly create accessory
+ // this is imported from `platformAccessory.ts`
+ new MeterPro(this, accessory, device)
+ await this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`)
+
+ // publish device externally or link the accessory to your platform
+ this.externalOrPlatform(device, accessory)
+ this.accessories.push(accessory)
+ } else {
+ await this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`)
+ }
+ }
+
private async createHub2(device: device & devicesConfig) {
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)