diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e4c40e5..398013cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/) +## [3.8.2](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v3.8.2) (2024-09-14) + +### What's Changed +- Improved macAddress format and finding of invalid formating. +- Housekeeping and updated dependencies. + +**Full Changelog**: https://github.com/OpenWonderLabs/homebridge-switchbot/compare/v3.8.1...v3.8.2 + ## [3.8.1](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v3.8.1) (2024-09-13) ### What's Changed diff --git a/package-lock.json b/package-lock.json index 0e24dcf2..d0d13728 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@switchbot/homebridge-switchbot", - "version": "3.8.1", + "version": "3.8.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@switchbot/homebridge-switchbot", - "version": "3.8.1", + "version": "3.8.2", "funding": [ { "type": "Paypal", @@ -34,10 +34,10 @@ "@types/fs-extra": "^11.0.4", "@types/jest": "^29.5.13", "@types/mdast": "^4.0.4", - "@types/node": "^22.5.4", + "@types/node": "^22.5.5", "@types/semver": "^7.5.8", "@types/source-map-support": "^0.5.10", - "@vitest/coverage-v8": "^2.1.0", + "@vitest/coverage-v8": "^2.1.1", "eslint": "^9.10.0", "eslint-plugin-format": "^0.1.2", "homebridge": "^1.8.4", @@ -50,7 +50,7 @@ "typedoc": "^0.26.7", "typescript": "^5.6.2", "typescript-axios-wb": "^1.0.3", - "vitest": "^2.1.0" + "vitest": "^2.1.1" }, "engines": { "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.11 || ^2.0.0-alpha.10", @@ -3410,46 +3410,46 @@ "optional": true }, "node_modules/@shikijs/core": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.17.5.tgz", - "integrity": "sha512-JDgFZbJvfZ1g0lRVHtPTv6n2MwWnbTSGwncL/Qmlg7BZBzHCcDY2CxYGkNUm7k+lljOrFzXFGh38s8CRRZH+TQ==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.17.6.tgz", + "integrity": "sha512-9ztslig6/YmCg/XwESAXbKjAjOhaq6HVced9NY6qcbDz1X5g/S90Wco2vMjBNX/6V71ASkzri76JewSGPa7kiQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/engine-javascript": "1.17.5", - "@shikijs/engine-oniguruma": "1.17.5", - "@shikijs/types": "1.17.5", + "@shikijs/engine-javascript": "1.17.6", + "@shikijs/engine-oniguruma": "1.17.6", + "@shikijs/types": "1.17.6", "@shikijs/vscode-textmate": "^9.2.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.2" } }, "node_modules/@shikijs/engine-javascript": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.17.5.tgz", - "integrity": "sha512-129knB7yGxq51i5f9ci1lsrC/9rJwo7yzOmHVjQIRk+e1C0caaSwzm4mhLJ506ui0vEmQZ9LzY6a/crW1UsReA==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.17.6.tgz", + "integrity": "sha512-5EEZj8tVcierNxm4V0UMS2PVoflb0UJPalWWV8l9rRg+oOfnr5VivqBJbkyq5grltVPvByIXvVbY8GSM/356jQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.17.5", - "oniguruma-to-js": "0.4.0" + "@shikijs/types": "1.17.6", + "oniguruma-to-js": "0.4.3" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.17.5.tgz", - "integrity": "sha512-GcuDWdUcs06sCoRS/JwbcO8M55MOvirTs3wIR7E6pMoePJWgAxhIYDQHURvSrgKgyUrTl3EKwujHljivS5BJVA==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.17.6.tgz", + "integrity": "sha512-NLfWDMXFYe0nDHFbEoyZdz89aIIey3bTfF3zLYSUNTXks5s4uinZVmuPOFf1HfTeGqIn8uErJSBc3VnpJO7Alw==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.17.5", + "@shikijs/types": "1.17.6", "@shikijs/vscode-textmate": "^9.2.2" } }, "node_modules/@shikijs/types": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.17.5.tgz", - "integrity": "sha512-xDIczjZ7QB6opNrCObX/6/78Jb/BFglRPo7E7f9swd1TCabhumOLsv23103pNUOMZrJYARUkHJpEx7ryFLM3FA==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.17.6.tgz", + "integrity": "sha512-ndTFa2TJi2w51ddKQDn3Jy8f6K4E5Q2x3dA3Hmsd3+YmxDQ10UWHjcw7VbVbKzv3VcUvYPLy+z9neqytSzUMUg==", "dev": true, "license": "MIT", "dependencies": { @@ -3785,9 +3785,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.5.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", - "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "version": "22.5.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz", + "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==", "dev": true, "license": "MIT", "dependencies": { @@ -4067,9 +4067,9 @@ "license": "ISC" }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.0.tgz", - "integrity": "sha512-yqCkr2nrV4o58VcVMxTVkS6Ggxzy7pmSD8JbTbhbH5PsQfUIES1QT716VUzo33wf2lX9EcWYdT3Vl2MMmjR59g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.1.tgz", + "integrity": "sha512-md/A7A3c42oTT8JUHSqjP5uKTWJejzUW4jalpvs+rZ27gsURsMU8DEb+8Jf8C6Kj2gwfSHJqobDNBuoqlm0cFw==", "dev": true, "license": "MIT", "dependencies": { @@ -4090,8 +4090,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.0", - "vitest": "2.1.0" + "@vitest/browser": "2.1.1", + "vitest": "2.1.1" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -4100,9 +4100,9 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.3.tgz", - "integrity": "sha512-EKcwtabnZQtf/f6apYzlbYY4lag0qDbMBb6U3O6hBKSXvftPLhLTEMvHcpSSdumeDxzWovh1Avx3Q1Az2xd9lA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.4.tgz", + "integrity": "sha512-kudjgefmJJ7xQ2WfbUU6pZbm7Ou4gLYRaao/8Ynide3G0QhVKHd978sDyWX4KOH0CCMH9cyrGAkFd55eGzJ48Q==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4124,14 +4124,14 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.0.tgz", - "integrity": "sha512-N3/xR4fSu0+6sVZETEtPT1orUs2+Y477JOXTcU3xKuu3uBlsgbD7/7Mz2LZ1Jr1XjwilEWlrIgSCj4N1+5ZmsQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", + "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.0", - "@vitest/utils": "2.1.0", + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" }, @@ -4140,9 +4140,9 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.0.tgz", - "integrity": "sha512-ZxENovUqhzl+QiOFpagiHUNUuZ1qPd5yYTCYHomGIZOFArzn4mgX2oxZmiAItJWAaXHG6bbpb/DpSPhlk5DgtA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.1.tgz", + "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", "dev": true, "license": "MIT", "dependencies": { @@ -4154,7 +4154,7 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.0", + "@vitest/spy": "2.1.1", "msw": "^2.3.5", "vite": "^5.0.0" }, @@ -4178,9 +4178,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.0.tgz", - "integrity": "sha512-7sxf2F3DNYatgmzXXcTh6cq+/fxwB47RIQqZJFoSH883wnVAoccSRT6g+dTKemUBo8Q5N4OYYj1EBXLuRKvp3Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", + "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4191,13 +4191,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.0.tgz", - "integrity": "sha512-D9+ZiB8MbMt7qWDRJc4CRNNUlne/8E1X7dcKhZVAbcOKG58MGGYVDqAq19xlhNfMFZsW0bpVKgztBwks38Ko0w==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.1.tgz", + "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.0", + "@vitest/utils": "2.1.1", "pathe": "^1.1.2" }, "funding": { @@ -4205,13 +4205,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.0.tgz", - "integrity": "sha512-x69CygGMzt9VCO283K2/FYQ+nBrOj66OTKpsPykjCR4Ac3lLV+m85hj9reaIGmjBSsKzVvbxWmjWE3kF5ha3uQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.1.tgz", + "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.0", + "@vitest/pretty-format": "2.1.1", "magic-string": "^0.30.11", "pathe": "^1.1.2" }, @@ -4220,9 +4220,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.0.tgz", - "integrity": "sha512-IXX5NkbdgTYTog3F14i2LgnBc+20YmkXMx0IWai84mcxySUDRgm0ihbOfR4L0EVRBDFG85GjmQQEZNNKVVpkZw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.1.tgz", + "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", "dev": true, "license": "MIT", "dependencies": { @@ -4233,13 +4233,13 @@ } }, "node_modules/@vitest/utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.0.tgz", - "integrity": "sha512-rreyfVe0PuNqJfKYUwfPDfi6rrp0VSu0Wgvp5WBqJonP+4NvXHk48X6oBam1Lj47Hy6jbJtnMj3OcRdrkTP0tA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.1.tgz", + "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.0", + "@vitest/pretty-format": "2.1.1", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" }, @@ -4248,45 +4248,45 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.4.tgz", - "integrity": "sha512-oNwn+BAt3n9dK9uAYvI+XGlutwuTq/wfj4xCBaZCqwwVIGtD7D6ViihEbyYZrDHIHTDE3Q6oL3/hqmAyFEy9DQ==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.5.tgz", + "integrity": "sha512-ZrxcY8JMoV+kgDrmRwlDufz0SjDZ7jfoNZiIBluAACMBmgr55o/jTbxnyrccH6VSJXnFaDI4Ik1UFCiq9r8i7w==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.4", + "@vue/shared": "3.5.5", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.4.tgz", - "integrity": "sha512-yP9RRs4BDLOLfldn6ah+AGCNovGjMbL9uHvhDHf5wan4dAHLnFGOkqtfE7PPe4HTXIqE7l/NILdYw53bo1C8jw==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.5.tgz", + "integrity": "sha512-HSvK5q1gmBbxRse3S0Wt34RcKuOyjDJKDDMuF3i7NC+QkDFrbAqw8NnrEm/z7zFDxWZa4/5eUwsBOMQzm1RHBA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-core": "3.5.4", - "@vue/shared": "3.5.4" + "@vue/compiler-core": "3.5.5", + "@vue/shared": "3.5.5" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.4.tgz", - "integrity": "sha512-P+yiPhL+NYH7m0ZgCq7AQR2q7OIE+mpAEgtkqEeH9oHSdIRvUO+4X6MPvblJIWcoe4YC5a2Gdf/RsoyP8FFiPQ==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.5.tgz", + "integrity": "sha512-MzBHDxwZhgQPHrwJ5tj92gdTYRCuPDSZr8PY3+JFv8cv2UD5/WayH5yo0kKCkKfrtJhc39jNSMityHrkMSbfnA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.4", - "@vue/compiler-dom": "3.5.4", - "@vue/compiler-ssr": "3.5.4", - "@vue/shared": "3.5.4", + "@vue/compiler-core": "3.5.5", + "@vue/compiler-dom": "3.5.5", + "@vue/compiler-ssr": "3.5.5", + "@vue/shared": "3.5.5", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.44", @@ -4294,21 +4294,21 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.4.tgz", - "integrity": "sha512-acESdTXsxPnYr2C4Blv0ggx5zIFMgOzZmYU2UgvIff9POdRGbRNBHRyzHAnizcItvpgerSKQbllUc9USp3V7eg==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.5.tgz", + "integrity": "sha512-oFasHnpv/upubjJEmqiTKQYb4qS3ziJddf4UVWuFw6ebk/QTrTUc+AUoTJdo39x9g+AOQBzhOU0ICCRuUjvkmw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.5.4", - "@vue/shared": "3.5.4" + "@vue/compiler-dom": "3.5.5", + "@vue/shared": "3.5.5" } }, "node_modules/@vue/shared": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.4.tgz", - "integrity": "sha512-L2MCDD8l7yC62Te5UUyPVpmexhL9ipVnYRw9CsWfm/BGRL5FwDX4a25bcJ/OJSD3+Hx+k/a8LDKcG2AFdJV3BA==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.5.tgz", + "integrity": "sha512-0KyMXyEgnmFAs6rNUL+6eUHtUCqCaNrVd+AW3MX3LyA0Yry5SA0Km03CDKiOua1x1WWnIr+W9+S0GMFoSDWERQ==", "dev": true, "license": "MIT", "peer": true @@ -6125,9 +6125,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.22", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.22.tgz", - "integrity": "sha512-tKYm5YHPU1djz0O+CGJ+oJIvimtsCcwR2Z9w7Skh08lUdyzXY5djods3q+z2JkWdb7tCcmM//eVavSRAiaPRNg==", + "version": "1.5.23", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.23.tgz", + "integrity": "sha512-mBhODedOXg4v5QWwl21DjM5amzjmI1zw9EPrPK/5Wx7C8jt33bpZNrC7OhHUG3pxRtbLpr3W2dXT+Ph1SsfRZA==", "dev": true, "license": "ISC" }, @@ -6775,14 +6775,14 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.5.0.tgz", - "integrity": "sha512-vwDNuxlAlbZJ3DjHo6GnfZrmMlJBLFrkOLBV/rYvVnLFD+x54u9VyJcGOfJ2DK9d1cd3a/C/vtBrbBNgAC6Mrg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.6.0.tgz", + "integrity": "sha512-sA6ljy6dL/9cM5ruZ/pMqRVt0FQ4Z7mbQWlBYpyX9941LVfm65d2jl2k1ZbWD3ud9Wm+/NKgOvRnAatsKhMJbA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.4.0", - "@typescript-eslint/utils": "^8.4.0", + "@typescript-eslint/types": "^8.5.0", + "@typescript-eslint/utils": "^8.5.0", "minimatch": "^9.0.5", "natural-compare-lite": "^1.4.0" }, @@ -6793,7 +6793,7 @@ "astro-eslint-parser": "^1.0.2", "eslint": ">=8.0.0", "svelte": ">=3.0.0", - "svelte-eslint-parser": "^0.41.0", + "svelte-eslint-parser": "^0.41.1", "vue-eslint-parser": ">=9.0.0" }, "peerDependenciesMeta": { @@ -12051,9 +12051,9 @@ } }, "node_modules/oniguruma-to-js": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.0.tgz", - "integrity": "sha512-GwNFPQygkpDjO9MOr54Rqi01dGS+h9VAS//Qxz9lTN5B09CxqiIc7rydvdV+Ex2Z8Vk+zqfHH7hU6ePn8uf+Mg==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", + "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13704,16 +13704,16 @@ } }, "node_modules/shiki": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.17.5.tgz", - "integrity": "sha512-8i4+fbTlnJPUYkgBEZ92QKmK3Gr23n2YVwqwyz0e+VmXqKpJZuV6P/CY00gSGHDXXjXT5l0BLwsMfO2Pe52TLQ==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.17.6.tgz", + "integrity": "sha512-RejGugKpDM75vh6YtF9R771acxHRDikC/01kxsUGW+Pnaz3pTY+c8aZB5CnD7p0vuFPs1HaoAIU/4E+NCfS+mQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/core": "1.17.5", - "@shikijs/engine-javascript": "1.17.5", - "@shikijs/engine-oniguruma": "1.17.5", - "@shikijs/types": "1.17.5", + "@shikijs/core": "1.17.6", + "@shikijs/engine-javascript": "1.17.6", + "@shikijs/engine-oniguruma": "1.17.6", + "@shikijs/types": "1.17.6", "@shikijs/vscode-textmate": "^9.2.2", "@types/hast": "^3.0.4" } @@ -15319,9 +15319,9 @@ } }, "node_modules/vite-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.0.tgz", - "integrity": "sha512-+ybYqBVUjYyIscoLzMWodus2enQDZOpGhcU6HdOVD6n8WZdk12w1GFL3mbnxLs7hPtRtqs1Wo5YF6/Tsr6fmhg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.1.tgz", + "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", "dev": true, "license": "MIT", "dependencies": { @@ -15341,19 +15341,19 @@ } }, "node_modules/vitest": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.0.tgz", - "integrity": "sha512-XuuEeyNkqbfr0FtAvd9vFbInSSNY1ykCQTYQ0sj9wPy4hx+1gR7gqVNdW0AX2wrrM1wWlN5fnJDjF9xG6mYRSQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz", + "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "2.1.0", - "@vitest/mocker": "2.1.0", - "@vitest/pretty-format": "^2.1.0", - "@vitest/runner": "2.1.0", - "@vitest/snapshot": "2.1.0", - "@vitest/spy": "2.1.0", - "@vitest/utils": "2.1.0", + "@vitest/expect": "2.1.1", + "@vitest/mocker": "2.1.1", + "@vitest/pretty-format": "^2.1.1", + "@vitest/runner": "2.1.1", + "@vitest/snapshot": "2.1.1", + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", "chai": "^5.1.1", "debug": "^4.3.6", "magic-string": "^0.30.11", @@ -15364,7 +15364,7 @@ "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.0", + "vite-node": "2.1.1", "why-is-node-running": "^2.3.0" }, "bin": { @@ -15379,8 +15379,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.0", - "@vitest/ui": "2.1.0", + "@vitest/browser": "2.1.1", + "@vitest/ui": "2.1.1", "happy-dom": "*", "jsdom": "*" }, diff --git a/package.json b/package.json index aaac7ea3..362a043f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@switchbot/homebridge-switchbot", "displayName": "SwitchBot", "type": "module", - "version": "3.8.1", + "version": "3.8.2", "description": "The SwitchBot plugin allows you to access your SwitchBot device(s) from HomeKit.", "author": "SwitchBot (https://github.com/SwitchBot)", "contributors": [ @@ -92,10 +92,10 @@ "@types/fs-extra": "^11.0.4", "@types/jest": "^29.5.13", "@types/mdast": "^4.0.4", - "@types/node": "^22.5.4", + "@types/node": "^22.5.5", "@types/semver": "^7.5.8", "@types/source-map-support": "^0.5.10", - "@vitest/coverage-v8": "^2.1.0", + "@vitest/coverage-v8": "^2.1.1", "eslint": "^9.10.0", "eslint-plugin-format": "^0.1.2", "homebridge": "^1.8.4", @@ -108,7 +108,7 @@ "typedoc": "^0.26.7", "typescript": "^5.6.2", "typescript-axios-wb": "^1.0.3", - "vitest": "^2.1.0" + "vitest": "^2.1.1" }, "directories": { "doc": "docs" diff --git a/src/device/blindtilt.ts b/src/device/blindtilt.ts index 3326c5c8..410ce4c8 100644 --- a/src/device/blindtilt.ts +++ b/src/device/blindtilt.ts @@ -18,7 +18,7 @@ import type { blindTiltWebhookContext } from '../types/devicewebhookstatus.js' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' -import { BlindTiltMappingMode } from '../utils.js' +import { BlindTiltMappingMode, formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' export class BlindTilt extends deviceBase { @@ -482,17 +482,22 @@ export class BlindTilt extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: blindTiltServiceData) => { - 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}`) + 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: blindTiltServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -563,32 +568,38 @@ export class BlindTilt extends deviceBase { if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) { await this.debugLog(`BLEpushChanges On: ${this.WindowCovering.TargetPosition} OnCached: ${this.WindowCovering.CurrentPosition}`) const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - const { setPositionMode, Mode }: { setPositionMode: number, Mode: string } = await this.setPerformance() - await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`) - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac }) - .then(async (device_list: any) => { - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), setPositionMode) - }, + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + const { setPositionMode, Mode }: { setPositionMode: number, Mode: string } = await this.setPerformance() + await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac }) + .then(async (device_list: any) => { + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), setPositionMode) + }, + }) }) - }) - .then(async () => { - await this.successLog(`TargetPostion: ${this.WindowCovering.TargetPosition} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + .then(async () => { + await this.successLog(`TargetPostion: ${this.WindowCovering.TargetPosition} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`) diff --git a/src/device/bot.ts b/src/device/bot.ts index 394f7d24..d5846eb0 100644 --- a/src/device/bot.ts +++ b/src/device/bot.ts @@ -18,6 +18,7 @@ import type { botWebhookContext } from '../types/devicewebhookstatus.js' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' +import { formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' /** @@ -575,17 +576,22 @@ export class Bot extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: botServiceData) => { - 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}`) + 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: botServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -663,57 +669,63 @@ export class Bot extends deviceBase { if (this.On !== this.accessory.context.On || this.allowPush) { await this.debugLog(`BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`) const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - // if (switchbot !== false) { - await this.debugLog(`Bot Mode: ${this.botMode}`) - if (this.botMode === 'press') { - switchbot - .discover({ model: 'H', quick: true, id: this.device.bleMac }) - .then(async (device_list: { press: (arg0: { id: string | undefined }) => any }[]) => { - await this.infoLog(`On: ${this.On}`) - return await device_list[0].press({ id: this.device.bleMac }) - }) - .then(async () => { - await this.successLog(`On: ${this.On} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - setTimeout(async () => { - this.On = false + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + // if (switchbot !== false) { + await this.debugLog(`Bot Mode: ${this.botMode}`) + if (this.botMode === 'press') { + switchbot + .discover({ model: 'H', quick: true, id: this.device.bleMac }) + .then(async (device_list: { press: (arg0: { id: string | undefined }) => any }[]) => { + await this.infoLog(`On: ${this.On}`) + return await device_list[0].press({ id: this.device.bleMac }) + }) + .then(async () => { + await this.successLog(`On: ${this.On} sent over SwitchBot BLE, sent successfully`) await this.updateHomeKitCharacteristics() - this.debugLog(`On: ${this.On}, Switch Timeout`) - }, 500) - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else if (this.botMode === 'switch') { - switchbot - .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac }) - .then(async (device_list: any) => { - this.infoLog(`On: ${this.On}`) - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - if (this.On) { - return await device_list[0].turnOn({ id: this.device.bleMac }) - } else { - return await device_list[0].turnOff({ id: this.device.bleMac }) - } - }, + setTimeout(async () => { + this.On = false + await this.updateHomeKitCharacteristics() + this.debugLog(`On: ${this.On}, Switch Timeout`) + }, 500) }) - }) - .then(async () => { - await this.successLog(`On: ${this.On} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`Device Parameters not set for this Bot, please check the device configuration. Bot Mode: ${this.botMode}`) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else if (this.botMode === 'switch') { + switchbot + .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac }) + .then(async (device_list: any) => { + this.infoLog(`On: ${this.On}`) + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + if (this.On) { + return await device_list[0].turnOn({ id: this.device.bleMac }) + } else { + return await device_list[0].turnOff({ id: this.device.bleMac }) + } + }, + }) + }) + .then(async () => { + await this.successLog(`On: ${this.On} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`Device Parameters not set for this Bot, please check the device configuration. Bot Mode: ${this.botMode}`) + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No Changes (BLEpushChanges), On: ${this.On} OnCached: ${this.accessory.context.On}`) diff --git a/src/device/ceilinglight.ts b/src/device/ceilinglight.ts index af1c3fe2..ddc96d78 100644 --- a/src/device/ceilinglight.ts +++ b/src/device/ceilinglight.ts @@ -18,7 +18,7 @@ import type { ceilingLightProWebhookContext, ceilingLightWebhookContext } from ' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' -import { hs2rgb, m2hs } from '../utils.js' +import { formatDeviceIdAsMac, hs2rgb, m2hs } from '../utils.js' import { deviceBase } from './device.js' /** @@ -310,17 +310,22 @@ export class CeilingLight extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: ceilingLightServiceData | ceilingLightProServiceData) => { - 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}`) + 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: ceilingLightServiceData | ceilingLightProServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -416,35 +421,41 @@ export class CeilingLight extends deviceBase { if (this.LightBulb.On !== this.accessory.context.On) { await this.debugLog(`BLEpushChanges On: ${this.LightBulb.On} OnCached: ${this.accessory.context.On}`) const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - this.infoLog(`On: ${this.LightBulb.On}`) - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - if (this.LightBulb.On) { - return await device_list[0].turnOn({ id: this.device.bleMac }) - } else { - return await device_list[0].turnOff({ id: this.device.bleMac }) - } - }, + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + this.infoLog(`On: ${this.LightBulb.On}`) + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + if (this.LightBulb.On) { + return await device_list[0].turnOn({ id: this.device.bleMac }) + } else { + return await device_list[0].turnOff({ id: this.device.bleMac }) + } + }, + }) }) - }) - .then(async () => { - await this.successLog(`On: ${this.LightBulb.On} sent over SwitchBot BLE, sent successfully`) - this.LightBulb.On = false - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + .then(async () => { + await this.successLog(`On: ${this.LightBulb.On} sent over SwitchBot BLE, sent successfully`) + this.LightBulb.On = false + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushChanges): On: ${this.LightBulb.On}, OnCached: ${this.accessory.context.On}`) diff --git a/src/device/colorbulb.ts b/src/device/colorbulb.ts index 33e1862b..2a434459 100644 --- a/src/device/colorbulb.ts +++ b/src/device/colorbulb.ts @@ -18,7 +18,7 @@ import type { colorBulbWebhookContext } from '../types/devicewebhookstatus.js' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' -import { hs2rgb, m2hs, rgb2hs } from '../utils.js' +import { formatDeviceIdAsMac, hs2rgb, m2hs, rgb2hs } from '../utils.js' import { deviceBase } from './device.js' /** @@ -333,17 +333,22 @@ export class ColorBulb extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: colorBulbServiceData) => { - 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}`) + 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: colorBulbServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -451,35 +456,41 @@ export class ColorBulb extends deviceBase { if (this.LightBulb.On !== this.accessory.context.On) { await this.debugLog(`BLEpushChanges On: ${this.LightBulb.On}, OnCached: ${this.accessory.context.On}`) const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - await this.infoLog(`On: ${this.LightBulb.On}`) - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - if (this.LightBulb.On) { - return await device_list[0].turnOn({ id: this.device.bleMac }) - } else { - return await device_list[0].turnOff({ id: this.device.bleMac }) - } - }, + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + await this.infoLog(`On: ${this.LightBulb.On}`) + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + if (this.LightBulb.On) { + return await device_list[0].turnOn({ id: this.device.bleMac }) + } else { + return await device_list[0].turnOff({ id: this.device.bleMac }) + } + }, + }) }) - }) - .then(async () => { - await this.successLog(`On: ${this.LightBulb.On} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + .then(async () => { + await this.successLog(`On: ${this.LightBulb.On} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushChanges), On: ${this.LightBulb.On}, OnCached: ${this.accessory.context.On}`) @@ -490,26 +501,32 @@ export class ColorBulb extends deviceBase { await this.debugLog('BLEpushBrightnessChanges') if (this.LightBulb.Brightness !== this.accessory.context.Brightness) { const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - await this.infoLog(`Target Brightness: ${this.LightBulb.Brightness}`) - return await device_list[0].setBrightness(this.LightBulb.Brightness) - }) - .then(async () => { - await this.successLog(`Brightness: ${this.LightBulb.Brightness} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + await this.infoLog(`Target Brightness: ${this.LightBulb.Brightness}`) + return await device_list[0].setBrightness(this.LightBulb.Brightness) + }) + .then(async () => { + await this.successLog(`Brightness: ${this.LightBulb.Brightness} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushBrightnessChanges), Brightness: ${this.LightBulb.Brightness}, BrightnessCached: ${this.accessory.context.Brightness}`) @@ -522,26 +539,32 @@ export class ColorBulb extends deviceBase { const kelvin = Math.round(1000000 / Number(this.LightBulb.ColorTemperature)) this.accessory.context.kelvin = kelvin const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - await this.infoLog(`ColorTemperature: ${this.LightBulb.ColorTemperature}`) - return await device_list[0].setColorTemperature(kelvin) - }) - .then(async () => { - await this.successLog(`ColorTemperature: ${this.LightBulb.ColorTemperature} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushRGBChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + await this.infoLog(`ColorTemperature: ${this.LightBulb.ColorTemperature}`) + return await device_list[0].setColorTemperature(kelvin) + }) + .then(async () => { + await this.successLog(`ColorTemperature: ${this.LightBulb.ColorTemperature} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushRGBChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushColorTemperatureChanges), ColorTemperature: ${this.LightBulb.ColorTemperature}, ColorTemperatureCached: ${this.accessory.context.ColorTemperature}`) @@ -555,26 +578,32 @@ export class ColorBulb extends deviceBase { const [red, green, blue] = hs2rgb(this.LightBulb.Hue, this.LightBulb.Saturation) await this.debugLog(`rgb: ${JSON.stringify([red, green, blue])}`) const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - await this.infoLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)}`) - return await device_list[0].setRGB(this.LightBulb.Brightness, red, green, blue) - }) - .then(async () => { - await this.successLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushRGBChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + await this.infoLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)}`) + return await device_list[0].setRGB(this.LightBulb.Brightness, red, green, blue) + }) + .then(async () => { + await this.successLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushRGBChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushRGBChanges), Hue: ${this.LightBulb.Hue}, HueCached: ${this.accessory.context.Hue}, Saturation: ${this.LightBulb.Saturation}, SaturationCached: ${this.accessory.context.Saturation}`) diff --git a/src/device/contact.ts b/src/device/contact.ts index a03c5beb..402f3138 100644 --- a/src/device/contact.ts +++ b/src/device/contact.ts @@ -18,6 +18,7 @@ import type { contactSensorWebhookContext } from '../types/devicewebhookstatus.j import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { interval, skipWhile, Subject } from 'rxjs' +import { formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' /** @@ -326,17 +327,22 @@ export class Contact extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: contactSensorServiceData) => { - 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}`) + 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: contactSensorServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') diff --git a/src/device/curtain.ts b/src/device/curtain.ts index 7e43372d..c3cf1343 100644 --- a/src/device/curtain.ts +++ b/src/device/curtain.ts @@ -20,6 +20,7 @@ import { hostname } from 'node:os' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' +import { formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' export class Curtain extends deviceBase { @@ -324,42 +325,45 @@ export class Curtain extends deviceBase { return } - const mac = this.device - .deviceId!.match(/.{1,2}/g)! - .join(':') - .toLowerCase() - this.historyService = new this.platform.fakegatoAPI('custom', this.accessory, { - log: this.platform.log, - storage: 'fs', - filename: `${hostname().split('.')[0]}_${mac}_persist.json`, - }) - const motion: Service + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + this.historyService = new this.platform.fakegatoAPI('custom', this.accessory, { + log: this.platform.log, + storage: 'fs', + filename: `${hostname().split('.')[0]}_${this.device.bleMac}_persist.json`, + }) + const motion: Service = this.accessory.getService(this.hap.Service.MotionSensor) || this.accessory.addService(this.hap.Service.MotionSensor, 'Motion') - motion.addOptionalCharacteristic(this.platform.eve.Characteristics.LastActivation) - motion.getCharacteristic(this.platform.eve.Characteristics.LastActivation).onGet(() => { - const lastActivation = this.accessory.context.lastActivation - ? Math.max(0, this.accessory.context.lastActivation - this.historyService.getInitialTime()) - : 0 - return lastActivation - }) - await this.setMinMax() - motion.getCharacteristic(this.hap.Characteristic.MotionDetected).on('change', (event: CharacteristicChange) => { - if (event.newValue !== event.oldValue) { - const sensor = this.accessory.getService(this.hap.Service.MotionSensor) - const entry = { - time: Math.round(new Date().valueOf() / 1000), - motion: event.newValue, + motion.addOptionalCharacteristic(this.platform.eve.Characteristics.LastActivation) + motion.getCharacteristic(this.platform.eve.Characteristics.LastActivation).onGet(() => { + const lastActivation = this.accessory.context.lastActivation + ? Math.max(0, this.accessory.context.lastActivation - this.historyService.getInitialTime()) + : 0 + return lastActivation + }) + await this.setMinMax() + motion.getCharacteristic(this.hap.Characteristic.MotionDetected).on('change', (event: CharacteristicChange) => { + if (event.newValue !== event.oldValue) { + const sensor = this.accessory.getService(this.hap.Service.MotionSensor) + const entry = { + time: Math.round(new Date().valueOf() / 1000), + motion: event.newValue, + } + this.accessory.context.lastActivation = entry.time + sensor?.updateCharacteristic( + this.platform.eve.Characteristics.LastActivation, + Math.max(0, this.accessory.context.lastActivation - this.historyService.getInitialTime()), + ) + this.historyService.addEntry(entry) } - this.accessory.context.lastActivation = entry.time - sensor?.updateCharacteristic( - this.platform.eve.Characteristics.LastActivation, - Math.max(0, this.accessory.context.lastActivation - this.historyService.getInitialTime()), - ) - this.historyService.addEntry(entry) - } - }) - this.updateHistory() + }) + this.updateHistory() + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) + } } async updateHistory(): Promise { @@ -541,17 +545,22 @@ export class Curtain extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: curtainServiceData | curtain3ServiceData) => { - 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}`) + 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: curtainServiceData | curtain3ServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -585,33 +594,39 @@ export class Curtain extends deviceBase { await this.debugLog('BLEpushChanges') if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) { const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - const { setPositionMode, Mode }: { setPositionMode: number, Mode: string } = await this.setPerformance() - const adjustedMode = setPositionMode === 1 ? 0x01 : 0xFF - await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`) - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac }) - .then(async (device_list: any) => { - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode) - }, + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + const { setPositionMode, Mode }: { setPositionMode: number, Mode: string } = await this.setPerformance() + const adjustedMode = setPositionMode === 1 ? 0x01 : 0xFF + await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac }) + .then(async (device_list: any) => { + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode) + }, + }) }) - }) - .then(async () => { - await this.successLog(`TargetPostion: ${this.WindowCovering.TargetPosition} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + .then(async () => { + await this.successLog(`TargetPostion: ${this.WindowCovering.TargetPosition} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`) diff --git a/src/device/device.ts b/src/device/device.ts index 92c269ff..346eb41b 100644 --- a/src/device/device.ts +++ b/src/device/device.ts @@ -17,7 +17,7 @@ import { SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName import { request } from 'undici' import { Devices } from '../settings.js' -import { BlindTiltMappingMode, sleep } from '../utils.js' +import { BlindTiltMappingMode, formatDeviceIdAsMac, sleep } from '../utils.js' export abstract class deviceBase { public readonly api: API @@ -261,33 +261,34 @@ export abstract class deviceBase { * Setup EVE history graph feature if enabled. */ async setupHistoryService(accessory: PlatformAccessory, device: device & devicesConfig): Promise { - const mac = this.device - .deviceId!.match(/.{1,2}/g)! - .join(':') - .toLowerCase() - this.historyService = device.history - ? new this.platform.fakegatoAPI('room', accessory, { - log: this.platform.log, - storage: 'fs', - filename: `${hostname().split('.')[0]}_${mac}_persist.json`, - }) - : null + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + this.historyService = device.history + ? new this.platform.fakegatoAPI('room', accessory, { + log: this.platform.log, + storage: 'fs', + filename: `${hostname().split('.')[0]}_${this.device.bleMac}_persist.json`, + }) + : null + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) + } } async switchbotBLE(): Promise { const switchbot = await this.platform.connectBLE(this.accessory, this.device) // Convert to BLE Address - await this.convertBLEAddress() - await this.getCustomBLEAddress(switchbot) - return switchbot - } - - async convertBLEAddress() { - this.device.bleMac = this.device - .deviceId!.match(/.{1,2}/g)! - .join(':') - .toLowerCase() - await this.debugLog(`BLE Address: ${this.device.bleMac}`) + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + await this.getCustomBLEAddress(switchbot) + return switchbot + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) + } } async monitorAdvertisementPackets(switchbot: any) { diff --git a/src/device/fan.ts b/src/device/fan.ts index 362b5f34..c97383e0 100644 --- a/src/device/fan.ts +++ b/src/device/fan.ts @@ -18,6 +18,7 @@ import type { batteryCirculatorFanWebhookContext } from '../types/devicewebhooks import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' +import { formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' export class Fan extends deviceBase { @@ -346,17 +347,22 @@ export class Fan extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: batteryCirculatorFanServiceData) => { - 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}`) + 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: batteryCirculatorFanServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -448,34 +454,40 @@ export class Fan extends deviceBase { if (this.Fan.Active !== this.accessory.context.Active) { await this.debugLog(`BLEpushChanges On: ${this.Fan.Active} OnCached: ${this.accessory.context.Active}`) const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - if (this.Fan.Active) { - return await device_list[0].turnOn({ id: this.device.bleMac }) - } else { - return await device_list[0].turnOff({ id: this.device.bleMac }) - } - }, + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + if (this.Fan.Active) { + return await device_list[0].turnOn({ id: this.device.bleMac }) + } else { + return await device_list[0].turnOff({ id: this.device.bleMac }) + } + }, + }) }) - }) - .then(async () => { - await this.successLog(`Active: ${this.Fan.Active} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + .then(async () => { + await this.successLog(`Active: ${this.Fan.Active} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No change (BLEpushChanges), Active: ${this.Fan.Active}, ActiveCached: ${this.accessory.context.Active}`) diff --git a/src/device/hub.ts b/src/device/hub.ts index c0ba0905..5df3791d 100644 --- a/src/device/hub.ts +++ b/src/device/hub.ts @@ -19,7 +19,7 @@ import { Units } from 'homebridge' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { interval, skipWhile, Subject } from 'rxjs' -import { convertUnits, validHumidity } from '../utils.js' +import { convertUnits, formatDeviceIdAsMac, validHumidity } from '../utils.js' import { deviceBase } from './device.js' export class Hub extends deviceBase { @@ -315,17 +315,22 @@ export class Hub extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: hub2ServiceData) => { - 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}`) + 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: hub2ServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') diff --git a/src/device/humidifier.ts b/src/device/humidifier.ts index 9291de5a..f6c22403 100644 --- a/src/device/humidifier.ts +++ b/src/device/humidifier.ts @@ -18,7 +18,7 @@ import type { humidifierWebhookContext } from '../types/devicewebhookstatus.js' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' -import { convertUnits, validHumidity } from '../utils.js' +import { convertUnits, formatDeviceIdAsMac, validHumidity } from '../utils.js' import { deviceBase } from './device.js' /** @@ -345,17 +345,22 @@ export class Humidifier extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: humidifierServiceData) => { - 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}`) + 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: humidifierServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -428,25 +433,31 @@ export class Humidifier extends deviceBase { && (this.HumidifierDehumidifier.Active === this.hap.Characteristic.Active.ACTIVE) && (this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold !== this.HumidifierDehumidifier.CurrentRelativeHumidity)) { const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac }) - .then(async (device_list: any) => { - return await device_list[0].percentage(this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold) - }) - .then(async () => { - await this.successLog(`RelativeHumidityHumidifierThreshold: ${this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold} sent over BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac }) + .then(async (device_list: any) => { + return await device_list[0].percentage(this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold) + }) + .then(async () => { + await this.successLog(`RelativeHumidityHumidifierThreshold: ${this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold} sent over BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushChanges), Active: ${this.HumidifierDehumidifier.Active}, RelativeHumidityHumidifierThreshold: ${this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold}, CurrentRelativeHumidity: ${this.HumidifierDehumidifier.CurrentRelativeHumidity}`) diff --git a/src/device/iosensor.ts b/src/device/iosensor.ts index 32e57db4..7da3623a 100644 --- a/src/device/iosensor.ts +++ b/src/device/iosensor.ts @@ -19,7 +19,7 @@ import { Units } from 'homebridge' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { interval, skipWhile, Subject } from 'rxjs' -import { convertUnits, validHumidity } from '../utils.js' +import { convertUnits, formatDeviceIdAsMac, validHumidity } from '../utils.js' import { deviceBase } from './device.js' /** @@ -310,17 +310,22 @@ export class IOSensor extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: outdoorMeterServiceData) => { - 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}`) + 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: outdoorMeterServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') diff --git a/src/device/lightstrip.ts b/src/device/lightstrip.ts index 72bf4ecd..ae93426d 100644 --- a/src/device/lightstrip.ts +++ b/src/device/lightstrip.ts @@ -18,7 +18,7 @@ import type { stripLightWebhookContext } from '../types/devicewebhookstatus.js' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' -import { hs2rgb, m2hs, rgb2hs } from '../utils.js' +import { formatDeviceIdAsMac, hs2rgb, m2hs, rgb2hs } from '../utils.js' import { deviceBase } from './device.js' /** @@ -337,17 +337,22 @@ export class StripLight extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: stripLightServiceData) => { - 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}`) + 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: stripLightServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -455,35 +460,41 @@ export class StripLight extends deviceBase { if (this.LightBulb.On !== this.accessory.context.On) { await this.debugLog(`BLEpushChanges On: ${this.LightBulb.On}, OnCached: ${this.accessory.context.On}`) const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - await this.infoLog(`On: ${this.LightBulb.On}`) - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - if (this.LightBulb.On) { - return await device_list[0].turnOn({ id: this.device.bleMac }) - } else { - return await device_list[0].turnOff({ id: this.device.bleMac }) - } - }, + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + await this.infoLog(`On: ${this.LightBulb.On}`) + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + if (this.LightBulb.On) { + return await device_list[0].turnOn({ id: this.device.bleMac }) + } else { + return await device_list[0].turnOff({ id: this.device.bleMac }) + } + }, + }) }) - }) - .then(async () => { - await this.successLog(`On: ${this.LightBulb.On} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + .then(async () => { + await this.successLog(`On: ${this.LightBulb.On} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushChanges), On: ${this.LightBulb.On}, OnCached: ${this.accessory.context.On}`) @@ -494,26 +505,32 @@ export class StripLight extends deviceBase { await this.debugLog('BLEpushBrightnessChanges') if (this.LightBulb.Brightness !== this.accessory.context.Brightness) { const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - await this.infoLog(`Brightness: ${this.LightBulb.Brightness}`) - return await device_list[0].setBrightness(this.LightBulb.Brightness) - }) - .then(async () => { - await this.successLog(`Brightness: ${this.LightBulb.Brightness} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + await this.infoLog(`Brightness: ${this.LightBulb.Brightness}`) + return await device_list[0].setBrightness(this.LightBulb.Brightness) + }) + .then(async () => { + await this.successLog(`Brightness: ${this.LightBulb.Brightness} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushBrightnessChanges), Brightness: ${this.LightBulb.Brightness}, BrightnessCached: ${this.accessory.context.Brightness}`) @@ -527,26 +544,32 @@ export class StripLight extends deviceBase { const [red, green, blue] = hs2rgb(this.LightBulb.Hue, this.LightBulb.Saturation) await this.debugLog(`rgb: ${JSON.stringify([red, green, blue])}`) const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - await this.infoLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)}`) - return await device_list[0].setRGB(this.LightBulb.Brightness, red, green, blue) - }) - .then(async () => { - await this.successLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushRGBChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + await this.infoLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)}`) + return await device_list[0].setRGB(this.LightBulb.Brightness, red, green, blue) + }) + .then(async () => { + await this.successLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushRGBChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushRGBChanges), Hue: ${this.LightBulb.Hue}, HueCached: ${this.accessory.context.Hue}, Saturation: ${this.LightBulb.Saturation}, SaturationCached: ${this.accessory.context.Saturation}`) diff --git a/src/device/lock.ts b/src/device/lock.ts index 626d839a..7df6348c 100644 --- a/src/device/lock.ts +++ b/src/device/lock.ts @@ -18,6 +18,7 @@ import type { lockProWebhookContext, lockWebhookContext } from '../types/devicew import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' +import { formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' export class Lock extends deviceBase { @@ -349,17 +350,22 @@ export class Lock extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: lockServiceData | lockProServiceData) => { - 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}`) + 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: lockServiceData | lockProServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -435,34 +441,40 @@ export class Lock extends deviceBase { await this.debugLog('BLEpushChanges') if (this.LockMechanism.LockTargetState !== this.accessory.context.LockTargetState) { const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - if (this.LockMechanism.LockTargetState === this.hap.Characteristic.LockTargetState.SECURED) { - return await device_list[0].lock({ id: this.device.bleMac }) - } else { - return await device_list[0].unlock({ id: this.device.bleMac }) - } - }, + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + if (this.LockMechanism.LockTargetState === this.hap.Characteristic.LockTargetState.SECURED) { + return await device_list[0].lock({ id: this.device.bleMac }) + } else { + return await device_list[0].unlock({ id: this.device.bleMac }) + } + }, + }) }) - }) - .then(async () => { - await this.successLog(`LockTargetState: ${this.LockMechanism.LockTargetState} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + .then(async () => { + await this.successLog(`LockTargetState: ${this.LockMechanism.LockTargetState} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushChanges), LockTargetState: ${this.LockMechanism.LockTargetState}, LockCurrentState: ${this.LockMechanism.LockCurrentState}`) diff --git a/src/device/meter.ts b/src/device/meter.ts index 8906ab6e..904ac3a2 100644 --- a/src/device/meter.ts +++ b/src/device/meter.ts @@ -19,7 +19,7 @@ import { Units } from 'homebridge' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { interval, skipWhile, Subject } from 'rxjs' -import { convertUnits, validHumidity } from '../utils.js' +import { convertUnits, formatDeviceIdAsMac, validHumidity } from '../utils.js' import { deviceBase } from './device.js' export class Meter extends deviceBase { @@ -305,17 +305,22 @@ export class Meter extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: meterServiceData) => { - 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}`) + 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: meterServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') diff --git a/src/device/meterplus.ts b/src/device/meterplus.ts index 28a89e3c..e95b7cb4 100644 --- a/src/device/meterplus.ts +++ b/src/device/meterplus.ts @@ -19,7 +19,7 @@ import { Units } from 'homebridge' import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { interval, skipWhile, Subject } from 'rxjs' -import { convertUnits, validHumidity } from '../utils.js' +import { convertUnits, formatDeviceIdAsMac, validHumidity } from '../utils.js' import { deviceBase } from './device.js' /** @@ -307,17 +307,22 @@ export class MeterPlus extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: meterPlusServiceData) => { - 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}`) + 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: meterPlusServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') diff --git a/src/device/motion.ts b/src/device/motion.ts index 86e135d1..bdf7586b 100644 --- a/src/device/motion.ts +++ b/src/device/motion.ts @@ -18,6 +18,7 @@ import type { motionSensorWebhookContext } from '../types/devicewebhookstatus.js import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { interval, skipWhile, Subject } from 'rxjs' +import { formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' /** @@ -281,17 +282,22 @@ export class Motion extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: motionSensorServiceData) => { - 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}`) + 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: motionSensorServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') diff --git a/src/device/plug.ts b/src/device/plug.ts index e45406ce..e68a7b83 100644 --- a/src/device/plug.ts +++ b/src/device/plug.ts @@ -18,6 +18,7 @@ import type { plugMiniJPWebhookContext, plugMiniUSWebhookContext, plugWebhookCon import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' +import { formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' export class Plug extends deviceBase { @@ -205,17 +206,22 @@ export class Plug extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: plugMiniUSServiceData | plugMiniJPServiceData) => { - 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}`) + 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: plugMiniUSServiceData | plugMiniJPServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -296,35 +302,41 @@ export class Plug extends deviceBase { if (this.Outlet.On !== this.accessory.context.On) { await this.debugLog(`BLEpushChanges On: ${this.Outlet.On}, OnCached: ${this.accessory.context.On}`) const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - await this.infoLog(`On: ${this.Outlet.On}`) - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - if (this.Outlet.On) { - return await device_list[0].turnOn({ id: this.device.bleMac }) - } else { - return await device_list[0].turnOff({ id: this.device.bleMac }) - } - }, + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + await this.infoLog(`On: ${this.Outlet.On}`) + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + if (this.Outlet.On) { + return await device_list[0].turnOn({ id: this.device.bleMac }) + } else { + return await device_list[0].turnOff({ id: this.device.bleMac }) + } + }, + }) }) - }) - .then(async () => { - await this.successLog(`On: ${this.Outlet.On} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + .then(async () => { + await this.successLog(`On: ${this.Outlet.On} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushChanges), On: ${this.Outlet.On}, OnCached: ${this.accessory.context.On}`) diff --git a/src/device/robotvacuumcleaner.ts b/src/device/robotvacuumcleaner.ts index ebe6cd98..4d97ba31 100644 --- a/src/device/robotvacuumcleaner.ts +++ b/src/device/robotvacuumcleaner.ts @@ -22,6 +22,7 @@ import type { import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs' +import { formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' export class RobotVacuumCleaner extends deviceBase { @@ -295,17 +296,22 @@ export class RobotVacuumCleaner extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: robotVacuumCleanerServiceData) => { - 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}`) + 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: robotVacuumCleanerServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') @@ -383,35 +389,41 @@ export class RobotVacuumCleaner extends deviceBase { await this.debugLog('BLEpushChanges') if (this.LightBulb.On !== this.accessory.context.On) { const switchbot = await this.platform.connectBLE(this.accessory, this.device) - await this.convertBLEAddress() - if (switchbot !== false) { - switchbot - .discover({ model: this.device.bleModel, id: this.device.bleMac }) - .then(async (device_list: any) => { - await this.infoLog(`On: ${this.LightBulb.On}`) - return await this.retryBLE({ - max: await this.maxRetryBLE(), - fn: async () => { - if (this.LightBulb.On) { - return await device_list[0].turnOn({ id: this.device.bleMac }) - } else { - return await device_list[0].turnOff({ id: this.device.bleMac }) - } - }, + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId!) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + if (switchbot !== false) { + switchbot + .discover({ model: this.device.bleModel, id: this.device.bleMac }) + .then(async (device_list: any) => { + await this.infoLog(`On: ${this.LightBulb.On}`) + return await this.retryBLE({ + max: await this.maxRetryBLE(), + fn: async () => { + if (this.LightBulb.On) { + return await device_list[0].turnOn({ id: this.device.bleMac }) + } else { + return await device_list[0].turnOff({ id: this.device.bleMac }) + } + }, + }) }) - }) - .then(async () => { - await this.successLog(`On: ${this.LightBulb.On} sent over SwitchBot BLE, sent successfully`) - await this.updateHomeKitCharacteristics() - }) - .catch(async (e: any) => { - await this.apiError(e) - await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) - await this.BLEPushConnection() - }) - } else { - await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) - await this.BLEPushConnection() + .then(async () => { + await this.successLog(`On: ${this.LightBulb.On} sent over SwitchBot BLE, sent successfully`) + await this.updateHomeKitCharacteristics() + }) + .catch(async (e: any) => { + await this.apiError(e) + await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + await this.BLEPushConnection() + }) + } else { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + await this.BLEPushConnection() + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog(`No changes (BLEpushChanges), On: ${this.LightBulb.On}, OnCached: ${this.accessory.context.On}`) diff --git a/src/device/waterdetector.ts b/src/device/waterdetector.ts index 2715fa48..41539528 100644 --- a/src/device/waterdetector.ts +++ b/src/device/waterdetector.ts @@ -18,6 +18,7 @@ import type { waterLeakDetectorWebhookContext } from '../types/devicewebhookstat import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' import { interval, skipWhile, Subject } from 'rxjs' +import { formatDeviceIdAsMac } from '../utils.js' import { deviceBase } from './device.js' /** @@ -295,17 +296,22 @@ export class WaterDetector extends deviceBase { await this.debugLog('registerPlatformBLE') if (this.config.options?.BLE) { await this.debugLog('is listening to Platform BLE.') - this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase() - await this.debugLog(`bleMac: ${this.device.bleMac}`) - this.platform.bleEventHandler[this.device.bleMac] = async (context: waterLeakDetectorServiceData) => { - 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}`) + 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: waterLeakDetectorServiceData) => { + 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}`) + } } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) } } else { await this.debugLog('is not listening to Platform BLE') diff --git a/src/utils.ts b/src/utils.ts index e61f38d2..32c0979e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -158,6 +158,35 @@ export function convertUnits(value: number, unit: string, convert?: string): num return value } +/** + * Formats a device ID as a MAC address. + * Ensures the device ID does not already contain colons. + * + * @param deviceId - The device ID to format. + * @returns The formatted MAC address. + */ +export function formatDeviceIdAsMac(deviceId: string): string { + if (typeof deviceId !== 'string') { + throw new TypeError('Invalid device ID format. Device ID must be a string.') + } + + deviceId = deviceId.trim() + + const macAddressRegex = /^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$/i + const hexRegex = /^[0-9a-f]{12}$/i + + if (macAddressRegex.test(deviceId)) { + return deviceId.toLowerCase() + } + + // Check if the deviceId is a valid 12-character hexadecimal string + if (hexRegex.test(deviceId)) { + return deviceId.match(/.{1,2}/g)!.join(':').toLowerCase() + } + + throw new Error('Invalid device ID format. Must be a valid MAC address or a 12-character hexadecimal string.') +} + export function rgb2hs(r: any, g: any, b: any) { /** * Credit: