diff --git a/.vscode/settings.json b/.vscode/settings.json index 68e080b4..75dda2db 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -23,6 +23,6 @@ } ], "[json]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "vscode.json-language-features" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index c5d87446..e476d225 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/) -## [2.0.0-beta](https://github.com/donavanbecker/homebridge-resideo/releases/tag/v2.0.0) (2024-XX-XX) +## [Beta 2.0.0](https://github.com/donavanbecker/homebridge-resideo/releases/tag/v2.0.0) (2024-XX-XX) ### What's Changes - Moved from CommonJS to ES Module diff --git a/config.schema.json b/config.schema.json index 41c80f4f..38d7d8ed 100644 --- a/config.schema.json +++ b/config.schema.json @@ -85,6 +85,10 @@ { "title": "Leak Sensor", "enum": ["LeakDetector"] + }, + { + "title": "Shut Off Valve", + "enum": ["ShutoffValve"] } ], "condition": { diff --git a/package-lock.json b/package-lock.json index 0a915680..e183410a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,11 +24,12 @@ "undici": "^6.3.0" }, "devDependencies": { - "@types/node": "^20.11.4", + "@types/node": "^20.11.5", "@typescript-eslint/eslint-plugin": "^6.19.0", "@typescript-eslint/parser": "^6.19.0", "eslint": "^8.56.0", "homebridge": "^1.7.0", + "homebridge-config-ui-x": "^4.55.1", "nodemon": "^3.0.3", "npm-check-updates": "^16.14.12", "rimraf": "^5.0.5", @@ -50,6 +51,19 @@ "node": ">=0.10.0" } }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.23.8.tgz", + "integrity": "sha512-2ZzmcDugdm0/YQKFVYsXiwUN7USPX8PM7cytpb4PFl87fM+qYPSvTZX//8tyeJB1j0YDmafBJEbl5f8NfLyuKw==", + "dev": true, + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -150,14 +164,198 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fastify/accept-negotiator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz", + "integrity": "sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@fastify/ajv-compiler": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.5.0.tgz", + "integrity": "sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==", + "dev": true, + "dependencies": { + "ajv": "^8.11.0", + "ajv-formats": "^2.1.1", + "fast-uri": "^2.0.0" + } + }, + "node_modules/@fastify/ajv-compiler/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@fastify/ajv-compiler/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/@fastify/busboy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", - "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz", + "integrity": "sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==", + "dev": true, + "dependencies": { + "text-decoding": "^1.0.0" + }, "engines": { "node": ">=14" } }, + "node_modules/@fastify/cors": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-8.4.2.tgz", + "integrity": "sha512-IVynbcPG9eWiJ0P/A1B+KynmiU/yTYbu3ooBUSIeHfca/N1XLb9nIJVCws+YTr2q63MA8Y6QLeXQczEv4npM9g==", + "dev": true, + "dependencies": { + "fastify-plugin": "^4.0.0", + "mnemonist": "0.39.5" + } + }, + "node_modules/@fastify/deepmerge": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-1.3.0.tgz", + "integrity": "sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==", + "dev": true + }, + "node_modules/@fastify/error": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", + "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==", + "dev": true + }, + "node_modules/@fastify/fast-json-stringify-compiler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz", + "integrity": "sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==", + "dev": true, + "dependencies": { + "fast-json-stringify": "^5.7.0" + } + }, + "node_modules/@fastify/formbody": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-7.4.0.tgz", + "integrity": "sha512-H3C6h1GN56/SMrZS8N2vCT2cZr7mIHzBHzOBa5OPpjfB/D6FzP9mMpE02ZzrFX0ANeh0BAJdoXKOF2e7IbV+Og==", + "dev": true, + "dependencies": { + "fast-querystring": "^1.0.0", + "fastify-plugin": "^4.0.0" + } + }, + "node_modules/@fastify/helmet": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@fastify/helmet/-/helmet-11.1.1.tgz", + "integrity": "sha512-pjJxjk6SLEimITWadtYIXt6wBMfFC1I6OQyH/jYVCqSAn36sgAIFjeNiibHtifjCd+e25442pObis3Rjtame6A==", + "dev": true, + "dependencies": { + "fastify-plugin": "^4.2.1", + "helmet": "^7.0.0" + } + }, + "node_modules/@fastify/middie": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@fastify/middie/-/middie-8.3.0.tgz", + "integrity": "sha512-h+zBxCzMlkEkh4fM7pZaSGzqS7P9M0Z6rXnWPdUEPfe7x1BCj++wEk/pQ5jpyYY4pF8AknFqb77n7uwh8HdxEA==", + "dev": true, + "dependencies": { + "@fastify/error": "^3.2.0", + "fastify-plugin": "^4.0.0", + "path-to-regexp": "^6.1.0", + "reusify": "^1.0.4" + } + }, + "node_modules/@fastify/middie/node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "node_modules/@fastify/multipart": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@fastify/multipart/-/multipart-8.0.0.tgz", + "integrity": "sha512-xaH1pGIqYnIJjYs5qG6ryhPSFnWuJIfSXYqEUtzmcyREkMk0SwONd2y+SZ9JXfDmETAC/Ogtc/SRbz+AjZhCkw==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^1.0.0", + "@fastify/deepmerge": "^1.0.0", + "@fastify/error": "^3.0.0", + "@fastify/swagger": "^8.3.1", + "@fastify/swagger-ui": "^1.8.0", + "fastify-plugin": "^4.0.0", + "secure-json-parse": "^2.4.0", + "stream-wormhole": "^1.1.0" + } + }, + "node_modules/@fastify/send": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fastify/send/-/send-2.1.0.tgz", + "integrity": "sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA==", + "dev": true, + "dependencies": { + "@lukeed/ms": "^2.0.1", + "escape-html": "~1.0.3", + "fast-decode-uri-component": "^1.0.1", + "http-errors": "2.0.0", + "mime": "^3.0.0" + } + }, + "node_modules/@fastify/static": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@fastify/static/-/static-6.12.0.tgz", + "integrity": "sha512-KK1B84E6QD/FcQWxDI2aiUCwHxMJBI1KeCUzm1BwYpPY1b742+jeKruGHP2uOluuM6OkBPI8CIANrXcCRtC2oQ==", + "dev": true, + "dependencies": { + "@fastify/accept-negotiator": "^1.0.0", + "@fastify/send": "^2.0.0", + "content-disposition": "^0.5.3", + "fastify-plugin": "^4.0.0", + "glob": "^8.0.1", + "p-limit": "^3.1.0" + } + }, + "node_modules/@fastify/swagger": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@fastify/swagger/-/swagger-8.14.0.tgz", + "integrity": "sha512-sGiznEb3rl6pKGGUZ+JmfI7ct5cwbTQGo+IjewaTvtzfrshnryu4dZwEsjw0YHABpBA+kCz3kpRaHB7qpa67jg==", + "dev": true, + "dependencies": { + "fastify-plugin": "^4.0.0", + "json-schema-resolver": "^2.0.0", + "openapi-types": "^12.0.0", + "rfdc": "^1.3.0", + "yaml": "^2.2.2" + } + }, + "node_modules/@fastify/swagger-ui": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@fastify/swagger-ui/-/swagger-ui-1.10.2.tgz", + "integrity": "sha512-f2mRqtblm6eRAFQ3e8zSngxVNEtiYY7rISKQVjPA++ZsWc5WYlPVTb6Bx0G/zy0BIoucNqDr/Q2Vb/kTYkOq1A==", + "dev": true, + "dependencies": { + "@fastify/static": "^6.0.0", + "fastify-plugin": "^4.0.0", + "openapi-types": "^12.0.2", + "rfdc": "^1.3.0", + "yaml": "^2.2.2" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -206,6 +404,17 @@ "integrity": "sha512-i5Df8R63XNPCn+Nj1OgAoRdw9e+jHUQb3CNUbvJneI2iu3j4+OtzQj+5PA1Ce+747NR1SPqZSvyvD483dOT3AA==", "dev": true }, + "node_modules/@homebridge/node-pty-prebuilt-multiarch": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/@homebridge/node-pty-prebuilt-multiarch/-/node-pty-prebuilt-multiarch-0.11.12.tgz", + "integrity": "sha512-AHAqVWqWjMxNld+6mpNi/WtwvtskGNJkqxj1EBeMEmxt/0mEY3L109qZE665gc8l+5mo5Whgw64bdl5diQrtag==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "nan": "^2.18.0", + "prebuild-install": "^7.1.1" + } + }, "node_modules/@homebridge/plugin-ui-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@homebridge/plugin-ui-utils/-/plugin-ui-utils-1.0.1.tgz", @@ -373,6 +582,253 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@lukeed/ms": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", + "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nestjs/axios": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.1.tgz", + "integrity": "sha512-VlOZhAGDmOoFdsmewn8AyClAdGpKXQQaY1+3PGB+g6ceurGIdTxZgRX3VXc1T6Zs60PedWjg3A82TDOB05mrzQ==", + "dev": true, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", + "reflect-metadata": "^0.1.12", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, + "node_modules/@nestjs/common": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.0.tgz", + "integrity": "sha512-DGv34UHsZBxCM3H5QGE2XE/+oLJzz5+714JQjBhjD9VccFlQs3LRxo/epso4l7nJIiNlZkPyIUC8WzfU/5RTsQ==", + "dev": true, + "dependencies": { + "iterare": "1.2.1", + "tslib": "2.6.2", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/core": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.3.0.tgz", + "integrity": "sha512-N06P5ncknW/Pm8bj964WvLIZn2gNhHliCBoAO1LeBvNImYkecqKcrmLbY49Fa1rmMfEM3MuBHeDys3edeuYAOA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.2.0", + "tslib": "2.6.2", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } + } + }, + "node_modules/@nestjs/jwt": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.2.0.tgz", + "integrity": "sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==", + "dev": true, + "dependencies": { + "@types/jsonwebtoken": "9.0.5", + "jsonwebtoken": "9.0.2" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/@nestjs/mapped-types": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.4.tgz", + "integrity": "sha512-xl+gUSp0B+ln1VSNoUftlglk8dfpUes3DHGxKZ5knuBxS5g2H/8p9/DSBOYWUfO5f4u9s6ffBPZ71WO+tbe5SA==", + "dev": true, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "class-transformer": "^0.4.0 || ^0.5.0", + "class-validator": "^0.13.0 || ^0.14.0", + "reflect-metadata": "^0.1.12" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/passport": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.3.tgz", + "integrity": "sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==", + "dev": true, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "passport": "^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0" + } + }, + "node_modules/@nestjs/platform-fastify": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@nestjs/platform-fastify/-/platform-fastify-10.3.0.tgz", + "integrity": "sha512-ka4r/cPWM5y/dXoi9dj6pn1o3WLnfImy2bT3aYVasiDsJff2cd3h/ThugwxjdH0BHUpLSPnawEGzADAcO8Fqug==", + "dev": true, + "dependencies": { + "@fastify/cors": "8.4.2", + "@fastify/formbody": "7.4.0", + "@fastify/middie": "8.3.0", + "fastify": "4.25.1", + "light-my-request": "5.11.0", + "path-to-regexp": "3.2.0", + "tslib": "2.6.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@fastify/static": "^6.0.0", + "@fastify/view": "^7.0.0 || ^8.0.0", + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "@fastify/view": { + "optional": true + } + } + }, + "node_modules/@nestjs/platform-socket.io": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.3.0.tgz", + "integrity": "sha512-Rdpk9OdsvJfsmVRtg4/0+cUdvOgBEb3F4zo2r4SBgxb0eaR3BHbhbXTJH/U7NvREIvvYbtSNoWI+h2taUEkXwg==", + "dev": true, + "dependencies": { + "socket.io": "4.7.2", + "tslib": "2.6.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "rxjs": "^7.1.0" + } + }, + "node_modules/@nestjs/swagger": { + "version": "7.1.17", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.1.17.tgz", + "integrity": "sha512-ASCxBrvMEN2o/8vEEmrIPMNzrr/hVi7QIR4y1oNYvoBNXHuwoF1VSI3+4Rq/3xmwVnVveJxHlBIs2u5xY9VgGQ==", + "dev": true, + "dependencies": { + "@nestjs/mapped-types": "2.0.4", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "path-to-regexp": "3.2.0", + "swagger-ui-dist": "5.10.3" + }, + "peerDependencies": { + "@fastify/static": "^6.0.0", + "@nestjs/common": "^9.0.0 || ^10.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/websockets": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.3.0.tgz", + "integrity": "sha512-1cqh46s4iHLytExSWcvp/58pMZFAT7pQ59IAYQCSZz5xFq0lEGxd36C982KyROQIHfno8E+FWm71UhgVTwKsyA==", + "dev": true, + "dependencies": { + "iterare": "1.2.1", + "object-hash": "3.0.0", + "tslib": "2.6.2" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-socket.io": "^10.0.0", + "reflect-metadata": "^0.1.12", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/platform-socket.io": { + "optional": true + } + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -620,6 +1076,94 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/@otplib/core": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz", + "integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==", + "dev": true + }, + "node_modules/@otplib/plugin-crypto": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz", + "integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==", + "dev": true, + "dependencies": { + "@otplib/core": "^12.0.1" + } + }, + "node_modules/@otplib/plugin-thirty-two": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz", + "integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==", + "dev": true, + "dependencies": { + "@otplib/core": "^12.0.1", + "thirty-two": "^1.0.2" + } + }, + "node_modules/@otplib/preset-default": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz", + "integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==", + "dev": true, + "dependencies": { + "@otplib/core": "^12.0.1", + "@otplib/plugin-crypto": "^12.0.1", + "@otplib/plugin-thirty-two": "^12.0.1" + } + }, + "node_modules/@otplib/preset-v11": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz", + "integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==", + "dev": true, + "dependencies": { + "@otplib/core": "^12.0.1", + "@otplib/plugin-crypto": "^12.0.1", + "@otplib/plugin-thirty-two": "^12.0.1" + } + }, + "node_modules/@oznu/hap-client": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@oznu/hap-client/-/hap-client-1.9.0.tgz", + "integrity": "sha512-dtx8SNLzT62VVwN2YwBVooLyKBrBphddVvYda8CqY5BHLzjK8SMDOF63t2nvp+MLwzWXKfpmcX1w+qS3V8J9Gw==", + "dev": true, + "dependencies": { + "axios": "^0.27.2", + "bonjour-service": "^1.0.12", + "decamelize": "^3.2.0", + "inflection": "^1.13.2", + "source-map-support": "^0.5.19" + } + }, + "node_modules/@oznu/hap-client/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -731,6 +1275,12 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true + }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", @@ -798,10 +1348,25 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", "dev": true }, "node_modules/@types/json-schema": { @@ -810,10 +1375,19 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", + "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { - "version": "20.11.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.4.tgz", - "integrity": "sha512-6I0fMH8Aoy2lOejL3s4LhyIYX34DPwY8bl5xlNjBvUEk8OHrcuzsFt+Ied4LvJihbtXPM+8zUqdydfIti86v9g==", + "version": "20.11.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", + "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -825,6 +1399,12 @@ "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, + "node_modules/@types/validator": { + "version": "13.11.8", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", + "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.19.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.0.tgz", @@ -1027,6 +1607,37 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abstract-logging": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -1110,6 +1721,45 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -1162,6 +1812,12 @@ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true + }, "node_modules/are-we-there-yet": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", @@ -1215,6 +1871,21 @@ "node": ">=8" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -1227,12 +1898,91 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/avvio": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.2.1.tgz", + "integrity": "sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "debug": "^4.0.0", + "fastq": "^1.6.1" + } + }, + "node_modules/axios": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/bash-color": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/bash-color/-/bash-color-0.0.4.tgz", + "integrity": "sha512-ZNB4525U7BxT6v9C8LEtywyCgB4Pjnm7/bh+ru/Z9Ecxvg3fDjaJ6z305z9a61orQdbB1zqYHh5JbUqx4s4K0g==", + "dev": true + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dev": true, + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1242,6 +1992,23 @@ "node": ">=8" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "dev": true + }, "node_modules/bonjour-hap": { "version": "3.6.4", "resolved": "https://registry.npmjs.org/bonjour-hap/-/bonjour-hap-3.6.4.tgz", @@ -1255,6 +2022,18 @@ "multicast-dns-service-types": "^1.1.0" } }, + "node_modules/bonjour-service": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", + "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, "node_modules/boxen": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", @@ -1372,12 +2151,66 @@ "node": ">=8" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g==", + "dev": true + }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "dev": true, + "engines": { + "node": ">=0.2.0" + } + }, "node_modules/builtins": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", @@ -1410,6 +2243,28 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/cacache/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/cacache/node_modules/minipass": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", @@ -1446,6 +2301,18 @@ "node": ">=14.16" } }, + "node_modules/cacheable-request/node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/call-bind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", @@ -1481,6 +2348,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dev": true, + "dependencies": { + "traverse": ">=0.3.0 <0.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1560,6 +2439,23 @@ "node": ">=8" } }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "dev": true + }, + "node_modules/class-validator": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", + "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", + "dev": true, + "dependencies": { + "@types/validator": "^13.7.10", + "libphonenumber-js": "^1.10.14", + "validator": "^13.7.0" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -1581,6 +2477,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-table3": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", @@ -1596,6 +2516,15 @@ "@colors/colors": "1.5.0" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1623,6 +2552,18 @@ "color-support": "bin.js" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -1673,35 +2614,104 @@ "url": "https://github.com/yeoman/configstore?sponsor=1" } }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "dev": true + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "dev": true }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "safe-buffer": "5.2.1" }, "engines": { - "node": ">= 8" + "node": ">= 0.6" } }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-js-pure": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.35.0.tgz", + "integrity": "sha512-f+eRYmkou59uh7BPcyJ8MC76DiGhspj1KMxVIcF24tzP8NA9HVa1uC7BTW2tgx7E1QVCzDzsgp7kArrzhlz8Ew==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "dev": true, + "dependencies": { + "luxon": "^3.2.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", "dev": true, "dependencies": { @@ -1726,6 +2736,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "dev": true + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1743,6 +2759,18 @@ } } }, + "node_modules/decamelize": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-3.2.0.tgz", + "integrity": "sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw==", + "dev": true, + "dependencies": { + "xregexp": "^4.2.4" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -1758,18 +2786,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/deep-equal": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", @@ -1817,6 +2833,27 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/defer-to-connect": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", @@ -1857,12 +2894,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -1884,6 +2948,12 @@ "node": ">=8" } }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", + "dev": true + }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -1929,12 +2999,66 @@ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -1951,6 +3075,54 @@ "iconv-lite": "^0.6.2" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -1998,6 +3170,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2189,12 +3367,51 @@ "through": "^2.3.8" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/exponential-backoff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", "dev": true }, + "node_modules/fast-content-type-parse": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz", + "integrity": "sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==", + "dev": true + }, + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", + "dev": true + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2235,6 +3452,43 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-json-stringify": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.10.0.tgz", + "integrity": "sha512-fu1BhzPzgOdvK+sVhSPFzm06DQl0Dwbo+NQxWm21k03ili2wsJExXbGZ9qsD4Lsn7zFGltF8h9I1fuhk4JPnrQ==", + "dev": true, + "dependencies": { + "@fastify/deepmerge": "^1.0.0", + "ajv": "^8.10.0", + "ajv-formats": "^2.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^2.1.0", + "json-schema-ref-resolver": "^1.0.1", + "rfdc": "^1.2.0" + } + }, + "node_modules/fast-json-stringify/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fast-json-stringify/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -2247,6 +3501,30 @@ "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==", "dev": true }, + "node_modules/fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "dev": true, + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "node_modules/fast-redact": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", + "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, "node_modules/fast-srp-hap": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/fast-srp-hap/-/fast-srp-hap-2.0.4.tgz", @@ -2256,6 +3534,42 @@ "node": ">=10.17.0" } }, + "node_modules/fast-uri": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.3.0.tgz", + "integrity": "sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==", + "dev": true + }, + "node_modules/fastify": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.25.1.tgz", + "integrity": "sha512-D8d0rv61TwqoAS7lom2tvIlgVMlx88lLsiwXyWNjA7CU/LC/mx/Gp2WAlC0S/ABq19U+y/aRvYFG5xLUu2aMrg==", + "dev": true, + "dependencies": { + "@fastify/ajv-compiler": "^3.5.0", + "@fastify/error": "^3.4.0", + "@fastify/fast-json-stringify-compiler": "^4.3.0", + "abstract-logging": "^2.0.1", + "avvio": "^8.2.1", + "fast-content-type-parse": "^1.1.0", + "fast-json-stringify": "^5.8.0", + "find-my-way": "^7.7.0", + "light-my-request": "^5.11.0", + "pino": "^8.17.0", + "process-warning": "^3.0.0", + "proxy-addr": "^2.0.7", + "rfdc": "^1.3.0", + "secure-json-parse": "^2.7.0", + "semver": "^7.5.4", + "toad-cache": "^3.3.0" + } + }, + "node_modules/fastify-plugin": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz", + "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==", + "dev": true + }, "node_modules/fastq": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", @@ -2289,6 +3603,20 @@ "node": ">=8" } }, + "node_modules/find-my-way": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-7.7.0.tgz", + "integrity": "sha512-+SrHpvQ52Q6W9f3wJoJBbAQULJuNEEQwBvlvYwACDhBTLOTMiQ0HYWh4+vC3OivGP2ENcTI1oKlFA2OepJNjhQ==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-querystring": "^1.0.0", + "safe-regex2": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2382,6 +3710,26 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2407,6 +3755,32 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/form-data-encoder": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", @@ -2416,6 +3790,15 @@ "node": ">= 14.17" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fp-and-or": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/fp-and-or/-/fp-and-or-0.1.4.tgz", @@ -2431,6 +3814,12 @@ "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", "dev": true }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -2486,6 +3875,75 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/fstream/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fstream/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fstream/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fstream/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2532,12 +3990,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/gauge/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/get-intrinsic": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", @@ -2577,23 +4029,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2608,7 +4063,19 @@ "is-glob": "^4.0.3" }, "engines": { - "node": ">=10.13.0" + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, "node_modules/global-dirs": { @@ -2839,6 +4306,15 @@ "node": ">= 0.4" } }, + "node_modules/helmet": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", + "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==", + "dev": true, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/hexy": { "version": "0.2.11", "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", @@ -2869,6 +4345,96 @@ "node": "^18.15.0 || ^20.7.0" } }, + "node_modules/homebridge-config-ui-x": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/homebridge-config-ui-x/-/homebridge-config-ui-x-4.55.1.tgz", + "integrity": "sha512-XojwCOEB6LsJeYt6NFakXGCIs9WFA/xiraVhC1R1+//bQPmv1T1F3sZvrPxp1UTBLKxoxT37SMdtq0us8pRyaw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/oznu" + }, + { + "type": "paypal", + "url": "https://paypal.me/oznu" + } + ], + "dependencies": { + "@fastify/helmet": "11.1.1", + "@fastify/multipart": "8.0.0", + "@fastify/static": "6.12.0", + "@homebridge/node-pty-prebuilt-multiarch": "0.11.12", + "@nestjs/axios": "3.0.1", + "@nestjs/common": "10.3.0", + "@nestjs/core": "10.3.0", + "@nestjs/jwt": "10.2.0", + "@nestjs/passport": "10.0.3", + "@nestjs/platform-fastify": "10.3.0", + "@nestjs/platform-socket.io": "10.3.0", + "@nestjs/swagger": "7.1.17", + "@nestjs/websockets": "10.3.0", + "@oznu/hap-client": "1.9.0", + "axios": "1.6.5", + "bash-color": "0.0.4", + "bonjour-service": "=1.1.1", + "buffer-shims": "1.0.0", + "class-transformer": "0.5.1", + "class-validator": "0.14.0", + "commander": "11.1.0", + "dayjs": "1.11.10", + "fastify": "4.25.1", + "fs-extra": "11.2.0", + "jsonwebtoken": "9.0.2", + "lodash": "4.17.21", + "node-cache": "5.1.2", + "node-schedule": "2.1.1", + "ora": "5.4.1", + "otplib": "12.0.1", + "p-limit": "3.1.0", + "passport": "0.7.0", + "passport-jwt": "4.0.1", + "reflect-metadata": "0.1.14", + "rxjs": "7.8.1", + "semver": "7.5.4", + "systeminformation": "5.21.22", + "tail": "2.2.6", + "tar": "6.2.0", + "tcp-port-used": "1.0.2", + "unzipper": "0.10.14" + }, + "bin": { + "hb-service": "dist/bin/hb-service.js", + "homebridge-config-ui-x": "dist/bin/standalone.js" + }, + "engines": { + "homebridge": "^1.6.0", + "node": "^18 || ^20" + } + }, + "node_modules/homebridge-config-ui-x/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/homebridge-config-ui-x/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/hosted-git-info": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", @@ -2887,6 +4453,22 @@ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", @@ -2949,6 +4531,26 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -3025,6 +4627,15 @@ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, + "node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "dev": true, + "engines": [ + "node >= 0.4.0" + ] + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3070,6 +4681,24 @@ "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", "dev": true }, + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -3237,6 +4866,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-lambda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", @@ -3394,6 +5032,24 @@ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, "node_modules/is-weakmap": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", @@ -3425,6 +5081,20 @@ "node": ">=12" } }, + "node_modules/is2": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", + "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" + }, + "engines": { + "node": ">=v0.10.0" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -3437,6 +5107,15 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/iterare": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/jackspeak": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", @@ -3497,6 +5176,32 @@ "jju": "^1.1.0" } }, + "node_modules/json-schema-ref-resolver": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz", + "integrity": "sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, + "node_modules/json-schema-resolver": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-resolver/-/json-schema-resolver-2.0.0.tgz", + "integrity": "sha512-pJ4XLQP4Q9HTxl6RVDLJ8Cyh1uitSs0CzDBAz1uoJ4sRD/Bk7cFSXL1FUXDW3zJ7YnfliJx6eu8Jn283bpZ4Yg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "rfdc": "^1.1.4", + "uri-js": "^4.2.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/Eomm/json-schema-resolver?sponsor=1" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3548,6 +5253,49 @@ "node >= 0.2.0" ] }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dev": true, + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3594,6 +5342,35 @@ "node": ">= 0.8.0" } }, + "node_modules/libphonenumber-js": { + "version": "1.10.53", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.53.tgz", + "integrity": "sha512-sDTnnqlWK4vH4AlDQuswz3n4Hx7bIQWTpIcScJX+Sp7St3LXHmfiax/ZFfyYxHmkdCvydOLSuvtAO/XpXiSySw==", + "dev": true + }, + "node_modules/light-my-request": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.11.0.tgz", + "integrity": "sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==", + "dev": true, + "dependencies": { + "cookie": "^0.5.0", + "process-warning": "^2.0.0", + "set-cookie-parser": "^2.4.1" + } + }, + "node_modules/light-my-request/node_modules/process-warning": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.3.2.tgz", + "integrity": "sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==", + "dev": true + }, + "node_modules/listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", + "dev": true + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3615,12 +5392,76 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/long-timeout": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", + "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==", + "dev": true + }, "node_modules/lowercase-keys": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", @@ -3642,6 +5483,15 @@ "node": ">=12" } }, + "node_modules/luxon": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", + "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -3702,13 +5552,55 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3928,6 +5820,21 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/mnemonist": { + "version": "0.39.5", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.5.tgz", + "integrity": "sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ==", + "dev": true, + "dependencies": { + "obliterator": "^2.0.1" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -3953,6 +5860,18 @@ "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==", "dev": true }, + "node_modules/nan": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "dev": true + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3968,6 +5887,50 @@ "node": ">= 0.6" } }, + "node_modules/node-abi": { + "version": "3.54.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz", + "integrity": "sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "dev": true, + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-gyp": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", @@ -4258,6 +6221,20 @@ "q": "~1.1.1" } }, + "node_modules/node-schedule": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz", + "integrity": "sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==", + "dev": true, + "dependencies": { + "cron-parser": "^4.2.0", + "long-timeout": "0.1.1", + "sorted-array-functions": "^1.3.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/nodemon": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz", @@ -4619,6 +6596,24 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -4671,6 +6666,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obliterator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", + "dev": true + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4680,6 +6690,27 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "dev": true + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -4697,6 +6728,40 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/otplib": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz", + "integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==", + "dev": true, + "dependencies": { + "@otplib/core": "^12.0.1", + "@otplib/preset-default": "^12.0.1", + "@otplib/preset-v11": "^12.0.1" + } + }, "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", @@ -4825,6 +6890,43 @@ "node": ">=0.10.0" } }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "dev": true, + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "dev": true, + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4877,6 +6979,12 @@ "node": "14 || >=16.14" } }, + "node_modules/path-to-regexp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", + "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==", + "dev": true + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -4886,6 +6994,12 @@ "node": ">=8" } }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", + "dev": true + }, "node_modules/pause-stream": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", @@ -4907,6 +7021,110 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pino": { + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.17.2.tgz", + "integrity": "sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.1.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", + "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", + "dev": true, + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", + "dev": true + }, + "node_modules/prebuild-install": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4925,6 +7143,27 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "dev": true + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -4972,12 +7211,41 @@ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", "dev": true }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5041,6 +7309,12 @@ } ] }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "dev": true + }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", @@ -5123,6 +7397,28 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/read-package-json/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -5149,6 +7445,27 @@ "node": ">=8.10.0" } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", + "dev": true + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", @@ -5241,6 +7558,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -5260,6 +7599,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "node_modules/rimraf": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", @@ -5278,6 +7623,28 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5329,6 +7696,24 @@ } ] }, + "node_modules/safe-regex2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", + "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", + "dev": true, + "dependencies": { + "ret": "~0.2.0" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -5342,6 +7727,12 @@ "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", "dev": true }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "dev": true + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -5396,6 +7787,12 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", + "dev": true + }, "node_modules/set-function-length": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", @@ -5426,6 +7823,18 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5462,16 +7871,10 @@ } }, "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true }, "node_modules/sigstore": { "version": "1.9.0", @@ -5492,6 +7895,51 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -5529,6 +7977,46 @@ "npm": ">= 3.0.0" } }, + "node_modules/socket.io": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dev": true, + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/socks": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", @@ -5563,6 +8051,21 @@ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, + "node_modules/sonic-boom": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", + "integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/sorted-array-functions": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", + "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==", + "dev": true + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5638,6 +8141,15 @@ "node": "*" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, "node_modules/ssri": { "version": "10.0.5", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", @@ -5659,6 +8171,15 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -5681,6 +8202,15 @@ "through": "~2.3.4" } }, + "node_modules/stream-wormhole": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz", + "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5768,6 +8298,47 @@ "node": ">=8" } }, + "node_modules/swagger-ui-dist": { + "version": "5.10.3", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.10.3.tgz", + "integrity": "sha512-fu3aozjxFWsmcO1vyt1q1Ji2kN7KlTd1vHy27E9WgPyXo9nrEzhQPqgxaAjbMsOmb8XFKNGo4Sa3Q+84Fh+pFw==", + "dev": true + }, + "node_modules/systeminformation": { + "version": "5.21.22", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.21.22.tgz", + "integrity": "sha512-gNHloAJSyS+sKWkwvmvozZ1eHrdVTEsynWMTY6lvLGBB70gflkBQFw8drXXr1oEXY84+Vr9tOOrN8xHZLJSycA==", + "dev": true, + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, + "node_modules/tail": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/tail/-/tail-2.2.6.tgz", + "integrity": "sha512-IQ6G4wK/t8VBauYiGPLx+d3fA5XjSVagjWV5SIYzvEvglbQjwEcukeYI68JOPpdydjxhZ9sIgzRlSmwSpphHyw==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/tar": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", @@ -5785,6 +8356,40 @@ "node": ">=10" } }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tar/node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -5821,12 +8426,63 @@ "node": ">=10" } }, + "node_modules/tcp-port-used": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", + "dev": true, + "dependencies": { + "debug": "4.3.1", + "is2": "^2.0.6" + } + }, + "node_modules/tcp-port-used/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==", + "dev": true + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thirty-two": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", + "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==", + "dev": true, + "engines": { + "node": ">=0.2.6" + } + }, + "node_modules/thread-stream": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", + "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", + "dev": true, + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -5851,6 +8507,24 @@ "node": ">=8.0" } }, + "node_modules/toad-cache": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", + "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -5878,6 +8552,21 @@ "node": "*" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/ts-api-utils": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", @@ -5952,6 +8641,18 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", @@ -6013,6 +8714,18 @@ "node": ">=6.0.0" } }, + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "dev": true, + "dependencies": { + "@lukeed/csprng": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -6036,6 +8749,14 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/undici/node_modules/@fastify/busboy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", + "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", + "engines": { + "node": ">=14" + } + }, "node_modules/unique-filename": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", @@ -6093,6 +8814,60 @@ "node": ">=8" } }, + "node_modules/unzipper": { + "version": "0.10.14", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", + "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "node_modules/unzipper/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/unzipper/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/unzipper/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/unzipper/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/update-notifier": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", @@ -6148,6 +8923,15 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -6176,6 +8960,49 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6430,11 +9257,26 @@ "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, "node_modules/xdg-basedir": { "version": "5.1.0", @@ -6470,12 +9312,30 @@ "node": ">=4.0" } }, + "node_modules/xregexp": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.4.1.tgz", + "integrity": "sha512-2u9HwfadaJaY9zHtRRnH6BY6CQVNQKkYm3oLtC9gJXXzfsbACg5X5e4EZZGVAH+YIfa+QA9lsFQTTe3HURF3ag==", + "dev": true, + "dependencies": { + "@babel/runtime-corejs3": "^7.12.1" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 11591856..a4bfc051 100644 --- a/package.json +++ b/package.json @@ -63,11 +63,12 @@ "rxjs": "^7.8.1" }, "devDependencies": { - "@types/node": "^20.11.4", + "@types/node": "^20.11.5", "@typescript-eslint/eslint-plugin": "^6.19.0", "@typescript-eslint/parser": "^6.19.0", "eslint": "^8.56.0", "homebridge": "^1.7.0", + "homebridge-config-ui-x": "^4.55.1", "nodemon": "^3.0.3", "rimraf": "^5.0.5", "ts-node": "^10.9.2", diff --git a/src/devices/leaksensors.ts b/src/devices/leaksensors.ts index 7d528cf9..9c18b584 100644 --- a/src/devices/leaksensors.ts +++ b/src/devices/leaksensors.ts @@ -1,19 +1,9 @@ -<<<<<<< Updated upstream -import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'; -======= import { request } from 'undici'; ->>>>>>> Stashed changes import { interval, Subject } from 'rxjs'; -import superStringify from 'super-stringify'; import { skipWhile, take } from 'rxjs/operators'; -<<<<<<< Updated upstream -import { ResideoPlatform } from '../platform'; -import * as settings from '../settings'; -======= import { ResideoPlatform } from '../platform.js'; import { Service, PlatformAccessory, CharacteristicValue, HAP, API, Logging } from 'homebridge'; import { DeviceURL, ResideoPlatformConfig, devicesConfig, location, resideoDevice } from '../settings.js'; ->>>>>>> Stashed changes /** * Platform Accessory @@ -21,13 +11,10 @@ import { DeviceURL, ResideoPlatformConfig, devicesConfig, location, resideoDevic * Each accessory may expose multiple services of different service types. */ export class LeakSensor { -<<<<<<< Updated upstream -======= public readonly api: API; public readonly log: Logging; public readonly config!: ResideoPlatformConfig; protected readonly hap: HAP; ->>>>>>> Stashed changes // Services service: Service; temperatureService?: Service; @@ -61,15 +48,6 @@ export class LeakSensor { constructor( private readonly platform: ResideoPlatform, -<<<<<<< Updated upstream - private accessory: PlatformAccessory, - public readonly locationId: settings.location['locationID'], - public device: settings.device & settings.devicesConfig, - ) { - this.logs(device); - this.refreshRate(device); - this.config(device); -======= private readonly accessory: PlatformAccessory, public readonly locationId: location['locationID'], public device: resideoDevice & devicesConfig, @@ -88,28 +66,19 @@ export class LeakSensor { this.CurrentRelativeHumidity = accessory.context.CurrentRelativeHumidity || 50; accessory.context.FirmwareRevision = 'v2.0.0'; ->>>>>>> Stashed changes + this.deviceLogging = this.device.logging || this.config.options?.logging || 'standard'; + // this is subject we use to track when we need to POST changes to the Resideo API this.doSensorUpdate = new Subject(); this.SensorUpdateInProgress = false; // set accessory information accessory -<<<<<<< Updated upstream - .getService(this.platform.Service.AccessoryInformation)! - .setCharacteristic(this.platform.Characteristic.Manufacturer, 'Resideo') - .setCharacteristic(this.platform.Characteristic.Model, device.deviceType) - .setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceID) - .setCharacteristic(this.platform.Characteristic.FirmwareRevision, accessory.context.firmwareRevision) - .getCharacteristic(this.platform.Characteristic.FirmwareRevision) - .updateValue(accessory.context.firmwareRevision); -======= .getService(this.hap.Service.AccessoryInformation)! .setCharacteristic(this.hap.Characteristic.Manufacturer, 'Resideo') .setCharacteristic(this.hap.Characteristic.Model, device.deviceType) .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceID) - .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision); ->>>>>>> Stashed changes + .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision || 'v2.0.0'); // get the LightBulb service if it exists, otherwise create a new LightBulb service // you can create multiple services for each accessory @@ -135,15 +104,6 @@ export class LeakSensor { // Leak Sensor Service if (this.device.leaksensor?.hide_leak) { -<<<<<<< Updated upstream - this.debugLog(`Leak Sensor: ${accessory.displayName} Removing Leak Sensor Service`); - this.leakService = this.accessory.getService(this.platform.Service.LeakSensor); - accessory.removeService(this.leakService!); - } else if (!this.leakService) { - this.debugLog(`Leak Sensor: ${accessory.displayName} Add Leak Sensor Service`); - (this.leakService = this.accessory.getService(this.platform.Service.LeakSensor) || this.accessory.addService(this.platform.Service.LeakSensor)), - `${accessory.displayName} Leak Sensor`; -======= this.log.debug(`Leak Sensor: ${accessory.displayName} Removing Leak Sensor Service`); this.leakService = this.accessory.getService(this.hap.Service.LeakSensor); accessory.removeService(this.leakService!); @@ -151,7 +111,6 @@ export class LeakSensor { this.log.debug(`Leak Sensor: ${accessory.displayName} Add Leak Sensor Service`); (this.leakService = this.accessory.getService(this.hap.Service.LeakSensor) || this.accessory.addService(this.hap.Service.LeakSensor)), `${accessory.displayName} Leak Sensor`; ->>>>>>> Stashed changes this.leakService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Leak Sensor`); } else { @@ -160,13 +119,8 @@ export class LeakSensor { // Temperature Sensor Service if (this.device.leaksensor?.hide_temperature) { -<<<<<<< Updated upstream - this.debugLog(`Leak Sensor: ${accessory.displayName} Removing Temperature Sensor Service`); - this.temperatureService = this.accessory.getService(this.platform.Service.TemperatureSensor); -======= this.log.debug(`Leak Sensor: ${accessory.displayName} Removing Temperature Sensor Service`); this.temperatureService = this.accessory.getService(this.hap.Service.TemperatureSensor); ->>>>>>> Stashed changes accessory.removeService(this.temperatureService!); } else if (!this.temperatureService) { this.log.debug(`Leak Sensor: ${accessory.displayName} Add Temperature Sensor Service`); @@ -192,13 +146,8 @@ export class LeakSensor { // Humidity Sensor Service if (this.device.leaksensor?.hide_humidity) { -<<<<<<< Updated upstream - this.debugLog(`Leak Sensor: ${accessory.displayName} Removing Humidity Sensor Service`); - this.humidityService = this.accessory.getService(this.platform.Service.HumiditySensor); -======= this.log.debug(`Leak Sensor: ${accessory.displayName} Removing Humidity Sensor Service`); this.humidityService = this.accessory.getService(this.hap.Service.HumiditySensor); ->>>>>>> Stashed changes accessory.removeService(this.humidityService!); } else if (!this.humidityService) { this.log.debug(`Leak Sensor: ${accessory.displayName} Add Humidity Sensor Service`); @@ -274,31 +223,24 @@ export class LeakSensor { */ async refreshStatus(): Promise { try { -<<<<<<< Updated upstream - const device: any = ( - await this.platform.axios.get(`${settings.DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, { + const { body, statusCode, trailers, opaque, context } = await request(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, { + method: 'GET', query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - method: 'GET', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'pushChanges'; + this.statusCode(statusCode, action); + this.log.debug(`(pushChanges) trailers: ${JSON.stringify(trailers)}`); + this.log.debug(`(pushChanges) opaque: ${JSON.stringify(opaque)}`); + this.log.debug(`(pushChanges) context: ${JSON.stringify(context)}`); const device: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(device)}`); - this.log.debug(`Location StatusCode: ${device.statusCode}`); - /*const device: any = ( - await this.platform.axios.get(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, { ->>>>>>> Stashed changes - params: { - locationId: this.locationId, - }, - }) - ).data;*/ + this.log.debug(`(refreshStatus) ${device.deviceClass}: ${JSON.stringify(device)}`); this.device = device; this.batteryRemaining = Number(device.batteryRemaining); this.waterPresent = device.waterPresent; @@ -322,47 +264,27 @@ export class LeakSensor { if (this.BatteryLevel === undefined) { this.log.debug(`Leak Sensor: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel); - this.debugLog(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.BatteryLevel); this.log.debug(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`); ->>>>>>> Stashed changes } if (this.StatusLowBattery === undefined) { this.log.debug(`Leak Sensor: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery); - this.debugLog(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.StatusLowBattery); this.log.debug(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`); ->>>>>>> Stashed changes } if (!this.device.leaksensor?.hide_leak) { if (this.LeakDetected === undefined) { this.log.debug(`Leak Sensor: ${this.accessory.displayName} LeakDetected: ${this.LeakDetected}`); } else { -<<<<<<< Updated upstream - this.leakService?.updateCharacteristic(this.platform.Characteristic.LeakDetected, this.LeakDetected); - this.debugLog(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic LeakDetected: ${this.LeakDetected}`); -======= this.leakService?.updateCharacteristic(this.hap.Characteristic.LeakDetected, this.LeakDetected); this.log.debug(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic LeakDetected: ${this.LeakDetected}`); ->>>>>>> Stashed changes } if (this.StatusActive === undefined) { this.log.debug(`Leak Sensor: ${this.accessory.displayName} StatusActive: ${this.StatusActive}`); } else { -<<<<<<< Updated upstream - this.leakService?.updateCharacteristic(this.platform.Characteristic.StatusActive, this.StatusActive); - this.debugLog(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic StatusActive: ${this.StatusActive}`); -======= this.leakService?.updateCharacteristic(this.hap.Characteristic.StatusActive, this.StatusActive); this.log.debug(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic StatusActive: ${this.StatusActive}`); ->>>>>>> Stashed changes } } if (this.device.leaksensor?.hide_temperature || this.CurrentTemperature === undefined) { @@ -370,26 +292,16 @@ export class LeakSensor { this.log.debug(`Leak Sensor: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`); } } else { -<<<<<<< Updated upstream - this.temperatureService?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature); - this.debugLog(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`); -======= this.temperatureService?.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, this.CurrentTemperature); this.log.debug(`Leak Sensor: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`); ->>>>>>> Stashed changes } if (this.device.leaksensor?.hide_humidity || this.CurrentRelativeHumidity === undefined) { if (!this.device.leaksensor?.hide_humidity) { this.log.debug(`Leak Sensor: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); } } else { -<<<<<<< Updated upstream - this.humidityService?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity); - this.debugLog(`Leak Sensor: ${this.accessory.displayName}` + ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); -======= this.humidityService?.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity); this.log.debug(`Leak Sensor: ${this.accessory.displayName}` + ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); ->>>>>>> Stashed changes } } @@ -416,28 +328,6 @@ export class LeakSensor { } } if (e.message.includes('400')) { -<<<<<<< Updated upstream - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Bad Request`); - this.debugLog('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.'); - } else if (e.message.includes('401')) { - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Unauthorized Request`); - this.debugLog('Authorization for the API is required, but the request has not been authenticated.'); - } else if (e.message.includes('403')) { - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Forbidden Request`); - this.debugLog('The request has been authenticated but does not have appropriate permissions, or a requested resource is not found.'); - } else if (e.message.includes('404')) { - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Requst Not Found`); - this.debugLog('Specifies the requested path does not exist.'); - } else if (e.message.includes('406')) { - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Request Not Acceptable`); - this.debugLog('The client has requested a MIME type via the Accept header for a value not supported by the server.'); - } else if (e.message.includes('415')) { - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Unsupported Requst Header`); - this.debugLog('The client has defined a contentType header that is not supported by the server.'); - } else if (e.message.includes('422')) { - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Unprocessable Entity`); - this.debugLog( -======= this.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Bad Request`); this.log.debug('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.'); } else if (e.message.includes('401')) { @@ -458,117 +348,10 @@ export class LeakSensor { } else if (e.message.includes('422')) { this.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Unprocessable Entity`); this.log.debug( ->>>>>>> Stashed changes 'The client has made a valid request, but the server cannot process it.' + - ' This is often used for APIs for which certain limits have been exceeded.', + ' This is often used for APIs for which certain limits have been exceeded.', ); } else if (e.message.includes('429')) { -<<<<<<< Updated upstream - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Too Many Requests`); - this.debugLog('The client has exceeded the number of requests allowed for a given time window.'); - } else if (e.message.includes('500')) { - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Internal Server Error`); - this.debugLog('An unexpected error on the SmartThings servers has occurred. These errors should be rare.'); - } else { - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action},`); - } - if (this.deviceLogging.includes('debug')) { - this.platform.log.error(`Leak Sensor: ${this.accessory.displayName} failed to pushChanges, Error Message: ${superStringify(e.message)}`); - } - } - - async config(device: settings.device & settings.devicesConfig): Promise { - let config = {}; - if (device.leaksensor) { - config = device.leaksensor; - } - if (device.logging !== undefined) { - config['logging'] = device.logging; - } - if (device.refreshRate !== undefined) { - config['refreshRate'] = device.refreshRate; - } - if (Object.entries(config).length !== 0) { - this.infoLog(`Leak Sensor: ${this.accessory.displayName} Config: ${superStringify(config)}`); - } - } - - async refreshRate(device: settings.device & settings.devicesConfig): Promise { - if (device.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate; - this.debugLog(`Leak Sensor: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`); - } else if (this.platform.config.options!.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate; - this.debugLog(`Leak Sensor: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`); - } - } - - async logs(device: settings.device & settings.devicesConfig): Promise { - if (this.platform.debugMode) { - this.deviceLogging = this.accessory.context.logging = 'debugMode'; - this.debugLog(`Leak Sensor: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`); - } else if (device.logging) { - this.deviceLogging = this.accessory.context.logging = device.logging; - this.debugLog(`Leak Sensor: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`); - } else if (this.platform.config.options?.logging) { - this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging; - this.debugLog(`Leak Sensor: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`); - } else { - this.deviceLogging = this.accessory.context.logging = 'standard'; - this.debugLog(`Leak Sensor: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`); - } - } - - /** - * Logging for Device - */ - infoLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.info(String(...log)); - } - } - - warnLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.warn(String(...log)); - } - } - - debugWarnLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.warn('[DEBUG]', String(...log)); - } - } - } - - errorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.error(String(...log)); - } - } - - debugErrorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.error('[DEBUG]', String(...log)); - } - } - } - - debugLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging === 'debug') { - this.platform.log.info('[DEBUG]', String(...log)); - } else { - this.platform.log.debug(String(...log)); - } - } - } - - enablingDeviceLogging(): boolean { - return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard'; -======= this.log.error(`Leak Sensor: ${this.accessory.displayName} failed to ${this.action}, Too Many Requests`); this.log.debug('The client has exceeded the number of requests allowed for a given time window.'); } else if (e.message.includes('500')) { @@ -582,39 +365,30 @@ export class LeakSensor { } } - async statusCode(statusCode: number): Promise { - /** - * Meater API Status Codes (https://github.com/apption-labs/meater-cloud-public-rest-api) - * - * Standard Response Codes: 200(OK), 201(Created), 204(No Content) - * https://github.com/apption-labs/meater-cloud-public-rest-api#standard-response - * - * Error Response: 400(Bad Request), 401(Unauthorized), 404(Not Found), 429(Too Many Requests), 500(Internal Server Error) - * https://github.com/apption-labs/meater-cloud-public-rest-api#error-response - **/ + async statusCode(statusCode: number, action: string): Promise { switch (statusCode) { case 200: - this.log.debug(`${this.accessory.displayName} Standard Response, statusCode: ${statusCode}`); + this.log.debug(`${this.device.deviceClass}: ${this.accessory.displayName} Standard Response, statusCode: ${statusCode}, Action: ${action}`); break; case 400: - this.log.error(`${this.accessory.displayName} Bad Request, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Bad Request, statusCode: ${statusCode}, Action: ${action}`); break; case 401: - this.log.error(`${this.accessory.displayName} Unauthorized, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Unauthorized, statusCode: ${statusCode}, Action: ${action}`); break; case 404: - this.log.error(`${this.accessory.displayName} Not Found, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Not Found, statusCode: ${statusCode}, Action: ${action}`); break; case 429: - this.log.error(`${this.accessory.displayName} Too Many Requests, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Too Many Requests, statusCode: ${statusCode}, Action: ${action}`); break; case 500: - this.log.error(`${this.accessory.displayName} Internal Server Error (Meater Server), statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Internal Server Error (Meater Server), statusCode: ${statusCode}, ` + + `Action: ${action}`); break; default: - this.log.info( - `${this.accessory.displayName} Unknown statusCode: ${statusCode}, Report Bugs Here: https://bit.ly/homebridge-meater-bug-report`); + this.log.info(`${this.device.deviceClass}: ${this.accessory.displayName} Unknown statusCode: ${statusCode}, ` + + `Action: ${action}, Report Bugs Here: https://bit.ly/homebridge-resideo-bug-report`); } ->>>>>>> Stashed changes } } diff --git a/src/devices/roomsensors.ts b/src/devices/roomsensors.ts index 530bf4fd..670081ba 100644 --- a/src/devices/roomsensors.ts +++ b/src/devices/roomsensors.ts @@ -1,17 +1,8 @@ -<<<<<<< Updated upstream -import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'; -import { interval, Subject } from 'rxjs'; -import superStringify from 'super-stringify'; -import { skipWhile, take } from 'rxjs/operators'; -import { ResideoPlatform } from '../platform'; -import * as settings from '../settings'; -======= import { Subject, interval } from 'rxjs'; import { take, skipWhile } from 'rxjs/operators'; import { ResideoPlatform } from '../platform.js'; import { Service, PlatformAccessory, CharacteristicValue, API, HAP, Logging } from 'homebridge'; import { devicesConfig, location, resideoDevice, ResideoPlatformConfig, sensorAccessory, T9groups } from '../settings.js'; ->>>>>>> Stashed changes /** * Platform Accessory @@ -19,13 +10,10 @@ import { devicesConfig, location, resideoDevice, ResideoPlatformConfig, sensorAc * Each accessory may expose multiple services of different service types. */ export class RoomSensors { -<<<<<<< Updated upstream -======= public readonly api: API; public readonly log: Logging; public readonly config!: ResideoPlatformConfig; protected readonly hap: HAP; ->>>>>>> Stashed changes // Services service: Service; temperatureService?: Service; @@ -54,22 +42,6 @@ export class RoomSensors { constructor( private readonly platform: ResideoPlatform, -<<<<<<< Updated upstream - private accessory: PlatformAccessory, - public readonly locationId: settings.location['locationID'], - public device: settings.device & settings.devicesConfig, - public sensorAccessory: settings.sensorAccessory, - public readonly group: settings.T9groups, - ) { - this.logs(device); - this.refreshRate(device); - this.config(device); - // default placeholders - this.CurrentTemperature; - this.StatusLowBattery; - this.OccupancyDetected; - this.CurrentRelativeHumidity; -======= private readonly accessory: PlatformAccessory, public readonly locationId: location['locationID'], public device: resideoDevice & devicesConfig, @@ -86,32 +58,23 @@ export class RoomSensors { this.CurrentTemperature = this.accessory.context.CurrentTemperature || 20; this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity || 50; this.TemperatureDisplayUnits = this.accessory.context.TemperatureDisplayUnits || this.hap.Characteristic.TemperatureDisplayUnits.CELSIUS; ->>>>>>> Stashed changes this.accessoryId = sensorAccessory.accessoryId; this.roomId = sensorAccessory.roomId; accessory.context.FirmwareRevision = 'v2.0.0'; + this.deviceLogging = this.device.logging || this.config.options?.logging || 'standard'; + // this is subject we use to track when we need to POST changes to the Resideo API this.doSensorUpdate = new Subject(); this.SensorUpdateInProgress = false; // set accessory information accessory -<<<<<<< Updated upstream - .getService(this.platform.Service.AccessoryInformation)! - .setCharacteristic(this.platform.Characteristic.Manufacturer, 'Resideo') - .setCharacteristic(this.platform.Characteristic.Model, sensorAccessory.accessoryAttribute.model) - .setCharacteristic(this.platform.Characteristic.SerialNumber, sensorAccessory.deviceID) - .setCharacteristic(this.platform.Characteristic.FirmwareRevision, accessory.context.firmwareRevision) - .getCharacteristic(this.platform.Characteristic.FirmwareRevision) - .updateValue(accessory.context.firmwareRevision); -======= .getService(this.hap.Service.AccessoryInformation)! .setCharacteristic(this.hap.Characteristic.Manufacturer, 'Resideo') .setCharacteristic(this.hap.Characteristic.Model, sensorAccessory.accessoryAttribute.model) .setCharacteristic(this.hap.Characteristic.SerialNumber, sensorAccessory.deviceID) - .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision); ->>>>>>> Stashed changes + .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision || 'v2.0.0'); // get the BatteryService service if it exists, otherwise create a new Battery service // you can create multiple services for each accessory @@ -137,13 +100,8 @@ export class RoomSensors { // Temperature Sensor Service if (device.thermostat?.roomsensor?.hide_temperature) { -<<<<<<< Updated upstream - this.debugLog(`Room Sensor: ${accessory.displayName} Removing Temperature Sensor Service`); - this.temperatureService = this.accessory.getService(this.platform.Service.TemperatureSensor); -======= this.log.debug(`Room Sensor: ${accessory.displayName} Removing Temperature Sensor Service`); this.temperatureService = this.accessory.getService(this.hap.Service.TemperatureSensor); ->>>>>>> Stashed changes accessory.removeService(this.temperatureService!); } else if (!this.temperatureService) { this.log.debug(`Room Sensor: ${accessory.displayName} Add Temperature Sensor Service`); @@ -169,13 +127,8 @@ export class RoomSensors { // Occupancy Sensor Service if (device.thermostat?.roomsensor?.hide_occupancy) { -<<<<<<< Updated upstream - this.debugLog(`Room Sensor: ${accessory.displayName} Removing Occupancy Sensor Service`); - this.occupancyService = this.accessory.getService(this.platform.Service.OccupancySensor); -======= this.log.debug(`Room Sensor: ${accessory.displayName} Removing Occupancy Sensor Service`); this.occupancyService = this.accessory.getService(this.hap.Service.OccupancySensor); ->>>>>>> Stashed changes accessory.removeService(this.occupancyService!); } else if (!this.occupancyService) { this.log.debug(`Room Sensor: ${accessory.displayName} Add Occupancy Sensor Service`); @@ -190,13 +143,8 @@ export class RoomSensors { // Humidity Sensor Service if (device.thermostat?.roomsensor?.hide_humidity) { -<<<<<<< Updated upstream - this.debugLog(`Room Sensor: ${accessory.displayName} Removing Humidity Sensor Service`); - this.humidityService = this.accessory.getService(this.platform.Service.HumiditySensor); -======= this.log.debug(`Room Sensor: ${accessory.displayName} Removing Humidity Sensor Service`); this.humidityService = this.accessory.getService(this.hap.Service.HumiditySensor); ->>>>>>> Stashed changes accessory.removeService(this.humidityService!); } else if (!this.humidityService) { this.log.debug(`Room Sensor: ${accessory.displayName} Add Humidity Sensor Service`); @@ -286,46 +234,26 @@ export class RoomSensors { if (this.StatusLowBattery === undefined) { this.log.debug(`Room Sensor: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery); - this.debugLog(`Room Sensor: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.StatusLowBattery); this.log.debug(`Room Sensor: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`); ->>>>>>> Stashed changes } if (this.device.thermostat?.roomsensor?.hide_temperature || (this.CurrentTemperature === undefined && Number.isNaN(this.CurrentTemperature))) { this.log.debug(`Room Sensor: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`); } else { -<<<<<<< Updated upstream - this.temperatureService?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature); - this.debugLog(`Room Sensor: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`); -======= this.temperatureService?.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, this.CurrentTemperature); this.log.debug(`Room Sensor: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`); ->>>>>>> Stashed changes } if (this.device.thermostat?.roomsensor?.hide_occupancy || this.OccupancyDetected === undefined) { this.log.debug(`Room Sensor: ${this.accessory.displayName} OccupancyDetected: ${this.OccupancyDetected}`); } else { -<<<<<<< Updated upstream - this.occupancyService?.updateCharacteristic(this.platform.Characteristic.OccupancyDetected, this.OccupancyDetected); - this.debugLog(`Room Sensor: ${this.accessory.displayName} updateCharacteristic OccupancyDetected: ${this.OccupancyDetected}`); -======= this.occupancyService?.updateCharacteristic(this.hap.Characteristic.OccupancyDetected, this.OccupancyDetected); this.log.debug(`Room Sensor: ${this.accessory.displayName} updateCharacteristic OccupancyDetected: ${this.OccupancyDetected}`); ->>>>>>> Stashed changes } if (this.device.thermostat?.roomsensor?.hide_humidity || this.CurrentRelativeHumidity === undefined) { this.log.debug(`Room Sensor: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); } else { -<<<<<<< Updated upstream - this.humidityService?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity); - this.debugLog(`Room Sensor: ${this.accessory.displayName}` + ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); -======= this.humidityService?.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity); this.log.debug(`Room Sensor: ${this.accessory.displayName}` + ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); ->>>>>>> Stashed changes } } @@ -350,28 +278,6 @@ export class RoomSensors { } } if (e.message.includes('400')) { -<<<<<<< Updated upstream - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Bad Request`); - this.debugLog('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.'); - } else if (e.message.includes('401')) { - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Unauthorized Request`); - this.debugLog('Authorization for the API is required, but the request has not been authenticated.'); - } else if (e.message.includes('403')) { - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Forbidden Request`); - this.debugLog('The request has been authenticated but does not have appropriate permissions, or a requested resource is not found.'); - } else if (e.message.includes('404')) { - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Requst Not Found`); - this.debugLog('Specifies the requested path does not exist.'); - } else if (e.message.includes('406')) { - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Request Not Acceptable`); - this.debugLog('The client has requested a MIME type via the Accept header for a value not supported by the server.'); - } else if (e.message.includes('415')) { - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Unsupported Requst Header`); - this.debugLog('The client has defined a contentType header that is not supported by the server.'); - } else if (e.message.includes('422')) { - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Unprocessable Entity`); - this.debugLog( -======= this.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Bad Request`); this.log.debug('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.'); } else if (e.message.includes('401')) { @@ -392,23 +298,10 @@ export class RoomSensors { } else if (e.message.includes('422')) { this.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Unprocessable Entity`); this.log.debug( ->>>>>>> Stashed changes 'The client has made a valid request, but the server cannot process it.' + ' This is often used for APIs for which certain limits have been exceeded.', ); } else if (e.message.includes('429')) { -<<<<<<< Updated upstream - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Too Many Requests`); - this.debugLog('The client has exceeded the number of requests allowed for a given time window.'); - } else if (e.message.includes('500')) { - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Internal Server Error`); - this.debugLog('An unexpected error on the SmartThings servers has occurred. These errors should be rare.'); - } else { - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action},`); - } - if (this.deviceLogging.includes('debug')) { - this.platform.log.error(`Room Sensor: ${this.accessory.displayName} failed to pushChanges, Error Message: ${superStringify(e.message)}`); -======= this.log.error(`Room Sensor: ${this.accessory.displayName} failed to ${this.action}, Too Many Requests`); this.log.debug('The client has exceeded the number of requests allowed for a given time window.'); } else if (e.message.includes('500')) { @@ -423,15 +316,6 @@ export class RoomSensors { } async statusCode(statusCode: number): Promise { - /** - * Meater API Status Codes (https://github.com/apption-labs/meater-cloud-public-rest-api) - * - * Standard Response Codes: 200(OK), 201(Created), 204(No Content) - * https://github.com/apption-labs/meater-cloud-public-rest-api#standard-response - * - * Error Response: 400(Bad Request), 401(Unauthorized), 404(Not Found), 429(Too Many Requests), 500(Internal Server Error) - * https://github.com/apption-labs/meater-cloud-public-rest-api#error-response - **/ switch (statusCode) { case 200: this.log.debug(`${this.accessory.displayName} Standard Response, statusCode: ${statusCode}`); @@ -453,8 +337,7 @@ export class RoomSensors { break; default: this.log.info( - `${this.accessory.displayName} Unknown statusCode: ${statusCode}, Report Bugs Here: https://bit.ly/homebridge-meater-bug-report`); ->>>>>>> Stashed changes + `${this.accessory.displayName} Unknown statusCode: ${statusCode}, Report Bugs Here: https://bit.ly/homebridge-resideo-bug-report`); } } @@ -469,103 +352,4 @@ export class RoomSensors { // celsius should be to the nearest 0.5 degree return Math.round((5 / 9) * (value - 32) * 2) / 2; } -<<<<<<< Updated upstream - - async config(device: settings.device & settings.devicesConfig): Promise { - let config = {}; - if (device.thermostat?.roomsensor) { - config = device.thermostat?.roomsensor; - } - if (device.logging !== undefined) { - config['logging'] = device.thermostat?.roomsensor?.logging; - } - if (device.refreshRate !== undefined) { - config['refreshRate'] = device.thermostat?.roomsensor?.refreshRate; - } - if (Object.entries(config).length !== 0) { - this.infoLog(`Room Sensor: ${this.accessory.displayName} Config: ${superStringify(config)}`); - } - } - - async refreshRate(device: settings.device & settings.devicesConfig): Promise { - if (device.thermostat?.roomsensor?.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = device.thermostat?.roomsensor?.refreshRate; - this.debugLog(`Room Sensor: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`); - } else if (device.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate; - this.debugLog(`Room Sensor: ${this.accessory.displayName} Using Thermostat Device Config refreshRate: ${this.deviceRefreshRate}`); - } else if (this.platform.config.options!.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate; - this.debugLog(`Room Sensor: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`); - } - } - - async logs(device: settings.device & settings.devicesConfig): Promise { - if (this.platform.debugMode) { - this.deviceLogging = this.accessory.context.logging = 'debugMode'; - this.debugLog(`Room Sensor: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`); - } else if (device.thermostat?.roomsensor?.logging) { - this.deviceLogging = this.accessory.context.logging = device.thermostat?.roomsensor?.logging; - this.debugLog(`Room Sensor: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`); - } else if (this.platform.config.options?.logging) { - this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging; - this.debugLog(`Room Sensor: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`); - } else { - this.deviceLogging = this.accessory.context.logging = 'standard'; - this.debugLog(`Room Sensor: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`); - } - } - - /** - * Logging for Device - */ - infoLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.info(String(...log)); - } - } - - warnLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.warn(String(...log)); - } - } - - debugWarnLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.warn('[DEBUG]', String(...log)); - } - } - } - - errorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.error(String(...log)); - } - } - - debugErrorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.error('[DEBUG]', String(...log)); - } - } - } - - debugLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging === 'debug') { - this.platform.log.info('[DEBUG]', String(...log)); - } else { - this.platform.log.debug(String(...log)); - } - } - } - - enablingDeviceLogging(): boolean { - return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard'; - } -======= ->>>>>>> Stashed changes } diff --git a/src/devices/roomsensorthermostats.ts b/src/devices/roomsensorthermostats.ts index 3476e11f..2a9941df 100644 --- a/src/devices/roomsensorthermostats.ts +++ b/src/devices/roomsensorthermostats.ts @@ -1,11 +1,3 @@ -<<<<<<< Updated upstream -import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'; -import { interval, Subject } from 'rxjs'; -import superStringify from 'super-stringify'; -import { debounceTime, skipWhile, take, tap } from 'rxjs/operators'; -import { ResideoPlatform } from '../platform'; -import * as settings from '../settings'; -======= import { request } from 'undici'; import { interval, Subject } from 'rxjs'; import { ResideoPlatform } from '../platform.js'; @@ -14,7 +6,6 @@ import { Service, PlatformAccessory, CharacteristicValue, API, HAP, Logging } fr import { FanChangeableValues, devicesConfig, modes, resideoDevice, sensorAccessory, T9groups, location, DeviceURL, payload, ResideoPlatformConfig, } from '../settings.js'; ->>>>>>> Stashed changes /** * Platform Accessory @@ -22,13 +13,10 @@ import { * Each accessory may expose multiple services of different service types. */ export class RoomSensorThermostat { -<<<<<<< Updated upstream -======= public readonly api: API; public readonly log: Logging; public readonly config!: ResideoPlatformConfig; protected readonly hap: HAP; ->>>>>>> Stashed changes // Services service: Service; @@ -43,11 +31,11 @@ export class RoomSensorThermostat { HeatingThresholdTemperature!: CharacteristicValue; // Others - modes: settings.modes; + modes: modes; action!: string; roompriority: any; resideoMode!: Array; - deviceFan!: settings.FanChangeableValues; + deviceFan!: FanChangeableValues; // Config deviceLogging!: string; @@ -67,17 +55,6 @@ export class RoomSensorThermostat { constructor( private readonly platform: ResideoPlatform, -<<<<<<< Updated upstream - private accessory: PlatformAccessory, - public readonly locationId: settings.location['locationID'], - public device: settings.device & settings.devicesConfig, - public sensorAccessory: settings.sensorAccessory, - public readonly group: settings.T9groups, - ) { - this.logs(device); - this.refreshRate(device); - this.config(device); -======= private readonly accessory: PlatformAccessory, public readonly locationId: location['locationID'], public device: resideoDevice & devicesConfig, @@ -97,8 +74,10 @@ export class RoomSensorThermostat { this.CurrentHeatingCoolingState = this.accessory.context.CurrentHeatingCoolingState || this.hap.Characteristic.CurrentHeatingCoolingState.OFF; this.CoolingThresholdTemperature = this.accessory.context.CoolingThresholdTemperature || 20; this.HeatingThresholdTemperature = this.accessory.context.HeatingThresholdTemperature || 22; + accessory.context.FirmwareRevision = 'v2.0.0'; + + this.deviceLogging = this.device.logging || this.config.options?.logging || 'standard'; ->>>>>>> Stashed changes // Map Resideo Modes to HomeKit Modes this.modes = { Off: platform.Characteristic.TargetHeatingCoolingState.OFF, @@ -129,21 +108,11 @@ export class RoomSensorThermostat { // set accessory information accessory -<<<<<<< Updated upstream - .getService(this.platform.Service.AccessoryInformation)! - .setCharacteristic(this.platform.Characteristic.Manufacturer, 'Resideo') - .setCharacteristic(this.platform.Characteristic.Model, sensorAccessory.accessoryAttribute.model || '1100') - .setCharacteristic(this.platform.Characteristic.SerialNumber, sensorAccessory.deviceID) - .setCharacteristic(this.platform.Characteristic.FirmwareRevision, accessory.context.firmwareRevision) - .getCharacteristic(this.platform.Characteristic.FirmwareRevision) - .updateValue(accessory.context.firmwareRevision); -======= .getService(this.hap.Service.AccessoryInformation)! .setCharacteristic(this.hap.Characteristic.Manufacturer, 'Resideo') .setCharacteristic(this.hap.Characteristic.Model, sensorAccessory.accessoryAttribute.model || '1100') .setCharacteristic(this.hap.Characteristic.SerialNumber, sensorAccessory.deviceID) - .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision); ->>>>>>> Stashed changes + .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision || 'v2.0.0'); // get the LightBulb service if it exists, otherwise create a new LightBulb service // you can create multiple services for each accessory @@ -345,26 +314,23 @@ export class RoomSensorThermostat { */ async refreshStatus(): Promise { try { -<<<<<<< Updated upstream - const device: any = ( - await this.platform.axios.get(`${settings.DeviceURL}/thermostats/${this.device.deviceID}`, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + method: 'GET', query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - method: 'GET', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'refreshStatus'; + this.statusCode(statusCode, action); const device: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(device)}`); - this.log.debug(`Location StatusCode: ${device.statusCode}`); + this.log.debug(`(refreshStatus) ${device.deviceClass}: ${JSON.stringify(device)}`); /*const device: any = ( await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}`, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, @@ -374,11 +340,7 @@ export class RoomSensorThermostat { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} device: ${JSON.stringify(device)}`); this.log.debug( `Room Sensor Thermostat: ${this.accessory.displayName}` + -<<<<<<< Updated upstream - ` Fetched update for: ${this.device.name} from Resideo API: ${superStringify(this.device.changeableValues)}`, -======= ` Fetched update for: ${this.device.name} from Resideo API: ${JSON.stringify(this.device.changeableValues)}`, ->>>>>>> Stashed changes ); this.parseStatus(); @@ -415,16 +377,12 @@ export class RoomSensorThermostat { this.sensorAccessory = accessory; this.log.debug( `Room Sensor Thermostat: ${this.accessory.displayName}` + -<<<<<<< Updated upstream - ` accessoryAttribute: ${superStringify(this.sensorAccessory.accessoryAttribute)}`, -======= ` accessoryAttribute: ${JSON.stringify(this.sensorAccessory.accessoryAttribute)}`, ->>>>>>> Stashed changes ); this.log.debug( `Room Sensor Thermostat: ${this.accessory.displayName}` + - ` Name: ${this.sensorAccessory.accessoryAttribute.name},` + - ` Software Version: ${this.sensorAccessory.accessoryAttribute.softwareRevision}`, + ` Name: ${this.sensorAccessory.accessoryAttribute.name},` + + ` Software Version: ${this.sensorAccessory.accessoryAttribute.softwareRevision}`, ); } } @@ -449,26 +407,23 @@ export class RoomSensorThermostat { async refreshRoomPriority(): Promise { if (this.device.thermostat?.roompriority?.deviceType === 'Thermostat') { -<<<<<<< Updated upstream - this.roompriority = ( - await this.platform.axios.get(`${settings.DeviceURL}/thermostats/${this.device.deviceID}/priority`, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + method: 'GET', query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - method: 'GET', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'refreshRoomPriority'; + this.statusCode(statusCode, action); const roompriority: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(roompriority)}`); - this.log.debug(`Location StatusCode: ${roompriority.statusCode}`); + this.log.debug(`(refreshRoomPriority) roompriority: ${JSON.stringify(roompriority)}`); /*this.roompriority = ( await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, @@ -503,54 +458,42 @@ export class RoomSensorThermostat { */ if (this.device.thermostat?.roompriority?.deviceType === 'Thermostat') { if (this.device.thermostat?.roompriority.priorityType === 'FollowMe') { -<<<<<<< Updated upstream - this.platform.log.info( -======= this.log.info( ->>>>>>> Stashed changes `Room Sensor Thermostat: ${this.accessory.displayName} sent request to Resideo API, Priority Type: ` + - `${this.device.thermostat?.roompriority.priorityType} Built-in Occupancy Sensor(s) Will be used to set Priority Automatically.`, + `${this.device.thermostat?.roompriority.priorityType} Built-in Occupancy Sensor(s) Will be used to set Priority Automatically.`, ); } else if (this.device.thermostat?.roompriority.priorityType === 'WholeHouse') { -<<<<<<< Updated upstream - this.platform.log.info( -======= this.log.info( ->>>>>>> Stashed changes `Room Sensor Thermostat: ${this.accessory.displayName} sent request to Resideo API,` + - ` Priority Type: ${this.device.thermostat?.roompriority.priorityType}`, + ` Priority Type: ${this.device.thermostat?.roompriority.priorityType}`, ); } else if (this.device.thermostat?.roompriority.priorityType === 'PickARoom') { -<<<<<<< Updated upstream - this.platform.log.info( -======= this.log.info( ->>>>>>> Stashed changes `Room Sensor Thermostat: ${this.accessory.displayName} sent request to Resideo API,` + - ` Room Priority: ${this.sensorAccessory.accessoryAttribute.name}, Priority Type: ${this.device.thermostat?.roompriority.priorityType}`, + ` Room Priority: ${this.sensorAccessory.accessoryAttribute.name}, Priority Type: ${this.device.thermostat?.roompriority.priorityType}`, ); } // Make the API request -<<<<<<< Updated upstream - await this.platform.axios.put(`${settings.DeviceURL}/thermostats/${this.device.deviceID}/priority`, payload, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + method: 'PUT', + body: JSON.stringify(payload), query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - body: JSON.stringify(payload), - method: 'PUT', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'pushRoomChanges'; + this.statusCode(statusCode, action); + this.log.debug(`(pushRoomChanges) body: ${JSON.stringify(body)}`); const pushRoomChanges: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(pushRoomChanges)}`); - this.log.debug(`Location StatusCode: ${pushRoomChanges.statusCode}`); + this.log.debug(`(pushRoomChanges) pushRoomChanges: ${JSON.stringify(pushRoomChanges)}`); + this.statusCode(pushRoomChanges.statusCode, action); /*await this.platform.axios.put(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, payload, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, @@ -571,7 +514,7 @@ export class RoomSensorThermostat { mode: this.resideoMode[Number(this.TargetHeatingCoolingState)], thermostatSetpointStatus: this.device.thermostat?.thermostatSetpointStatus, autoChangeoverActive: this.device.changeableValues!.autoChangeoverActive, - } as settings.payload; + } as payload; // Set the heat and cool set point value based on the selected mode switch (this.TargetHeatingCoolingState) { @@ -580,9 +523,9 @@ export class RoomSensorThermostat { payload.coolSetpoint = this.toFahrenheit(Number(this.CoolingThresholdTemperature)); this.log.debug( `Room Sensor Thermostat: ${this.accessory.displayName}` + - ` TargetHeatingCoolingState (HEAT): ${this.TargetHeatingCoolingState},` + - ` TargetTemperature: ${this.toFahrenheit(Number(this.TargetTemperature))} heatSetpoint,` + - ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint`, + ` TargetHeatingCoolingState (HEAT): ${this.TargetHeatingCoolingState},` + + ` TargetTemperature: ${this.toFahrenheit(Number(this.TargetTemperature))} heatSetpoint,` + + ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint`, ); break; case this.platform.Characteristic.TargetHeatingCoolingState.COOL: @@ -590,9 +533,9 @@ export class RoomSensorThermostat { payload.heatSetpoint = this.toFahrenheit(Number(this.HeatingThresholdTemperature)); this.log.debug( `Room Sensor Thermostat: ${this.accessory.displayName}` + - ` TargetHeatingCoolingState (COOL): ${this.TargetHeatingCoolingState},` + - ` TargetTemperature: ${this.toFahrenheit(Number(this.TargetTemperature))} coolSetpoint,` + - ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, + ` TargetHeatingCoolingState (COOL): ${this.TargetHeatingCoolingState},` + + ` TargetTemperature: ${this.toFahrenheit(Number(this.TargetTemperature))} coolSetpoint,` + + ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, ); break; case this.platform.Characteristic.TargetHeatingCoolingState.AUTO: @@ -600,9 +543,9 @@ export class RoomSensorThermostat { payload.heatSetpoint = this.toFahrenheit(Number(this.HeatingThresholdTemperature)); this.log.debug( `Room Sensor Thermostat: ${this.accessory.displayName}` + - ` TargetHeatingCoolingState (AUTO): ${this.TargetHeatingCoolingState},` + - ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint,` + - ` HeatingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, + ` TargetHeatingCoolingState (AUTO): ${this.TargetHeatingCoolingState},` + + ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint,` + + ` HeatingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, ); break; default: @@ -610,36 +553,32 @@ export class RoomSensorThermostat { payload.heatSetpoint = this.toFahrenheit(Number(this.HeatingThresholdTemperature)); this.log.debug( `Room Sensor Thermostat: ${this.accessory.displayName}` + - ` TargetHeatingCoolingState (OFF): ${this.TargetHeatingCoolingState},` + - ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint,` + - ` HeatingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, + ` TargetHeatingCoolingState (OFF): ${this.TargetHeatingCoolingState},` + + ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint,` + + ` HeatingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, ); } -<<<<<<< Updated upstream - this.platform.log.info(`Room Sensor Thermostat: ${this.accessory.displayName} set request (${superStringify(payload)}) to Resideo API.`); - - // Make the API request - await this.platform.axios.post(`${settings.DeviceURL}/thermostats/${this.device.deviceID}`, payload, { -======= this.log.info(`Room Sensor Thermostat: ${this.accessory.displayName} set request (${JSON.stringify(payload)}) to Resideo API.`); // Make the API request - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + method: 'POST', + body: JSON.stringify(payload), query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - body: JSON.stringify(payload), - method: 'POST', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'pushChanges'; + this.statusCode(statusCode, action); const pushChanges: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(pushChanges)}`); - this.log.debug(`Location StatusCode: ${pushChanges.statusCode}`); + this.log.debug(`(pushChanges) pushChanges: ${JSON.stringify(pushChanges)}`); + this.statusCode(pushChanges.statusCode, action); /*await this.platform.axios.post(`${DeviceURL}/thermostats/${this.device.deviceID}`, payload, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, @@ -659,105 +598,65 @@ export class RoomSensorThermostat { if (this.TemperatureDisplayUnits === undefined) { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} TemperatureDisplayUnits: ${this.TemperatureDisplayUnits}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits, this.TemperatureDisplayUnits); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.TemperatureDisplayUnits, this.TemperatureDisplayUnits); this.log.debug( ->>>>>>> Stashed changes `Room Sensor Thermostat: ${this.accessory.displayName}` + ` updateCharacteristic TemperatureDisplayUnits: ${this.TemperatureDisplayUnits}`, ); } if (this.CurrentTemperature === undefined) { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature); - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName}` + ` updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, this.CurrentTemperature); this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`); ->>>>>>> Stashed changes } if (this.CurrentRelativeHumidity === undefined) { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity); this.log.debug( ->>>>>>> Stashed changes `Room Sensor Thermostat: ${this.accessory.displayName}` + ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`, ); } if (this.TargetTemperature === undefined) { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} TargetTemperature: ${this.TargetTemperature}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.TargetTemperature, this.TargetTemperature); - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName} updateCharacteristic TargetTemperature: ${this.TargetTemperature}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.TargetTemperature, this.TargetTemperature); this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} updateCharacteristic TargetTemperature: ${this.TargetTemperature}`); ->>>>>>> Stashed changes } if (this.HeatingThresholdTemperature === undefined) { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} HeatingThresholdTemperature: ${this.HeatingThresholdTemperature}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature, this.HeatingThresholdTemperature); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.HeatingThresholdTemperature, this.HeatingThresholdTemperature); this.log.debug( ->>>>>>> Stashed changes `Room Sensor Thermostat: ${this.accessory.displayName} updateCharacteristic` + - ` HeatingThresholdTemperature: ${this.HeatingThresholdTemperature}`, + ` HeatingThresholdTemperature: ${this.HeatingThresholdTemperature}`, ); } if (this.CoolingThresholdTemperature === undefined) { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} CoolingThresholdTemperature: ${this.CoolingThresholdTemperature}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature, this.CoolingThresholdTemperature); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.CoolingThresholdTemperature, this.CoolingThresholdTemperature); this.log.debug( ->>>>>>> Stashed changes `Room Sensor Thermostat: ${this.accessory.displayName} updateCharacteristic` + - ` CoolingThresholdTemperature: ${this.CoolingThresholdTemperature}`, + ` CoolingThresholdTemperature: ${this.CoolingThresholdTemperature}`, ); } if (this.TargetHeatingCoolingState === undefined) { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} TargetHeatingCoolingState: ${this.TargetHeatingCoolingState}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState, this.TargetHeatingCoolingState); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.TargetHeatingCoolingState, this.TargetHeatingCoolingState); this.log.debug( ->>>>>>> Stashed changes `Room Sensor Thermostat: ${this.accessory.displayName} updateCharacteristic` + - ` TargetHeatingCoolingState: ${this.TargetHeatingCoolingState}`, + ` TargetHeatingCoolingState: ${this.TargetHeatingCoolingState}`, ); } if (this.CurrentHeatingCoolingState === undefined) { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} CurrentHeatingCoolingState: ${this.CurrentHeatingCoolingState}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState, this.CurrentHeatingCoolingState); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.CurrentHeatingCoolingState, this.CurrentHeatingCoolingState); this.log.debug( ->>>>>>> Stashed changes `Room Sensor Thermostat: ${this.accessory.displayName} updateCharacteristic` + - ` CurrentHeatingCoolingState: ${this.TargetHeatingCoolingState}`, + ` CurrentHeatingCoolingState: ${this.TargetHeatingCoolingState}`, ); } } @@ -811,28 +710,6 @@ export class RoomSensorThermostat { } } if (e.message.includes('400')) { -<<<<<<< Updated upstream - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Bad Request`); - this.debugLog('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.'); - } else if (e.message.includes('401')) { - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Unauthorized Request`); - this.debugLog('Authorization for the API is required, but the request has not been authenticated.'); - } else if (e.message.includes('403')) { - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Forbidden Request`); - this.debugLog('The request has been authenticated but does not have appropriate permissions, or a requested resource is not found.'); - } else if (e.message.includes('404')) { - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Requst Not Found`); - this.debugLog('Specifies the requested path does not exist.'); - } else if (e.message.includes('406')) { - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Request Not Acceptable`); - this.debugLog('The client has requested a MIME type via the Accept header for a value not supported by the server.'); - } else if (e.message.includes('415')) { - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Unsupported Requst Header`); - this.debugLog('The client has defined a contentType header that is not supported by the server.'); - } else if (e.message.includes('422')) { - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Unprocessable Entity`); - this.debugLog( -======= this.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Bad Request`); this.log.debug('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.'); } else if (e.message.includes('401')) { @@ -853,24 +730,10 @@ export class RoomSensorThermostat { } else if (e.message.includes('422')) { this.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Unprocessable Entity`); this.log.debug( ->>>>>>> Stashed changes 'The client has made a valid request, but the server cannot process it.' + - ' This is often used for APIs for which certain limits have been exceeded.', + ' This is often used for APIs for which certain limits have been exceeded.', ); } else if (e.message.includes('429')) { -<<<<<<< Updated upstream - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Too Many Requests`); - this.debugLog('The client has exceeded the number of requests allowed for a given time window.'); - } else if (e.message.includes('500')) { - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Internal Server Error`); - this.debugLog('An unexpected error on the SmartThings servers has occurred. These errors should be rare.'); - } else { - this.platform.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action},`); - } - if (this.deviceLogging.includes('debug')) { - this.platform.log.error( - `Room Sensor Thermostat: ${this.accessory.displayName} failed to pushChanges, ` + `Error Message: ${superStringify(e.message)}`, -======= this.log.error(`Room Sensor Thermostat: ${this.accessory.displayName} failed to ${this.action}, Too Many Requests`); this.log.debug('The client has exceeded the number of requests allowed for a given time window.'); } else if (e.message.includes('500')) { @@ -882,43 +745,34 @@ export class RoomSensorThermostat { if (this.deviceLogging.includes('debug')) { this.log.error( `Room Sensor Thermostat: ${this.accessory.displayName} failed to pushChanges, ` + `Error Message: ${JSON.stringify(e.message)}`, ->>>>>>> Stashed changes ); } } - async statusCode(statusCode: number): Promise { - /** - * Meater API Status Codes (https://github.com/apption-labs/meater-cloud-public-rest-api) - * - * Standard Response Codes: 200(OK), 201(Created), 204(No Content) - * https://github.com/apption-labs/meater-cloud-public-rest-api#standard-response - * - * Error Response: 400(Bad Request), 401(Unauthorized), 404(Not Found), 429(Too Many Requests), 500(Internal Server Error) - * https://github.com/apption-labs/meater-cloud-public-rest-api#error-response - **/ + async statusCode(statusCode: number, action: string): Promise { switch (statusCode) { case 200: - this.log.debug(`${this.accessory.displayName} Standard Response, statusCode: ${statusCode}`); + this.log.debug(`${this.device.deviceClass}: ${this.accessory.displayName} Standard Response, statusCode: ${statusCode}, Action: ${action}`); break; case 400: - this.log.error(`${this.accessory.displayName} Bad Request, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Bad Request, statusCode: ${statusCode}, Action: ${action}`); break; case 401: - this.log.error(`${this.accessory.displayName} Unauthorized, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Unauthorized, statusCode: ${statusCode}, Action: ${action}`); break; case 404: - this.log.error(`${this.accessory.displayName} Not Found, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Not Found, statusCode: ${statusCode}, Action: ${action}`); break; case 429: - this.log.error(`${this.accessory.displayName} Too Many Requests, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Too Many Requests, statusCode: ${statusCode}, Action: ${action}`); break; case 500: - this.log.error(`${this.accessory.displayName} Internal Server Error (Meater Server), statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Internal Server Error (Meater Server), statusCode: ${statusCode}, ` + + `Action: ${action}`); break; default: - this.log.info( - `${this.accessory.displayName} Unknown statusCode: ${statusCode}, Report Bugs Here: https://bit.ly/homebridge-meater-bug-report`); + this.log.info(`${this.device.deviceClass}: ${this.accessory.displayName} Unknown statusCode: ${statusCode}, ` + + `Action: ${action}, Report Bugs Here: https://bit.ly/homebridge-resideo-bug-report`); } } @@ -959,13 +813,8 @@ export class RoomSensorThermostat { } async setTemperatureDisplayUnits(value: CharacteristicValue): Promise { -<<<<<<< Updated upstream - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName} Set TemperatureDisplayUnits: ${value}`); - this.platform.log.warn('Changing the Hardware Display Units from HomeKit is not supported.'); -======= this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} Set TemperatureDisplayUnits: ${value}`); this.log.warn('Changing the Hardware Display Units from HomeKit is not supported.'); ->>>>>>> Stashed changes // change the temp units back to the one the Resideo API said the thermostat was set to setTimeout(() => { @@ -1016,103 +865,4 @@ export class RoomSensorThermostat { this.log.debug(`Room Sensor Thermostat: ${this.accessory.displayName} Only Show These Modes: ${JSON.stringify(TargetState)}`); return TargetState; } -<<<<<<< Updated upstream - - async config(device: settings.device & settings.devicesConfig): Promise { - let config = {}; - if (device.thermostat?.roompriority) { - config = device.thermostat?.roompriority; - } - if (device.thermostat?.roompriority?.logging !== undefined) { - config['logging'] = device.thermostat?.roompriority?.logging; - } - if (device.thermostat?.roompriority?.refreshRate !== undefined) { - config['refreshRate'] = device.thermostat?.roompriority?.refreshRate; - } - if (Object.entries(config).length !== 0) { - this.infoLog(`Room Sensor Thermostat: ${this.accessory.displayName} Config: ${superStringify(config)}`); - } - } - - async refreshRate(device: settings.device & settings.devicesConfig): Promise { - if (device.thermostat?.roompriority?.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = device.thermostat?.roompriority?.refreshRate; - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`); - } else if (device.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate; - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName} Using Thermostat Device Config refreshRate: ${this.deviceRefreshRate}`); - } else if (this.platform.config.options!.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate; - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`); - } - } - - async logs(device: settings.device & settings.devicesConfig): Promise { - if (this.platform.debugMode) { - this.deviceLogging = this.accessory.context.logging = 'debugMode'; - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`); - } else if (device.thermostat?.roompriority?.logging) { - this.deviceLogging = this.accessory.context.logging = device.thermostat?.roompriority?.logging; - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`); - } else if (this.platform.config.options?.logging) { - this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging; - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`); - } else { - this.deviceLogging = this.accessory.context.logging = 'standard'; - this.debugLog(`Room Sensor Thermostat: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`); - } - } - - /** - * Logging for Device - */ - infoLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.info(String(...log)); - } - } - - warnLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.warn(String(...log)); - } - } - - debugWarnLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.warn('[DEBUG]', String(...log)); - } - } - } - - errorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.error(String(...log)); - } - } - - debugErrorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.error('[DEBUG]', String(...log)); - } - } - } - - debugLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging === 'debug') { - this.platform.log.info('[DEBUG]', String(...log)); - } else { - this.platform.log.debug(String(...log)); - } - } - } - - enablingDeviceLogging(): boolean { - return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard'; - } -======= ->>>>>>> Stashed changes } diff --git a/src/devices/thermostats.ts b/src/devices/thermostats.ts index fd10df6a..ca4809de 100644 --- a/src/devices/thermostats.ts +++ b/src/devices/thermostats.ts @@ -1,11 +1,3 @@ -<<<<<<< Updated upstream -import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'; -import { interval, Subject } from 'rxjs'; -import superStringify from 'super-stringify'; -import { debounceTime, skipWhile, take, tap } from 'rxjs/operators'; -import { ResideoPlatform } from '../platform'; -import * as settings from '../settings'; -======= import { request } from 'undici'; import { interval, Subject } from 'rxjs'; import { ResideoPlatform } from '../platform.js'; @@ -14,7 +6,6 @@ import { API, CharacteristicValue, HAP, Service, PlatformAccessory, Logging } fr import { DeviceURL, FanChangeableValues, devicesConfig, holdModes, location, modes, resideoDevice, payload, ResideoPlatformConfig, } from '../settings.js'; ->>>>>>> Stashed changes /** * Platform Accessory @@ -22,14 +13,11 @@ import { * Each accessory may expose multiple services of different service types. */ export class Thermostats { -<<<<<<< Updated upstream -======= public readonly api: API; public readonly log: Logging; public readonly config!: ResideoPlatformConfig; protected readonly hap: HAP; // Services ->>>>>>> Stashed changes service!: Service; fanService?: Service; humidityService?: Service; @@ -52,15 +40,15 @@ export class Thermostats { TargetFanState!: CharacteristicValue; // Others - modes: settings.modes; - holdModes: settings.holdModes; + modes: modes; + holdModes: holdModes; action!: string; heatSetpoint!: number; coolSetpoint!: number; thermostatSetpointStatus!: string; resideoMode!: Array; resideoHold!: Array; - fanMode!: settings.FanChangeableValues; + fanMode!: FanChangeableValues; // Others - T9 Only roompriority!: any; @@ -83,15 +71,6 @@ export class Thermostats { constructor( private readonly platform: ResideoPlatform, -<<<<<<< Updated upstream - private accessory: PlatformAccessory, - public readonly locationId: settings.location['locationID'], - public device: settings.device & settings.devicesConfig, - ) { - this.logs(device); - this.refreshRate(device); - this.config(device); -======= private readonly accessory: PlatformAccessory, public readonly locationId: location['locationID'], public device: resideoDevice & devicesConfig, @@ -114,9 +93,10 @@ export class Thermostats { this.ProgrammableSwitchOutputState = accessory.context.ProgrammableSwitchOutputState || 0; accessory.context.FirmwareRevision = 'v2.0.0'; + this.deviceLogging = this.device.logging || this.config.options?.logging || 'standard'; + this.Active = accessory.context.Active || this.hap.Characteristic.Active.ACTIVE; this.TargetFanState = accessory.context.TargetFanState || this.hap.Characteristic.TargetFanState.MANUAL; ->>>>>>> Stashed changes // Map Resideo Modes to HomeKit Modes this.modes = { Off: platform.Characteristic.TargetHeatingCoolingState.OFF, @@ -127,8 +107,8 @@ export class Thermostats { // Map Resideo Hold Modes to HomeKit StatefulProgrammableSwitch Events this.holdModes = { NoHold: platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS, - TemporaryHold: platform.Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS, - PermanentHold: platform.Characteristic.ProgrammableSwitchEvent.LONG_PRESS, + TemporaryHold: platform.Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS, + PermanentHold: platform.Characteristic.ProgrammableSwitchEvent.LONG_PRESS, }; // Map HomeKit Modes to Resideo Modes @@ -136,12 +116,6 @@ export class Thermostats { this.resideoMode = ['Off', 'Heat', 'Cool', 'Auto']; this.resideoHold = ['NoHold', 'TemporaryHold', 'PermanentHold']; -<<<<<<< Updated upstream - // default placeholders - this.Active = this.platform.Characteristic.Active.INACTIVE; - this.TargetFanState = this.platform.Characteristic.TargetFanState.MANUAL; -======= ->>>>>>> Stashed changes if (this.thermostatSetpointStatus === undefined) { accessory.context.thermostatSetpointStatus = device.thermostat?.thermostatSetpointStatus; this.thermostatSetpointStatus = accessory.context.thermostatSetpointStatus; @@ -160,29 +134,15 @@ export class Thermostats { // set accessory information accessory -<<<<<<< Updated upstream - .getService(this.platform.Service.AccessoryInformation)! - .setCharacteristic(this.platform.Characteristic.Manufacturer, 'Resideo') - .setCharacteristic(this.platform.Characteristic.Model, device.deviceModel) - .setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceID) - .setCharacteristic(this.platform.Characteristic.FirmwareRevision, accessory.context.firmwareRevision) - .getCharacteristic(this.platform.Characteristic.FirmwareRevision) - .updateValue(accessory.context.firmwareRevision); - - //Thermostat Service - (this.service = this.accessory.getService(this.platform.Service.Thermostat) || this.accessory.addService(this.platform.Service.Thermostat)), - accessory.displayName; -======= .getService(this.hap.Service.AccessoryInformation)! .setCharacteristic(this.hap.Characteristic.Manufacturer, 'Resideo') .setCharacteristic(this.hap.Characteristic.Model, device.deviceModel) .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceID) - .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision); + .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision || 'v2.0.0'); //Thermostat Service (this.service = this.accessory.getService(this.hap.Service.Thermostat) || this.accessory.addService(this.hap.Service.Thermostat)), accessory.displayName; ->>>>>>> Stashed changes //Service Name this.service.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName); @@ -241,16 +201,6 @@ export class Thermostats { // Fan Controls if (device.thermostat?.hide_fan) { -<<<<<<< Updated upstream - this.debugLog(`Thermostat: ${accessory.displayName} Removing Fanv2 Service`); - this.fanService = this.accessory.getService(this.platform.Service.Fanv2); - accessory.removeService(this.fanService!); - } else if (!this.fanService && device.settings?.fan) { - this.debugLog(`Thermostat: ${accessory.displayName} Add Fanv2 Service`); - this.debugLog(`Thermostat: ${accessory.displayName} Available Fan Settings ${superStringify(device.settings.fan)}`); - (this.fanService = this.accessory.getService(this.platform.Service.Fanv2) || this.accessory.addService(this.platform.Service.Fanv2)), - `${accessory.displayName} Fan`; -======= this.log.debug(`Thermostat: ${accessory.displayName} Removing Fanv2 Service`); this.fanService = this.accessory.getService(this.hap.Service.Fanv2); accessory.removeService(this.fanService!); @@ -259,7 +209,6 @@ export class Thermostats { this.log.debug(`Thermostat: ${accessory.displayName} Available Fan Settings ${JSON.stringify(device.settings.fan)}`); (this.fanService = this.accessory.getService(this.hap.Service.Fanv2) || this.accessory.addService(this.hap.Service.Fanv2)), `${accessory.displayName} Fan`; ->>>>>>> Stashed changes this.fanService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Fan`); @@ -272,24 +221,14 @@ export class Thermostats { // Humidity Sensor Service if (device.thermostat?.hide_humidity) { -<<<<<<< Updated upstream - this.debugLog(`Thermostat: ${accessory.displayName} Removing Humidity Sensor Service`); - this.humidityService = this.accessory.getService(this.platform.Service.HumiditySensor); -======= this.log.debug(`Thermostat: ${accessory.displayName} Removing Humidity Sensor Service`); this.humidityService = this.accessory.getService(this.hap.Service.HumiditySensor); ->>>>>>> Stashed changes accessory.removeService(this.humidityService!); } else if (!this.humidityService && device.indoorHumidity) { this.log.debug(`Thermostat: ${accessory.displayName} Add Humidity Sensor Service`); (this.humidityService = -<<<<<<< Updated upstream - this.accessory.getService(this.platform.Service.HumiditySensor) || this.accessory.addService(this.platform.Service.HumiditySensor)), - `${device.name} Humidity Sensor`; -======= this.accessory.getService(this.hap.Service.HumiditySensor) || this.accessory.addService(this.hap.Service.HumiditySensor)), `${device.name} Humidity Sensor`; ->>>>>>> Stashed changes this.humidityService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Humidity Sensor`); @@ -308,14 +247,8 @@ export class Thermostats { // get the StatefulProgrammableSwitch service if it exists, otherwise create a new StatefulProgrammableSwitch service // you can create multiple services for each accessory (this.statefulService = -<<<<<<< Updated upstream - accessory.getService(this.platform.Service.StatefulProgrammableSwitch) || - accessory.addService(this.platform.Service.StatefulProgrammableSwitch)), - `${accessory.displayName} ${device.deviceModel}`; -======= accessory.getService(this.hap.Service.StatefulProgrammableSwitch) || accessory.addService(this.hap.Service.StatefulProgrammableSwitch)), `${accessory.displayName} ${device.deviceModel}`; ->>>>>>> Stashed changes this.statefulService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName); if (!this.statefulService.testCharacteristic(this.platform.Characteristic.ConfiguredName)) { @@ -439,27 +372,17 @@ export class Thermostats { async parseStatus(): Promise { this.log.debug(`Thermostat: ${this.accessory.displayName} parseStatus`); if (this.device.units === 'Fahrenheit') { -<<<<<<< Updated upstream - this.TemperatureDisplayUnits = this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT; - this.debugLog( -======= this.TemperatureDisplayUnits = this.hap.Characteristic.TemperatureDisplayUnits.FAHRENHEIT; this.log.debug( ->>>>>>> Stashed changes `Thermostat: ${this.accessory.displayName} parseStatus` + - ` TemperatureDisplayUnits: ${this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT}`, + ` TemperatureDisplayUnits: ${this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT}`, ); } if (this.device.units === 'Celsius') { -<<<<<<< Updated upstream - this.TemperatureDisplayUnits = this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS; - this.debugLog( -======= this.TemperatureDisplayUnits = this.hap.Characteristic.TemperatureDisplayUnits.CELSIUS; this.log.debug( ->>>>>>> Stashed changes `Thermostat: ${this.accessory.displayName} parseStatus` + - ` TemperatureDisplayUnits: ${this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS}`, + ` TemperatureDisplayUnits: ${this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS}`, ); } @@ -475,7 +398,7 @@ export class Thermostats { this.HeatingThresholdTemperature = this.toCelsius(this.device.changeableValues!.heatSetpoint); this.log.debug( `Thermostat: ${this.accessory.displayName} parseStatus` + - ` HeatingThresholdTemperature: ${this.toCelsius(this.device.changeableValues!.heatSetpoint)}`, + ` HeatingThresholdTemperature: ${this.toCelsius(this.device.changeableValues!.heatSetpoint)}`, ); } @@ -483,7 +406,7 @@ export class Thermostats { this.CoolingThresholdTemperature = this.toCelsius(this.device.changeableValues!.coolSetpoint); this.log.debug( `Thermostat: ${this.accessory.displayName} parseStatus` + - ` CoolingThresholdTemperature: ${this.toCelsius(this.device.changeableValues!.coolSetpoint)}`, + ` CoolingThresholdTemperature: ${this.toCelsius(this.device.changeableValues!.coolSetpoint)}`, ); } @@ -501,21 +424,21 @@ export class Thermostats { this.CurrentHeatingCoolingState = 1; this.log.debug( `Thermostat: ${this.accessory.displayName}` + - ` parseStatus Currently Mode (HEAT): ${this.device.operationStatus!.mode}(${this.CurrentHeatingCoolingState})`, + ` parseStatus Currently Mode (HEAT): ${this.device.operationStatus!.mode}(${this.CurrentHeatingCoolingState})`, ); break; case 'Cool': this.CurrentHeatingCoolingState = 2; this.log.debug( `Thermostat: ${this.accessory.displayName}` + - ` parseStatus Currently Mode (COOL): ${this.device.operationStatus!.mode}(${this.CurrentHeatingCoolingState})`, + ` parseStatus Currently Mode (COOL): ${this.device.operationStatus!.mode}(${this.CurrentHeatingCoolingState})`, ); break; default: this.CurrentHeatingCoolingState = 0; this.log.debug( `Thermostat: ${this.accessory.displayName}` + - ` parseStatus Currently Mode (OFF): ${this.device.operationStatus!.mode}(${this.CurrentHeatingCoolingState})`, + ` parseStatus Currently Mode (OFF): ${this.device.operationStatus!.mode}(${this.CurrentHeatingCoolingState})`, ); } @@ -525,7 +448,7 @@ export class Thermostats { this.TargetTemperature = this.toCelsius(this.device.changeableValues!.heatSetpoint); this.log.debug( `Thermostat: ${this.accessory.displayName}` + - ` parseStatus TargetTemperature (HEAT): ${this.toCelsius(this.device.changeableValues!.heatSetpoint)})`, + ` parseStatus TargetTemperature (HEAT): ${this.toCelsius(this.device.changeableValues!.heatSetpoint)})`, ); } } else { @@ -533,7 +456,7 @@ export class Thermostats { this.TargetTemperature = this.toCelsius(this.device.changeableValues!.coolSetpoint); this.log.debug( `Thermostat: ${this.accessory.displayName}` + - ` parseStatus TargetTemperature (OFF/COOL): ${this.toCelsius(this.device.changeableValues!.coolSetpoint)})`, + ` parseStatus TargetTemperature (OFF/COOL): ${this.toCelsius(this.device.changeableValues!.coolSetpoint)})`, ); } } @@ -561,26 +484,23 @@ export class Thermostats { */ async refreshStatus(): Promise { try { -<<<<<<< Updated upstream - const device: any = ( - await this.platform.axios.get(`${settings.DeviceURL}/thermostats/${this.device.deviceID}`, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + method: 'GET', query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - method: 'GET', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'refreshStatus'; + this.statusCode(statusCode, action); const device: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(device)}`); - this.log.debug(`Location StatusCode: ${device.statusCode}`); + this.log.debug(`(refreshStatus) ${device.deviceClass}: ${JSON.stringify(device)}`); /*const device: any = ( await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}`, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, @@ -588,32 +508,28 @@ export class Thermostats { ).data;*/ this.device = device; this.log.debug(`Thermostat: ${this.accessory.displayName} device: ${JSON.stringify(this.device)}`); - this.log.debug(`Thermostat: ${this.accessory.displayName} refreshStatus for ${this.device.name} - from Resideo API: ${JSON.stringify(this.device.changeableValues)}`); + this.log.debug(`Thermostat: ${this.accessory.displayName} refreshStatus for ${this.device.name}` + + `from Resideo API: ${JSON.stringify(this.device.changeableValues)}`); await this.refreshRoomPriority(); if (this.device.settings?.fan && !device.thermostat?.hide_fan) { -<<<<<<< Updated upstream - const fanMode: any = ( - await this.platform.axios.get(`${settings.DeviceURL}/thermostats/${this.device.deviceID}/fan`, { -======= - - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/fan`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/fan`, { + method: 'GET', query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - method: 'GET', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'refreshStatus/fan'; + this.statusCode(statusCode, action); + this.log.debug(`(refreshStatus:fan) statusCode: ${statusCode}`); const fanMode: any = await body.json(); - this.log.debug(`Fan Mode: ${JSON.stringify(fanMode)}`); - this.log.debug(`Fan Mode StatusCode: ${fanMode.statusCode}`); - + this.log.debug(`(refreshStatus:fan) Fan Mode: ${JSON.stringify(fanMode)}`); /*const fanMode: any = ( await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}/fan`, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, @@ -621,8 +537,8 @@ export class Thermostats { ).data;*/ this.fanMode = fanMode; this.log.debug(`Thermostat: ${this.accessory.displayName} fanMode: ${JSON.stringify(this.fanMode)}`); - this.log.debug(`Thermostat: ${this.accessory.displayName} refreshStatus for ${this.device.name} Fan - from Resideo Fan API: ${JSON.stringify(this.fanMode)}`); + this.log.debug(`Thermostat: ${this.accessory.displayName} refreshStatus for ${this.device.name} Fan` + + `from Resideo Fan API: ${JSON.stringify(this.fanMode)}`); } this.pushChangesthermostatSetpointStatus(); this.parseStatus(); @@ -636,32 +552,29 @@ export class Thermostats { async refreshRoomPriority(): Promise { if (this.device.thermostat?.roompriority?.deviceType === 'Thermostat' && this.device.deviceModel === 'T9-T10') { -<<<<<<< Updated upstream - this.roompriority = ( - await this.platform.axios.get(`${settings.DeviceURL}/thermostats/${this.device.deviceID}/priority`, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + method: 'GET', query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - method: 'GET', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'refreshRoomPriority'; + this.statusCode(statusCode, action); const roompriority: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(roompriority)}`); - this.log.debug(`Location StatusCode: ${roompriority.statusCode}`); + this.log.debug(`(refreshRoomPriority) roompriority: ${JSON.stringify(roompriority)}`); /*this.roompriority = ( await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, }) ).data;*/ - this.log.debug(`Thermostat: ${this.accessory.displayName} Priority: ${JSON.stringify(this.roompriority.data)}`); + this.log.debug(`Thermostat: ${this.accessory.displayName} Priority: ${JSON.stringify(roompriority)}`); } } @@ -670,8 +583,7 @@ export class Thermostats { */ async pushChanges(): Promise { try { - const payload = {} as settings.payload; - + const payload = {} as payload; // Only include mode on certain models switch (this.device.deviceModel) { case 'Unknown': @@ -681,7 +593,7 @@ export class Thermostats { payload.mode = this.resideoMode[Number(this.TargetHeatingCoolingState)]; this.log.debug( `Thermostat: ${this.accessory.displayName} send TargetHeatingCoolingState` + - ` mode: ${this.resideoMode[Number(this.TargetHeatingCoolingState)]}`, + ` mode: ${this.resideoMode[Number(this.TargetHeatingCoolingState)]}`, ); } @@ -696,12 +608,12 @@ export class Thermostats { if (this.thermostatSetpointStatus === 'TemporaryHold') { this.log.warn( `Thermostat: ${this.accessory.displayName} send thermostatSetpointStatus: ` + - `${payload.thermostatSetpointStatus}, Model: ${this.device.deviceModel}`, + `${payload.thermostatSetpointStatus}, Model: ${this.device.deviceModel}`, ); } else { this.log.debug( `Thermostat: ${this.accessory.displayName} send thermostatSetpointStatus: ` + - `${payload.thermostatSetpointStatus}, Model: ${this.device.deviceModel}`, + `${payload.thermostatSetpointStatus}, Model: ${this.device.deviceModel}`, ); } } @@ -718,14 +630,14 @@ export class Thermostats { payload.autoChangeoverActive = true; this.log.debug( `Thermostat: ${this.accessory.displayName} Heating/Cooling state set to Auto for` + - ` Model: ${this.device.deviceModel}, Force autoChangeoverActive: ${payload.autoChangeoverActive}`, + ` Model: ${this.device.deviceModel}, Force autoChangeoverActive: ${payload.autoChangeoverActive}`, ); } else { payload.autoChangeoverActive = this.device.changeableValues?.autoChangeoverActive; this.log.debug( `Thermostat: ${this.accessory.displayName} Heating/cooling state not set to Auto for` + - ` Model: ${this.device.deviceModel}, Using device setting` + - ` autoChangeoverActive: ${this.device.changeableValues!.autoChangeoverActive}`, + ` Model: ${this.device.deviceModel}, Using device setting` + + ` autoChangeoverActive: ${this.device.changeableValues!.autoChangeoverActive}`, ); } break; @@ -736,7 +648,7 @@ export class Thermostats { payload.autoChangeoverActive = this.device.changeableValues!.autoChangeoverActive; this.log.debug( `Thermostat: ${this.accessory.displayName} set autoChangeoverActive to ` + - `${this.device.changeableValues!.autoChangeoverActive} for Model: ${this.device.deviceModel}`, + `${this.device.changeableValues!.autoChangeoverActive} for Model: ${this.device.deviceModel}`, ); } @@ -754,7 +666,7 @@ export class Thermostats { } this.log.info( `Thermostat: ${this.accessory.displayName} sent request to Resideo API thermostatSetpoint:` + - ` ${payload.thermostatSetpoint}, unit: ${payload.unit}`, + ` ${payload.thermostatSetpoint}, unit: ${payload.unit}`, ); break; @@ -766,8 +678,8 @@ export class Thermostats { payload.coolSetpoint = this.toFahrenheit(Number(this.CoolingThresholdTemperature)); this.log.debug( `Thermostat: ${this.accessory.displayName} TargetHeatingCoolingState (HEAT): ${this.TargetHeatingCoolingState},` + - ` TargetTemperature: ${this.toFahrenheit(Number(this.TargetTemperature))} heatSetpoint,` + - ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint`, + ` TargetTemperature: ${this.toFahrenheit(Number(this.TargetTemperature))} heatSetpoint,` + + ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint`, ); break; case this.platform.Characteristic.TargetHeatingCoolingState.COOL: @@ -775,8 +687,8 @@ export class Thermostats { payload.heatSetpoint = this.toFahrenheit(Number(this.HeatingThresholdTemperature)); this.log.debug( `Thermostat: ${this.accessory.displayName} TargetHeatingCoolingState (COOL): ${this.TargetHeatingCoolingState},` + - ` TargetTemperature: ${this.toFahrenheit(Number(this.TargetTemperature))} coolSetpoint,` + - ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, + ` TargetTemperature: ${this.toFahrenheit(Number(this.TargetTemperature))} coolSetpoint,` + + ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, ); break; case this.platform.Characteristic.TargetHeatingCoolingState.AUTO: @@ -784,8 +696,8 @@ export class Thermostats { payload.heatSetpoint = this.toFahrenheit(Number(this.HeatingThresholdTemperature)); this.log.debug( `Thermostat: ${this.accessory.displayName} TargetHeatingCoolingState (AUTO): ${this.TargetHeatingCoolingState},` + - ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint,` + - ` HeatingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, + ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint,` + + ` HeatingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, ); break; default: @@ -793,33 +705,33 @@ export class Thermostats { payload.heatSetpoint = this.toFahrenheit(Number(this.HeatingThresholdTemperature)); this.log.debug( `Thermostat: ${this.accessory.displayName} TargetHeatingCoolingState (OFF): ${this.TargetHeatingCoolingState},` + - ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint,` + - ` HeatingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, + ` CoolingThresholdTemperature: ${this.toFahrenheit(Number(this.CoolingThresholdTemperature))} coolSetpoint,` + + ` HeatingThresholdTemperature: ${this.toFahrenheit(Number(this.HeatingThresholdTemperature))} heatSetpoint`, ); } this.log.info(`Room Sensor Thermostat: ${this.accessory.displayName} set request (${JSON.stringify(payload)}) to Resideo API.`); } // Attempt to make the API request -<<<<<<< Updated upstream - await this.platform.axios.post(`${settings.DeviceURL}/thermostats/${this.device.deviceID}`, payload, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + method: 'POST', + body: JSON.stringify(payload), query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - body: JSON.stringify(payload), - method: 'POST', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'pushChanges'; + this.statusCode(statusCode, action); const pushChanges: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(pushChanges)}`); - this.log.debug(`Location StatusCode: ${pushChanges.statusCode}`); + this.log.debug(`(pushChanges) pushChanges: ${JSON.stringify(pushChanges)}`); + this.log.debug(`(pushChanges) pushChanges StatusCode: ${pushChanges.statusCode}`); + this.statusCode(pushChanges.statusCode, action); /*await this.platform.axios.post(`${DeviceURL}/thermostats/${this.device.deviceID}`, payload, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, @@ -870,36 +782,36 @@ export class Thermostats { if (this.device.priorityType === 'FollowMe') { this.log.info( `Sending request for ${this.accessory.displayName} to Resideo API Priority Type:` + - ` ${this.device.priorityType}, Built-in Occupancy Sensor(s) Will be used to set Priority Automatically`, + ` ${this.device.priorityType}, Built-in Occupancy Sensor(s) Will be used to set Priority Automatically`, ); } else if (this.device.priorityType === 'WholeHouse') { this.log.info(`Sending request for ${this.accessory.displayName} to Resideo API Priority Type:` + ` ${this.device.priorityType}`); } else if (this.device.priorityType === 'PickARoom') { this.log.info( `Sending request for ${this.accessory.displayName} to Resideo API Room Priority:` + - ` ${this.device.inBuiltSensorState!.roomName}, Priority Type: ${this.device.thermostat?.roompriority.priorityType}`, + ` ${this.device.inBuiltSensorState!.roomName}, Priority Type: ${this.device.thermostat?.roompriority.priorityType}`, ); } // Make the API request -<<<<<<< Updated upstream - await this.platform.axios.put(`${settings.DeviceURL}/thermostats/${this.device.deviceID}/priority`, payload, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + method: 'PUT', + body: JSON.stringify(payload), query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - body: JSON.stringify(payload), - method: 'PUT', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'pushRoomChanges'; + this.statusCode(statusCode, action); const pushRoomChanges: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(pushRoomChanges)}`); - this.log.debug(`Location StatusCode: ${pushRoomChanges.statusCode}`); + this.log.debug(`(pushRoomChanges) pushRoomChanges: ${JSON.stringify(pushRoomChanges)}`); + this.log.debug(`(pushRoomChanges) pushRoomChanges StatusCode: ${pushRoomChanges.statusCode}`); + this.statusCode(pushRoomChanges.statusCode, action); /*await this.platform.axios.put(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, payload, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, @@ -916,96 +828,56 @@ export class Thermostats { if (this.TemperatureDisplayUnits === undefined) { this.log.debug(`Thermostat: ${this.accessory.displayName} TemperatureDisplayUnits: ${this.TemperatureDisplayUnits}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits, this.TemperatureDisplayUnits); - this.debugLog(`Thermostat: ${this.accessory.displayName} updateCharacteristic TemperatureDisplayUnits: ${this.TemperatureDisplayUnits}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.TemperatureDisplayUnits, this.TemperatureDisplayUnits); this.log.debug(`Thermostat: ${this.accessory.displayName} updateCharacteristic TemperatureDisplayUnits: ${this.TemperatureDisplayUnits}`); ->>>>>>> Stashed changes } if (this.CurrentTemperature === undefined) { this.log.debug(`Thermostat: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature); - this.debugLog(`Thermostat: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, this.CurrentTemperature); this.log.debug(`Thermostat: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`); ->>>>>>> Stashed changes } if (!this.device.indoorHumidity || this.device.thermostat?.hide_humidity || this.CurrentRelativeHumidity === undefined) { this.log.debug(`Thermostat: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); } else { -<<<<<<< Updated upstream - this.humidityService!.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity); - this.debugLog(`Thermostat: ${this.accessory.displayName} updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); -======= this.humidityService!.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity); this.log.debug(`Thermostat: ${this.accessory.displayName} updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`); ->>>>>>> Stashed changes } if (this.TargetTemperature === undefined) { this.log.debug(`Thermostat: ${this.accessory.displayName} TargetTemperature: ${this.TargetTemperature}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.TargetTemperature, this.TargetTemperature); - this.debugLog(`Thermostat: ${this.accessory.displayName} updateCharacteristic TargetTemperature: ${this.TargetTemperature}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.TargetTemperature, this.TargetTemperature); this.log.debug(`Thermostat: ${this.accessory.displayName} updateCharacteristic TargetTemperature: ${this.TargetTemperature}`); ->>>>>>> Stashed changes } if (this.HeatingThresholdTemperature === undefined) { this.log.debug(`Thermostat: ${this.accessory.displayName} HeatingThresholdTemperature: ${this.HeatingThresholdTemperature}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature, this.HeatingThresholdTemperature); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.HeatingThresholdTemperature, this.HeatingThresholdTemperature); this.log.debug( ->>>>>>> Stashed changes `Thermostat: ${this.accessory.displayName} updateCharacteristic` + ` HeatingThresholdTemperature: ${this.HeatingThresholdTemperature}`, ); } if (this.CoolingThresholdTemperature === undefined) { this.log.debug(`Thermostat: ${this.accessory.displayName} CoolingThresholdTemperature: ${this.CoolingThresholdTemperature}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature, this.CoolingThresholdTemperature); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.CoolingThresholdTemperature, this.CoolingThresholdTemperature); this.log.debug( ->>>>>>> Stashed changes `Thermostat: ${this.accessory.displayName} updateCharacteristic` + ` CoolingThresholdTemperature: ${this.CoolingThresholdTemperature}`, ); } if (this.TargetHeatingCoolingState === undefined) { this.log.debug(`Thermostat: ${this.accessory.displayName} TargetHeatingCoolingState: ${this.TargetHeatingCoolingState}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState, this.TargetHeatingCoolingState); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.TargetHeatingCoolingState, this.TargetHeatingCoolingState); this.log.debug( ->>>>>>> Stashed changes `Thermostat: ${this.accessory.displayName} updateCharacteristic` + ` TargetHeatingCoolingState: ${this.TargetHeatingCoolingState}`, ); } if (this.CurrentHeatingCoolingState === undefined) { this.log.debug(`Thermostat: ${this.accessory.displayName} CurrentHeatingCoolingState: ${this.CurrentHeatingCoolingState}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState, this.CurrentHeatingCoolingState); - this.debugLog( -======= this.service.updateCharacteristic(this.hap.Characteristic.CurrentHeatingCoolingState, this.CurrentHeatingCoolingState); this.log.debug( ->>>>>>> Stashed changes `Thermostat: ${this.accessory.displayName} updateCharacteristic` + ` CurrentHeatingCoolingState: ${this.TargetHeatingCoolingState}`, ); } @@ -1013,24 +885,14 @@ export class Thermostats { if (this.TargetFanState === undefined) { this.log.debug(`Thermostat Fan: ${this.accessory.displayName} TargetFanState: ${this.TargetFanState}`); } else { -<<<<<<< Updated upstream - this.fanService?.updateCharacteristic(this.platform.Characteristic.TargetFanState, this.TargetFanState); - this.debugLog(`Thermostat Fan: ${this.accessory.displayName} updateCharacteristic TargetFanState: ${this.TargetFanState}`); -======= this.fanService?.updateCharacteristic(this.hap.Characteristic.TargetFanState, this.TargetFanState); this.log.debug(`Thermostat Fan: ${this.accessory.displayName} updateCharacteristic TargetFanState: ${this.TargetFanState}`); ->>>>>>> Stashed changes } if (this.Active === undefined) { this.log.debug(`Thermostat Fan: ${this.accessory.displayName} Active: ${this.Active}`); } else { -<<<<<<< Updated upstream - this.fanService?.updateCharacteristic(this.platform.Characteristic.Active, this.Active); - this.debugLog(`Thermostat Fan: ${this.accessory.displayName} updateCharacteristic Active: ${this.Active}`); -======= this.fanService?.updateCharacteristic(this.hap.Characteristic.Active, this.Active); this.log.debug(`Thermostat Fan: ${this.accessory.displayName} updateCharacteristic Active: ${this.Active}`); ->>>>>>> Stashed changes } } } @@ -1119,7 +981,7 @@ export class Thermostats { this.log.error(`Thermostat: ${this.accessory.displayName} failed to ${this.action}, Unprocessable Entity`); this.log.debug( 'The client has made a valid request, but the server cannot process it.' + - ' This is often used for APIs for which certain limits have been exceeded.', + ' This is often used for APIs for which certain limits have been exceeded.', ); } else if (e.message.includes('429')) { this.log.error(`Thermostat: ${this.accessory.displayName} failed to ${this.action}, Too Many Requests`); @@ -1135,38 +997,30 @@ export class Thermostats { } } - async statusCode(statusCode: number): Promise { - /** - * Meater API Status Codes (https://github.com/apption-labs/meater-cloud-public-rest-api) - * - * Standard Response Codes: 200(OK), 201(Created), 204(No Content) - * https://github.com/apption-labs/meater-cloud-public-rest-api#standard-response - * - * Error Response: 400(Bad Request), 401(Unauthorized), 404(Not Found), 429(Too Many Requests), 500(Internal Server Error) - * https://github.com/apption-labs/meater-cloud-public-rest-api#error-response - **/ + async statusCode(statusCode: number, action: string): Promise { switch (statusCode) { case 200: - this.log.debug(`${this.accessory.displayName} Standard Response, statusCode: ${statusCode}`); + this.log.debug(`${this.device.deviceClass}: ${this.accessory.displayName} Standard Response, statusCode: ${statusCode}, Action: ${action}`); break; case 400: - this.log.error(`${this.accessory.displayName} Bad Request, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Bad Request, statusCode: ${statusCode}, Action: ${action}`); break; case 401: - this.log.error(`${this.accessory.displayName} Unauthorized, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Unauthorized, statusCode: ${statusCode}, Action: ${action}`); break; case 404: - this.log.error(`${this.accessory.displayName} Not Found, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Not Found, statusCode: ${statusCode}, Action: ${action}`); break; case 429: - this.log.error(`${this.accessory.displayName} Too Many Requests, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Too Many Requests, statusCode: ${statusCode}, Action: ${action}`); break; case 500: - this.log.error(`${this.accessory.displayName} Internal Server Error (Meater Server), statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Internal Server Error (Meater Server), statusCode: ${statusCode}, ` + + `Action: ${action}`); break; default: - this.log.info( - `${this.accessory.displayName} Unknown statusCode: ${statusCode}, Report Bugs Here: https://bit.ly/homebridge-meater-bug-report`); + this.log.info(`${this.device.deviceClass}: ${this.accessory.displayName} Unknown statusCode: ${statusCode}, ` + + `Action: ${action}, Report Bugs Here: https://bit.ly/homebridge-resideo-bug-report`); } } @@ -1305,25 +1159,25 @@ export class Thermostats { this.log.info(`Sending request for ${this.accessory.displayName} to Resideo API Fan Mode: ${payload.mode}`); // Make the API request -<<<<<<< Updated upstream - await this.platform.axios.post(`${settings.DeviceURL}/thermostats/${this.device.deviceID}/fan`, payload, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/fan`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}/fan`, { + method: 'PUT', + body: JSON.stringify(payload), query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - body: JSON.stringify(payload), - method: 'PUT', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'pushFanChanges'; + this.statusCode(statusCode, action); const pushRoomChanges: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(pushRoomChanges)}`); - this.log.debug(`Location StatusCode: ${pushRoomChanges.statusCode}`); + this.log.debug(`(pushFanChanges) pushFanChanges: ${JSON.stringify(pushRoomChanges)}`); + this.log.debug(`(pushFanChanges) pushFanChanges StatusCode: ${pushRoomChanges.statusCode}`); + this.statusCode(pushRoomChanges.statusCode, action); /*await this.platform.axios.post(`${DeviceURL}/thermostats/${this.device.deviceID}/fan`, payload, { ->>>>>>> Stashed changes params: { locationId: this.locationId, }, @@ -1367,100 +1221,4 @@ export class Thermostats { this.log.debug(`Thermostat: ${this.accessory.displayName} Only Show These Modes: ${JSON.stringify(TargetState)}`); return TargetState; } -<<<<<<< Updated upstream - - async config(device: settings.device & settings.devicesConfig): Promise { - let config = {}; - if (device.thermostat) { - config = device.thermostat; - } - if (device.logging !== undefined) { - config['logging'] = device.logging; - } - if (device.refreshRate !== undefined) { - config['refreshRate'] = device.refreshRate; - } - if (Object.entries(config).length !== 0) { - this.infoLog(`Thermostat: ${this.accessory.displayName} Config: ${superStringify(config)}`); - } - } - - async refreshRate(device: settings.device & settings.devicesConfig): Promise { - if (device.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate; - this.debugLog(`Thermostat: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`); - } else if (this.platform.config.options!.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate; - this.debugLog(`Thermostat: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`); - } - } - - async logs(device: settings.device & settings.devicesConfig): Promise { - if (this.platform.debugMode) { - this.deviceLogging = this.accessory.context.logging = 'debugMode'; - this.debugLog(`Thermostat: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`); - } else if (device.logging) { - this.deviceLogging = this.accessory.context.logging = device.logging; - this.debugLog(`Thermostat: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`); - } else if (this.platform.config.options?.logging) { - this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging; - this.debugLog(`Thermostat: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`); - } else { - this.deviceLogging = this.accessory.context.logging = 'standard'; - this.debugLog(`Thermostat: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`); - } - } - - /** - * Logging for Device - */ - infoLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.info(String(...log)); - } - } - - warnLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.warn(String(...log)); - } - } - - debugWarnLog({ log = [] }: { log?: any[] } = {}): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.warn('[DEBUG]', String(...log)); - } - } - } - - errorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.error(String(...log)); - } - } - - debugErrorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.error('[DEBUG]', String(...log)); - } - } - } - - debugLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging === 'debug') { - this.platform.log.info('[DEBUG]', String(...log)); - } else { - this.platform.log.debug(String(...log)); - } - } - } - - enablingDeviceLogging(): boolean { - return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard'; - } -======= ->>>>>>> Stashed changes } diff --git a/src/devices/valve.ts b/src/devices/valve.ts index 669cc69e..ce65a0ba 100644 --- a/src/devices/valve.ts +++ b/src/devices/valve.ts @@ -1,18 +1,9 @@ -<<<<<<< Updated upstream -import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'; -import { interval, Subject } from 'rxjs'; -import superStringify from 'super-stringify'; -import { skipWhile, take } from 'rxjs/operators'; -import { ResideoPlatform } from '../platform'; -import * as settings from '../settings'; -======= import { request } from 'undici'; import { interval, Subject } from 'rxjs'; -import { skipWhile, take } from 'rxjs/operators'; +import { debounceTime, skipWhile, take, tap } from 'rxjs/operators'; import { ResideoPlatform } from '../platform.js'; import { API, HAP, CharacteristicValue, PlatformAccessory, Service, Logging } from 'homebridge'; -import { devicesConfig, DeviceURL, location, resideoDevice, ResideoPlatformConfig } from '../settings.js'; ->>>>>>> Stashed changes +import { devicesConfig, DeviceURL, location, resideoDevice, payload, ResideoPlatformConfig } from '../settings.js'; /** * Platform Accessory @@ -20,13 +11,10 @@ import { devicesConfig, DeviceURL, location, resideoDevice, ResideoPlatformConfi * Each accessory may expose multiple services of different service types. */ export class Valve { -<<<<<<< Updated upstream -======= public readonly api: API; public readonly log: Logging; public readonly config!: ResideoPlatformConfig; protected readonly hap: HAP; ->>>>>>> Stashed changes // Services service: Service; @@ -46,21 +34,11 @@ export class Valve { valvetype!: number; // Updates - SensorUpdateInProgress!: boolean; - doSensorUpdate!: Subject; + valveUpdateInProgress!: boolean; + doValveUpdate!: Subject; constructor( private readonly platform: ResideoPlatform, -<<<<<<< Updated upstream - private accessory: PlatformAccessory, - public readonly locationId: settings.location['locationID'], - public device: settings.device & settings.devicesConfig, - ) { - this.logs(device); - this.refreshRate(device); - this.config(device); - this.valveType(device); -======= private readonly accessory: PlatformAccessory, public readonly locationId: location['locationID'], public device: resideoDevice & devicesConfig, @@ -91,38 +69,24 @@ export class Valve { } accessory.context.FirmwareRevision = 'v2.0.0'; ->>>>>>> Stashed changes + this.deviceLogging = this.device.logging || this.config.options?.logging || 'standard'; + // this is subject we use to track when we need to POST changes to the Resideo API - this.doSensorUpdate = new Subject(); - this.SensorUpdateInProgress = false; + this.doValveUpdate = new Subject(); + this.valveUpdateInProgress = false; // set accessory information accessory -<<<<<<< Updated upstream - .getService(this.platform.Service.AccessoryInformation)! - .setCharacteristic(this.platform.Characteristic.Manufacturer, 'Resideo') - .setCharacteristic(this.platform.Characteristic.Model, device.deviceType) - .setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceID) - .setCharacteristic(this.platform.Characteristic.FirmwareRevision, accessory.context.firmwareRevision) - .getCharacteristic(this.platform.Characteristic.FirmwareRevision) - .updateValue(accessory.context.firmwareRevision); - - // get the LightBulb service if it exists, otherwise create a new LightBulb service - // you can create multiple services for each accessory - (this.service = this.accessory.getService(this.platform.Service.Valve) || this.accessory.addService(this.platform.Service.Valve)), - `${accessory.displayName}`; -======= .getService(this.hap.Service.AccessoryInformation)! .setCharacteristic(this.hap.Characteristic.Manufacturer, 'Resideo') .setCharacteristic(this.hap.Characteristic.Model, device.deviceType) .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceID) - .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision); + .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.firmwareRevision || 'v2.0.0'); // get the LightBulb service if it exists, otherwise create a new LightBulb service // you can create multiple services for each accessory (this.service = this.accessory.getService(this.hap.Service.Valve) || this.accessory.addService(this.hap.Service.Valve)), `${accessory.displayName}`; ->>>>>>> Stashed changes // To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error, // when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id: @@ -154,10 +118,35 @@ export class Valve { // Start an update interval interval(this.platform.config.options!.refreshRate! * 1000) - .pipe(skipWhile(() => this.SensorUpdateInProgress)) + .pipe(skipWhile(() => this.valveUpdateInProgress)) .subscribe(async () => { await this.refreshStatus(); }); + + // Watch for Lock change events + // We put in a debounce of 100ms so we don't make duplicate calls + this.doValveUpdate + .pipe( + tap(() => { + this.valveUpdateInProgress = true; + }), + debounceTime(this.config.options!.pushRate! * 1000), + ) + .subscribe(async () => { + try { + await this.pushChanges(); + } catch (e: any) { + this.log.error(`doValveUpdate pushChanges: ${JSON.stringify(e)}`); + } + // Refresh the status from the API + interval(this.deviceRefreshRate * 500) + .pipe(skipWhile(() => this.valveUpdateInProgress)) + .pipe(take(1)) + .subscribe(async () => { + await this.refreshStatus(); + }); + this.valveUpdateInProgress = false; + }); } /** @@ -184,27 +173,23 @@ export class Valve { */ async refreshStatus(): Promise { try { -<<<<<<< Updated upstream - const device: any = ( - await this.platform.axios.get(`${settings.DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, { + const { body, statusCode } = await request(`${DeviceURL}/shutoffvalve/${this.device.deviceID}`, { + method: 'GET', query: { - locationId: this.locationId, + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - method: 'GET', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'pushChanges'; + this.statusCode(statusCode, action); const device: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(device)}`); - this.log.debug(`Location StatusCode: ${device.statusCode}`); - + this.log.debug(`(refreshStatus) ${device.deviceClass}: ${JSON.stringify(device)}`); /*const device: any = ( - await this.platform.axios.get(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, { ->>>>>>> Stashed changes + await this.platform.axios.get(`${DeviceURL}/shutoffvalve/${this.device.deviceID}`, { params: { locationId: this.locationId, }, @@ -223,6 +208,47 @@ export class Valve { } } + /** + * Pushes the requested changes to the August API + */ + async pushChanges(): Promise { + try { + const payload = {} as payload; + if (this.Active === this.platform.Characteristic.Active.ACTIVE) { + payload.state = 'open'; + } else { + payload.state = 'closed'; + } + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + method: 'POST', + body: JSON.stringify(payload), + query: { + 'locationId': this.locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', + }, + }); + const action = 'pushChanges'; + this.statusCode(statusCode, action); + const pushChanges: any = await body.json(); + this.log.debug(`(pushChanges) ${this.device.deviceClass}: ${JSON.stringify(pushChanges)}`); + this.log.debug(`(pushChanges) ${this.device.deviceClass} StatusCode: ${JSON.stringify(pushChanges.statusCode)}`); + this.statusCode(pushChanges.statusCode, action); + /*await this.platform.axios.post(`${DeviceURL}/thermostats/${this.device.deviceID}`, payload, { + params: { + locationId: this.locationId, + }, + });*/ + this.log.debug(`Thermostat: ${this.accessory.displayName} pushChanges: ${JSON.stringify(payload)}`); + } catch (e: any) { + this.log.error(`pushChanges: ${JSON.stringify(e)}`); + this.log.error(`Lock: ${this.accessory.displayName} failed pushChanges, Error Message: ${JSON.stringify(e.message)}`); + } + } + /** * Updates the status for each of the HomeKit Characteristics */ @@ -230,24 +256,14 @@ export class Valve { if (this.Active === undefined) { this.log.debug(`Valve: ${this.accessory.displayName} Active: ${this.Active}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.Active, this.Active); - this.debugLog(`Valve: ${this.accessory.displayName} updateCharacteristic Active: ${this.Active}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.Active, this.Active); this.log.debug(`Valve: ${this.accessory.displayName} updateCharacteristic Active: ${this.Active}`); ->>>>>>> Stashed changes } if (this.InUse === undefined) { this.log.debug(`Valve: ${this.accessory.displayName} InUse: ${this.InUse}`); } else { -<<<<<<< Updated upstream - this.service.updateCharacteristic(this.platform.Characteristic.InUse, this.InUse); - this.debugLog(`Valve: ${this.accessory.displayName} updateCharacteristic InUse: ${this.InUse}`); -======= this.service.updateCharacteristic(this.hap.Characteristic.InUse, this.InUse); this.log.debug(`Valve: ${this.accessory.displayName} updateCharacteristic InUse: ${this.InUse}`); ->>>>>>> Stashed changes } } @@ -255,7 +271,9 @@ export class Valve { * Handle requests to set the "Active" characteristic */ setActive(value) { - this.log.debug('Triggered SET Active:', value); + this.log.debug(`Thermostat: ${this.accessory.displayName} Set Active: ${value}`); + this.Active = value; + this.doValveUpdate.next(); } /** @@ -279,7 +297,7 @@ export class Valve { if (this.action === 'refreshStatus') { // Refresh the status from the API interval(5000) - .pipe(skipWhile(() => this.SensorUpdateInProgress)) + .pipe(skipWhile(() => this.valveUpdateInProgress)) .pipe(take(1)) .subscribe(async () => { await this.refreshStatus(); @@ -287,28 +305,6 @@ export class Valve { } } if (e.message.includes('400')) { -<<<<<<< Updated upstream - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Bad Request`); - this.debugLog('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.'); - } else if (e.message.includes('401')) { - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Unauthorized Request`); - this.debugLog('Authorization for the API is required, but the request has not been authenticated.'); - } else if (e.message.includes('403')) { - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Forbidden Request`); - this.debugLog('The request has been authenticated but does not have appropriate permissions, or a requested resource is not found.'); - } else if (e.message.includes('404')) { - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Requst Not Found`); - this.debugLog('Specifies the requested path does not exist.'); - } else if (e.message.includes('406')) { - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Request Not Acceptable`); - this.debugLog('The client has requested a MIME type via the Accept header for a value not supported by the server.'); - } else if (e.message.includes('415')) { - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Unsupported Requst Header`); - this.debugLog('The client has defined a contentType header that is not supported by the server.'); - } else if (e.message.includes('422')) { - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Unprocessable Entity`); - this.debugLog( -======= this.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Bad Request`); this.log.debug('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.'); } else if (e.message.includes('401')) { @@ -329,130 +325,10 @@ export class Valve { } else if (e.message.includes('422')) { this.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Unprocessable Entity`); this.log.debug( ->>>>>>> Stashed changes 'The client has made a valid request, but the server cannot process it.' + ' This is often used for APIs for which certain limits have been exceeded.', ); } else if (e.message.includes('429')) { -<<<<<<< Updated upstream - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Too Many Requests`); - this.debugLog('The client has exceeded the number of requests allowed for a given time window.'); - } else if (e.message.includes('500')) { - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Internal Server Error`); - this.debugLog('An unexpected error on the SmartThings servers has occurred. These errors should be rare.'); - } else { - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action},`); - } - if (this.deviceLogging.includes('debug')) { - this.platform.log.error(`Valve: ${this.accessory.displayName} failed to pushChanges, Error Message: ${superStringify(e.message)}`); - } - } - - async valveType(device: settings.device & settings.devicesConfig): Promise { - if (device.valve?.valveType === 1) { - this.valvetype = this.platform.Characteristic.ValveType.IRRIGATION; - } else if (device.valve?.valveType === 2){ - this.valvetype = this.platform.Characteristic.ValveType.SHOWER_HEAD; - } else if (device.valve?.valveType === 3) { - this.valvetype = this.platform.Characteristic.ValveType.WATER_FAUCET; - } else { - this.valvetype = this.platform.Characteristic.ValveType.GENERIC_VALVE; - } - } - - async config(device: settings.device & settings.devicesConfig): Promise { - let config = {}; - if (device.leaksensor) { - config = device.leaksensor; - } - if (device.logging !== undefined) { - config['logging'] = device.logging; - } - if (device.refreshRate !== undefined) { - config['refreshRate'] = device.refreshRate; - } - if (Object.entries(config).length !== 0) { - this.infoLog(`Valve: ${this.accessory.displayName} Config: ${superStringify(config)}`); - } - } - - async refreshRate(device: settings.device & settings.devicesConfig): Promise { - if (device.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate; - this.debugLog(`Valve: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`); - } else if (this.platform.config.options!.refreshRate) { - this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate; - this.debugLog(`Valve: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`); - } - } - - async logs(device: settings.device & settings.devicesConfig): Promise { - if (this.platform.debugMode) { - this.deviceLogging = this.accessory.context.logging = 'debugMode'; - this.debugLog(`Valve: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`); - } else if (device.logging) { - this.deviceLogging = this.accessory.context.logging = device.logging; - this.debugLog(`Valve: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`); - } else if (this.platform.config.options?.logging) { - this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging; - this.debugLog(`Valve: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`); - } else { - this.deviceLogging = this.accessory.context.logging = 'standard'; - this.debugLog(`Valve: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`); - } - } - - /** - * Logging for Device - */ - infoLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.info(String(...log)); - } - } - - warnLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.warn(String(...log)); - } - } - - debugWarnLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.warn('[DEBUG]', String(...log)); - } - } - } - - errorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - this.platform.log.error(String(...log)); - } - } - - debugErrorLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging?.includes('debug')) { - this.platform.log.error('[DEBUG]', String(...log)); - } - } - } - - debugLog(...log: any[]): void { - if (this.enablingDeviceLogging()) { - if (this.deviceLogging === 'debug') { - this.platform.log.info('[DEBUG]', String(...log)); - } else { - this.platform.log.debug(String(...log)); - } - } - } - - enablingDeviceLogging(): boolean { - return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard'; - } -======= this.log.error(`Valve: ${this.accessory.displayName} failed to ${this.action}, Too Many Requests`); this.log.debug('The client has exceeded the number of requests allowed for a given time window.'); } else if (e.message.includes('500')) { @@ -466,39 +342,30 @@ export class Valve { } } - async statusCode(statusCode: number): Promise { - /** - * Meater API Status Codes (https://github.com/apption-labs/meater-cloud-public-rest-api) - * - * Standard Response Codes: 200(OK), 201(Created), 204(No Content) - * https://github.com/apption-labs/meater-cloud-public-rest-api#standard-response - * - * Error Response: 400(Bad Request), 401(Unauthorized), 404(Not Found), 429(Too Many Requests), 500(Internal Server Error) - * https://github.com/apption-labs/meater-cloud-public-rest-api#error-response - **/ + async statusCode(statusCode: number, action: string): Promise { switch (statusCode) { case 200: - this.log.debug(`${this.accessory.displayName} Standard Response, statusCode: ${statusCode}`); + this.log.debug(`${this.device.deviceClass}: ${this.accessory.displayName} Standard Response, statusCode: ${statusCode}, Action: ${action}`); break; case 400: - this.log.error(`${this.accessory.displayName} Bad Request, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Bad Request, statusCode: ${statusCode}, Action: ${action}`); break; case 401: - this.log.error(`${this.accessory.displayName} Unauthorized, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Unauthorized, statusCode: ${statusCode}, Action: ${action}`); break; case 404: - this.log.error(`${this.accessory.displayName} Not Found, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Not Found, statusCode: ${statusCode}, Action: ${action}`); break; case 429: - this.log.error(`${this.accessory.displayName} Too Many Requests, statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Too Many Requests, statusCode: ${statusCode}, Action: ${action}`); break; case 500: - this.log.error(`${this.accessory.displayName} Internal Server Error (Meater Server), statusCode: ${statusCode}`); + this.log.error(`${this.device.deviceClass}: ${this.accessory.displayName} Internal Server Error (Meater Server), statusCode: ${statusCode}, ` + + `Action: ${action}`); break; default: - this.log.info( - `${this.accessory.displayName} Unknown statusCode: ${statusCode}, Report Bugs Here: https://bit.ly/homebridge-meater-bug-report`); + this.log.info(`${this.device.deviceClass}: ${this.accessory.displayName} Unknown statusCode: ${statusCode}, ` + + `Action: ${action}, Report Bugs Here: https://bit.ly/homebridge-resideo-bug-report`); } } ->>>>>>> Stashed changes } diff --git a/src/platform.ts b/src/platform.ts index d927034a..f4733bff 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -1,13 +1,8 @@ -<<<<<<< Updated upstream -import axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios'; -======= /* Copyright(C) 2017-2023, donavanbecker (https://github.com/donavanbecker). All rights reserved. * * protect-platform.ts: homebridge-cloudflared-tunnel platform class. */ -import { API, DynamicPlatformPlugin, Logging, PlatformAccessory } from 'homebridge'; import { - resideoDevice, AuthURL, DeviceURL, LocationURL, @@ -18,28 +13,18 @@ import { accessoryAttribute, devicesConfig, location, + resideoDevice, sensorAccessory, } from './settings.js'; import { request } from 'undici'; ->>>>>>> Stashed changes import { readFileSync, writeFileSync } from 'fs'; -import { API, Characteristic, DynamicPlatformPlugin, Logger, PlatformAccessory, Service } from 'homebridge'; +import { API, DynamicPlatformPlugin, Logging, PlatformAccessory, Characteristic, Service } from 'homebridge'; import { stringify } from 'querystring'; -<<<<<<< Updated upstream -import superStringify from 'super-stringify'; -import { LeakSensor } from './devices/leaksensors'; -import { Valve } from './devices/valve'; -import { RoomSensors } from './devices/roomsensors'; -import { RoomSensorThermostat } from './devices/roomsensorthermostats'; -import { Thermostats } from './devices/thermostats'; -import * as settings from './settings'; -======= -import { LeakSensor } from './devices/leaksensors.js'; import { Valve } from './devices/valve.js'; +import { LeakSensor } from './devices/leaksensors.js'; import { RoomSensors } from './devices/roomsensors.js'; -import { RoomSensorThermostat } from './devices/roomsensorthermostats.js'; import { Thermostats } from './devices/thermostats.js'; ->>>>>>> Stashed changes +import { RoomSensorThermostat } from './devices/roomsensorthermostats.js'; /** * HomebridgePlatform @@ -58,43 +43,35 @@ export class ResideoPlatform implements DynamicPlatformPlugin { });*/ locations?: any; - firmware!: settings.accessoryAttribute['softwareRevision']; - sensorAccessory!: settings.sensorAccessory; + firmware!: accessoryAttribute['softwareRevision']; + sensorAccessory!: sensorAccessory; version = process.env.npm_package_version || '1.3.0'; public sensorData = []; private refreshInterval!: NodeJS.Timeout; debugMode!: boolean; action!: string; platformLogging!: string; -<<<<<<< Updated upstream -======= - config!: ResideoPlatformConfig; ->>>>>>> Stashed changes - constructor(public readonly log: Logger, public readonly config: settings.ResideoPlatformConfig, public readonly api: API) { + constructor( + public readonly log: Logging, + public readonly config: ResideoPlatformConfig, + public readonly api: API, + ) { this.logs(); - this.debugLog(`Finished initializing platform: ${this.config.name}`); + this.log.debug(`Finished initializing platform: ${this.config.name}`); // only load if configured if (!this.config) { return; } -<<<<<<< Updated upstream - // HOOBS notice - if (__dirname.includes('hoobs')) { - this.warnLog('This plugin has not been tested under HOOBS, it is highly recommended that ' + 'you switch to Homebridge: https://git.io/Jtxb0'); - } -======= // Plugin options into our config variables. this.config = { platform: 'ResideoPlatform', credentials: config.credentials, options: config.options, }; - this.logs(); this.log.debug(`Finished initializing platform: ${config.name}`); ->>>>>>> Stashed changes // verify the config try { @@ -123,17 +100,26 @@ export class ResideoPlatform implements DynamicPlatformPlugin { this.log.debug('Executed didFinishLaunching callback'); // run the method to discover / register your devices as accessories await this.refreshAccessToken(); - try { - this.locations = await this.discoverlocations(); - } catch (e: any) { - this.action = 'Discober Locations'; - this.apiError(e); - } - try { - this.discoverDevices(); - } catch (e: any) { - this.action = 'Discober Device'; - this.apiError(e); + if (this.config.credentials?.accessToken) { + this.log.debug(`accessToken: ${this.config.credentials?.accessToken}`); + try { + this.locations = await this.discoverlocations(); + } catch (e: any) { + this.action = 'Discover Locations'; + this.apiError(e); + } + if (this.locations !== undefined) { + try { + this.discoverDevices(); + } catch (e: any) { + this.action = 'Discover Device'; + this.apiError(e); + } + } else { + this.log.error('Failed to Discover Locations. Re-Link Your Resideo Account.'); + } + } else { + this.log.error('Missing Access Token. Re-Link Your Resideo Account.'); } }); } @@ -174,6 +160,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { */ verifyConfig() { this.config.options = this.config.options || {}; + this.config.credentials = this.config.credentials || {}; const platformConfig = {}; if (this.config.options.logging) { @@ -251,45 +238,37 @@ export class ResideoPlatform implements DynamicPlatformPlugin { */ async getAccessToken() { try { - let result: any; - - if (this.config.credentials!.consumerSecret) { - result = ( -<<<<<<< Updated upstream - await axios({ - url: settings.AuthURL, -======= - await /*axios*/({ - url: AuthURL, ->>>>>>> Stashed changes - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - auth: { - username: this.config.credentials!.consumerKey, - password: this.config.credentials!.consumerSecret, - }, - data: stringify({ - grant_type: 'refresh_token', - refresh_token: this.config.credentials!.refreshToken, - }), - responseType: 'json', - }) - ).data; + if (this.config.credentials!.consumerSecret && this.config.credentials!.consumerKey && this.config.credentials!.refreshToken) { + this.log.debug(`consumerKey: ${this.config.credentials!.consumerKey},` + ` consumerSecret: ${this.config.credentials!.consumerSecret},` + + ` refreshToken: ${this.config.credentials!.refreshToken}` + ` accessToken: ${this.config.credentials!.accessToken}`); + const { body, statusCode } = await request(AuthURL, { + method: 'POST', + headers: { + Authorization: + `Basic ${Buffer.from(`${this.config.credentials!.consumerKey}:${this.config.credentials!.consumerSecret}`).toString('base64')}`, + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: stringify({ + grant_type: 'refresh_token', + refresh_token: this.config.credentials!.refreshToken, + }), + }); + const action = 'getAccessToken'; + this.statusCode(statusCode, action); + this.log.debug(`(getAccessToken) body: ${JSON.stringify(body)}`); + const result: any = await body.json(); + this.log.debug(`(getAccessToken) Result: ${JSON.stringify(result)}`); + this.config.credentials!.accessToken = result.access_token; + this.log.debug(`Got access token: ${this.config.credentials!.accessToken}`); + // check if the refresh token has changed + if (result.refresh_token !== this.config.credentials!.refreshToken) { + this.log.debug(`New refresh token: ${result.refresh_token}`); + await this.updateRefreshToken(result.refresh_token); + } + this.config.credentials!.refreshToken = result.refresh_token; } else { this.log.warn('Please re-link your account in the Homebridge UI.'); } - - this.config.credentials!.accessToken = result.access_token; - this.log.debug(`Got access token: ${this.config.credentials!.accessToken}`); - // check if the refresh token has changed - if (result.refresh_token !== this.config.credentials!.refreshToken) { - this.log.debug(`New refresh token: ${result.refresh_token}`); - await this.updateRefreshToken(result.refresh_token); - } - - this.config.credentials!.refreshToken = result.refresh_token; } catch (e: any) { this.action = 'refresh access token'; this.apiError(e); @@ -317,10 +296,10 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } // find this plugins current config - const pluginConfig = currentConfig.platforms.find((x: { platform: string }) => x.platform === settings.PLATFORM_NAME); + const pluginConfig = currentConfig.platforms.find((x: { platform: string }) => x.platform === PLATFORM_NAME); if (!pluginConfig) { - throw new Error(`Cannot find config for ${settings.PLATFORM_NAME} in platforms array`); + throw new Error(`Cannot find config for ${PLATFORM_NAME} in platforms array`); } // check the .credentials is an object before doing object things with it @@ -344,23 +323,24 @@ export class ResideoPlatform implements DynamicPlatformPlugin { * this method discovers the Locations */ async discoverlocations() { -<<<<<<< Updated upstream - const locations = (await this.axios.get(settings.LocationURL)).data; -======= - const { body, statusCode, headers } = await request(LocationURL, { + this.log.debug(`accessToken: ${this.config.credentials?.accessToken}, consumerKey: ${this.config.credentials?.consumerKey}`); + const { body, statusCode } = await request(LocationURL, { method: 'GET', - headers: { 'content-type': 'application/json' }, + query: { + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', + }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); - const login: any = await body.json(); - this.log.debug(`Location: ${JSON.stringify(login)}`); - this.log.debug(`Location Data: ${JSON.stringify(login.data)}`); - this.log.debug(`Location StatusCode: ${login.statusCode}`); - const locations = login.data.locations; + const action = 'discoverlocations'; + this.statusCode(statusCode, action); + this.log.debug(`(discoverlocations) body: ${JSON.stringify(body)}`); + const locations: any = await body.json(); + this.log.debug(`(discoverlocations) Location: ${JSON.stringify(locations)}`); + this.statusCode(locations.statusCode, action); //const locations = (await this.axios.get(LocationURL)).data; ->>>>>>> Stashed changes return locations; } @@ -368,38 +348,37 @@ export class ResideoPlatform implements DynamicPlatformPlugin { * this method discovers the rooms at each location */ public async getCurrentSensorData( - device: settings.device & settings.devicesConfig, - group: settings.T9groups, - locationId: settings.location['locationID'], + device: resideoDevice & devicesConfig, + group: T9groups, + locationId: location['locationID'], ) { if (!this.sensorData[device.deviceID] || this.sensorData[device.deviceID].timestamp < Date.now()) { -<<<<<<< Updated upstream - const response: any = await this.axios.get(`${settings.DeviceURL}/thermostats/${device.deviceID}/group/${group.id}/rooms`, { -======= - const { body, statusCode, headers } = await request(`${DeviceURL}/thermostats/${device.deviceID}/group/${group.id}/rooms`, { + const { body, statusCode } = await request(`${DeviceURL}/thermostats/${device.deviceID}/group/${group.id}/rooms`, { + method: 'GET', query: { - locationId: locationId, + 'locationId': locationId, + 'apikey': this.config.credentials?.consumerKey, + }, + headers: { + 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, + 'Content-Type': 'application/json', }, - method: 'GET', - headers: { 'content-type': 'application/json' }, }); - this.log.debug(`body: ${JSON.stringify(body)}`); - this.log.debug(`statusCode: ${statusCode}`); - this.log.debug(`headers: ${JSON.stringify(headers)}`); + const action = 'getCurrentSensorData'; + this.statusCode(statusCode, action); const response: any = await body.json(); - this.log.debug(`Response: ${JSON.stringify(response)}`); - this.log.debug(`Response StatusCode: ${response.statusCode}`); - + this.log.debug(`(getCurrentSensorData) Response: ${JSON.stringify(response)}`); /*const response: any = await this.axios.get(`${DeviceURL}/thermostats/${device.deviceID}/group/${group.id}/rooms`, { ->>>>>>> Stashed changes params: { locationId: locationId, }, });*/ + this.sensorData[device.deviceID] = { timestamp: Date.now() + 45000, - data: this.normalizeSensorDate(response.data), + data: this.normalizeSensorDate(response), }; + this.log.debug(`getCurrentSensorData ${device.deviceType} ${device.deviceModel}: ${this.sensorData[device.deviceID]}`); } else { this.log.debug(`getCurrentSensorData Cache ${device.deviceType} ${device.deviceModel} - ${device.userDefinedDeviceName}`); } @@ -421,7 +400,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { /** * this method discovers the firmware Veriosn for T9 Thermostats */ - public async getSoftwareRevision(locationId: settings.location['locationID'], device: settings.device & settings.devicesConfig) { + public async getSoftwareRevision(locationId: location['locationID'], device: resideoDevice & devicesConfig) { if (device.deviceModel.startsWith('T9') && device.groups) { for (const group of device.groups) { const roomsensors = await this.getCurrentSensorData(device, group, locationId); @@ -506,7 +485,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private async deviceClass(device: settings.device & settings.devicesConfig, location: any, locationId: any) { + private async deviceClass(device: resideoDevice & devicesConfig, location: any, locationId: any) { switch (device.deviceClass) { case 'ShutoffValve': this.log.debug(`Discovered ${device.userDefinedDeviceName} ${device.deviceClass} @ ${location.name}`); @@ -521,6 +500,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { await this.createThermostat(location, device, locationId); if (device.deviceModel!.startsWith('T9')) { try { + this.log.debug(`Discovering Room Sensor(s) for ${device.userDefinedDeviceName} ${device.deviceClass} (${device.deviceModel})`); await this.discoverRoomSensors(location.locationID, device); } catch (e: any) { this.action = 'Find Room Sensor(s)'; @@ -534,10 +514,11 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private async discoverRoomSensors(locationId: settings.location['locationID'], device: settings.device & settings.devicesConfig) { + private async discoverRoomSensors(locationId: location['locationID'], device: resideoDevice & devicesConfig) { // get the devices at each location this.roomsensordisplaymethod(device); if (device.groups) { + this.log.debug(`Discovered ${device.groups.length} Group(s) for ${device.userDefinedDeviceName} ${device.deviceClass} (${device.deviceModel})`); for (const group of device.groups) { const roomsensors = await this.getCurrentSensorData(device, group, locationId); for (const accessories of roomsensors) { @@ -549,7 +530,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { if (sensorAccessory.accessoryAttribute.type.startsWith('IndoorAirSensor')) { this.log.debug( `Discovered Room Sensor groupId: ${sensorAccessory.roomId},` + - ` roomId: ${sensorAccessory.accessoryId}, accessoryId: ${sensorAccessory.accessoryAttribute.name}`, + ` roomId: ${sensorAccessory.accessoryId}, accessoryId: ${sensorAccessory.accessoryAttribute.name}`, ); if (sensorAccessory.accessoryAttribute.model === '0') { sensorAccessory.accessoryAttribute.model = '4352'; @@ -567,7 +548,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private roomsensordisplaymethod(device: settings.device & settings.devicesConfig) { + private roomsensordisplaymethod(device: resideoDevice & devicesConfig) { if (device.thermostat?.roompriority) { /** * Room Priority @@ -583,9 +564,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } private async createThermostat( - location: settings.location, - device: settings.device & settings.devicesConfig, - locationId: settings.location['locationID'], + location: location, + device: resideoDevice & devicesConfig, + locationId: location['locationID'], ) { const uuid = this.api.hap.uuid.generate(`${device.deviceID}-${device.deviceClass}`); @@ -642,7 +623,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private Leak(device: settings.device & settings.devicesConfig, locationId: settings.location['locationID']) { + private Leak(device: resideoDevice & devicesConfig, locationId: location['locationID']) { const uuid = this.api.hap.uuid.generate(`${device.deviceID}-${device.deviceClass}`); // see if an accessory with the same uuid has already been registered and restored from @@ -701,7 +682,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private Valve(device: settings.device & settings.devicesConfig, locationId: settings.location['locationID']) { + private Valve(device: resideoDevice & devicesConfig, locationId: location['locationID']) { const uuid = this.api.hap.uuid.generate(`${device.deviceID}-${device.deviceClass}`); // see if an accessory with the same uuid has already been registered and restored from @@ -761,10 +742,10 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } private createRoomSensors( - device: settings.device & settings.devicesConfig, - locationId: settings.location['locationID'], - sensorAccessory: settings.sensorAccessory, - group: settings.T9groups, + device: resideoDevice & devicesConfig, + locationId: location['locationID'], + sensorAccessory: sensorAccessory, + group: T9groups, ) { // Room Sensor(s) const uuid = this.api.hap.uuid.generate(`${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-RoomSensor`); @@ -787,7 +768,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { new RoomSensors(this, existingAccessory, locationId, device, sensorAccessory, group); this.log.debug( `${sensorAccessory.accessoryAttribute.type}` + - ` uuid: ${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-RoomSensor, (${existingAccessory.UUID})`, + ` uuid: ${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-RoomSensor, (${existingAccessory.UUID})`, ); } else { this.unregisterPlatformAccessories(existingAccessory); @@ -813,7 +794,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { new RoomSensors(this, accessory, locationId, device, sensorAccessory, group); this.log.debug( `${sensorAccessory.accessoryAttribute.type}` + - ` uuid: ${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-RoomSensor, (${accessory.UUID})`, + ` uuid: ${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-RoomSensor, (${accessory.UUID})`, ); // publish device externally or link the accessory to your platform @@ -823,7 +804,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { if (this.platformLogging?.includes('debug')) { this.log.error( `Unable to Register new device: ${sensorAccessory.accessoryAttribute.name} ${sensorAccessory.accessoryAttribute.type} ` + - `DeviceID: ${sensorAccessory.deviceID}`, + `DeviceID: ${sensorAccessory.deviceID}`, ); this.log.error('Check Config to see if DeviceID is being Hidden.'); } @@ -831,10 +812,10 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } private createRoomSensorThermostat( - device: settings.device & settings.devicesConfig, - locationId: settings.location['locationID'], - sensorAccessory: settings.sensorAccessory, - group: settings.T9groups, + device: resideoDevice & devicesConfig, + locationId: location['locationID'], + sensorAccessory: sensorAccessory, + group: T9groups, ) { const uuid = this.api.hap.uuid.generate(`${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-RoomSensorThermostat`); @@ -859,7 +840,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { new RoomSensorThermostat(this, existingAccessory, locationId, device, sensorAccessory, group); this.log.debug( `${sensorAccessory.accessoryAttribute.type} Thermostat uuid:` + - ` ${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-RoomSensorThermostat, (${existingAccessory.UUID})`, + ` ${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-RoomSensorThermostat, (${existingAccessory.UUID})`, ); } else { this.unregisterPlatformAccessories(existingAccessory); @@ -885,8 +866,8 @@ export class ResideoPlatform implements DynamicPlatformPlugin { new RoomSensorThermostat(this, accessory, locationId, device, sensorAccessory, group); this.log.debug( `${sensorAccessory.accessoryAttribute.type} Thermostat uuid:` + - ` ${sensorAccessory.accessoryAttribute.name}-${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-` + - `RoomSensorThermostat, (${accessory.UUID})`, + ` ${sensorAccessory.accessoryAttribute.name}-${sensorAccessory.accessoryAttribute.type}-${sensorAccessory.accessoryId}-` + + `RoomSensorThermostat, (${accessory.UUID})`, ); // publish device externally or link the accessory to your platform @@ -896,14 +877,14 @@ export class ResideoPlatform implements DynamicPlatformPlugin { if (this.platformLogging?.includes('debug')) { this.log.error( `Unable to Register new device: ${sensorAccessory.accessoryAttribute.name} ${sensorAccessory.accessoryAttribute.type} ` + - `DeviceID: ${sensorAccessory.deviceID}`, + `DeviceID: ${sensorAccessory.deviceID}`, ); this.log.error('Check Config to see if DeviceID is being Hidden.'); } } } - private leaksensorFirmwareNewAccessory(device: settings.device & settings.devicesConfig, accessory: PlatformAccessory) { + private leaksensorFirmwareNewAccessory(device: resideoDevice & devicesConfig, accessory: PlatformAccessory) { if (device.firmware) { accessory.context.firmwareRevision = device.firmware; } else { @@ -911,7 +892,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private leaksensorFirmwareExistingAccessory(device: settings.device & settings.devicesConfig, existingAccessory: PlatformAccessory) { + private leaksensorFirmwareExistingAccessory(device: resideoDevice & devicesConfig, existingAccessory: PlatformAccessory) { if (device.firmware) { existingAccessory.context.firmwareRevision = device.firmware; } else { @@ -919,7 +900,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private valveFirmwareNewAccessory(device: settings.device & settings.devicesConfig, accessory: PlatformAccessory) { + private valveFirmwareNewAccessory(device: resideoDevice & devicesConfig, accessory: PlatformAccessory) { if (device.firmware) { accessory.context.firmwareRevision = device.firmware; } else { @@ -927,7 +908,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private valveFirmwareExistingAccessory(device: settings.device & settings.devicesConfig, existingAccessory: PlatformAccessory) { + private valveFirmwareExistingAccessory(device: resideoDevice & devicesConfig, existingAccessory: PlatformAccessory) { if (device.firmware) { existingAccessory.context.firmwareRevision = device.firmware; } else { @@ -935,7 +916,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private roomsensorFirmwareNewAccessory(accessory, sensorAccessory: settings.sensorAccessory) { + private roomsensorFirmwareNewAccessory(accessory, sensorAccessory: sensorAccessory) { if (accessory.firmware) { accessory.context.firmwareRevision = accessory.firmware; } else { @@ -943,7 +924,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - private roomsensorFirmwareExistingAccessory(existingAccessory, sensorAccessory: settings.sensorAccessory) { + private roomsensorFirmwareExistingAccessory(existingAccessory, sensorAccessory: sensorAccessory) { if (existingAccessory.firmware) { existingAccessory.context.firmwareRevision = existingAccessory.firmware; } else { @@ -951,7 +932,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - public async thermostatFirmwareNewAccessory(device: settings.device & settings.devicesConfig, accessory: PlatformAccessory, location: any) { + public async thermostatFirmwareNewAccessory(device: resideoDevice & devicesConfig, accessory: PlatformAccessory, location: any) { if (device.firmware) { accessory.context.firmwareRevision = device.firmware; } else { @@ -971,7 +952,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } public async thermostatFirmwareExistingAccessory( - device: settings.device & settings.devicesConfig, + device: resideoDevice & devicesConfig, existingAccessory: PlatformAccessory, location: any, ) { @@ -993,110 +974,24 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - public async externalOrPlatform(device: settings.device & settings.devicesConfig, accessory: PlatformAccessory) { + public async externalOrPlatform(device: resideoDevice & devicesConfig, accessory: PlatformAccessory) { if (device.external) { this.log.warn(`${accessory.displayName} External Accessory Mode`); this.externalAccessory(accessory); } else { -<<<<<<< Updated upstream - this.debugLog(`${accessory.displayName} External Accessory Mode: ${device.external}`); - this.api.registerPlatformAccessories(settings.PLUGIN_NAME, settings.PLATFORM_NAME, [accessory]); -======= this.log.debug(`${accessory.displayName} External Accessory Mode: ${device.external}`); this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); ->>>>>>> Stashed changes } } public async externalAccessory(accessory: PlatformAccessory) { - this.api.publishExternalAccessories(settings.PLUGIN_NAME, [accessory]); + this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]); } public unregisterPlatformAccessories(existingAccessory: PlatformAccessory) { // remove platform accessories when no longer present -<<<<<<< Updated upstream - this.api.unregisterPlatformAccessories(settings.PLUGIN_NAME, settings.PLATFORM_NAME, [existingAccessory]); - this.warnLog(`Removing existing accessory from cache: ${existingAccessory.displayName}`); - } - - public locationinfo(location: settings.location) { - if (this.platformLogging?.includes('debug')) { - if (location) { - this.warnLog(superStringify(location)); - } - } - } - - public deviceinfo(device: { - deviceID: string; - deviceType: string; - deviceClass: string; - deviceModel: string; - priorityType: string; - settings: settings.Settings; - inBuiltSensorState: settings.inBuiltSensorState; - groups: settings.device['groups'] & settings.devicesConfig; - }) { - if (this.platformLogging?.includes('debug')) { - this.warnLog(superStringify(device)); - if (device.deviceID) { - this.warnLog(superStringify(device.deviceID)); - this.errorLog(`Device ID: ${device.deviceID}`); - } - if (device.deviceType) { - this.warnLog(superStringify(device.deviceType)); - this.errorLog(`Device Type: ${device.deviceType}`); - } - if (device.deviceClass) { - this.warnLog(superStringify(device.deviceClass)); - this.errorLog(`Device Class: ${device.deviceClass}`); - } - if (device.deviceModel) { - this.warnLog(superStringify(device.deviceModel)); - this.errorLog(`Device Model: ${device.deviceModel}`); - } - if (device.priorityType) { - this.warnLog(superStringify(device.priorityType)); - this.errorLog(`Device Priority Type: ${device.priorityType}`); - } - if (device.settings) { - this.warnLog(superStringify(device.settings)); - if (device.settings.fan) { - this.warnLog(superStringify(device.settings.fan)); - this.errorLog(`Device Fan Settings: ${superStringify(device.settings.fan)}`); - if (device.settings.fan.allowedModes) { - this.warnLog(superStringify(device.settings.fan.allowedModes)); - this.errorLog(`Device Fan Allowed Modes: ${device.settings.fan.allowedModes}`); - } - if (device.settings.fan.changeableValues) { - this.warnLog(superStringify(device.settings.fan.changeableValues)); - this.errorLog(`Device Fan Changeable Values: ${superStringify(device.settings.fan.changeableValues)}`); - } - } - } - if (device.inBuiltSensorState) { - this.warnLog(superStringify(device.inBuiltSensorState)); - if (device.inBuiltSensorState.roomId) { - this.warnLog(superStringify(device.inBuiltSensorState.roomId)); - this.errorLog(`Device Built In Sensor Room ID: ${device.inBuiltSensorState.roomId}`); - } - if (device.inBuiltSensorState.roomName) { - this.warnLog(superStringify(device.inBuiltSensorState.roomName)); - this.errorLog(`Device Built In Sensor Room Name: ${device.inBuiltSensorState.roomName}`); - } - } - if (device.groups) { - this.warnLog(superStringify(device.groups)); - - for (const group of device.groups) { - this.errorLog(`Group: ${group.id}`); - } - } - } -======= this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]); this.log.warn(`Removing existing accessory from cache: ${existingAccessory.displayName}`); ->>>>>>> Stashed changes } apiError(e: any) { @@ -1122,7 +1017,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { this.log.error(`Failed to ${this.action}: Unprocessable Entity`); this.log.debug( 'The client has made a valid request, but the server cannot process it.' + - ' This is often used for APIs for which certain limits have been exceeded.', + ' This is often used for APIs for which certain limits have been exceeded.', ); } else if (e.message.includes('429')) { this.log.error(`Failed to ${this.action}: Too Many Requests`); @@ -1138,28 +1033,28 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - async statusCode(statusCode: number): Promise { + async statusCode(statusCode: number, action: string): Promise { switch (statusCode) { case 200: - this.log.debug(`Standard Response, statusCode: ${statusCode}`); + this.log.debug(`Standard Response, statusCode: ${statusCode}, Action: ${action}`); break; case 400: - this.log.error(`Bad Request, statusCode: ${statusCode}`); + this.log.error(`Bad Request, statusCode: ${statusCode}, Action: ${action}`); break; case 401: - this.log.error(`Unauthorized, statusCode: ${statusCode}`); + this.log.error(`Unauthorized, statusCode: ${statusCode}, Action: ${action}`); break; case 404: - this.log.error(`Not Found, statusCode: ${statusCode}`); + this.log.error(`Not Found, statusCode: ${statusCode}, Action: ${action}`); break; case 429: - this.log.error(`Too Many Requests, statusCode: ${statusCode}`); + this.log.error(`Too Many Requests, statusCode: ${statusCode}, Action: ${action}`); break; case 500: - this.log.error(`Internal Server Error (Meater Server), statusCode: ${statusCode}`); + this.log.error(`Internal Server Error (Meater Server), statusCode: ${statusCode}, Action: ${action}`); break; default: - this.log.info(`Unknown statusCode: ${statusCode}, Report Bugs Here: https://bit.ly/homebridge-meater-bug-report`); + this.log.info(`Unknown statusCode: ${statusCode}, Report Bugs Here: https://bit.ly/homebridge-resideo-bug-report. Action: ${action}`); } } } diff --git a/src/settings.ts b/src/settings.ts index 010f486d..e289b84e 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -37,10 +37,10 @@ export interface ResideoPlatformConfig extends PlatformConfig { } export type credentials = { - accessToken?: any; - consumerKey?: any; - consumerSecret?: any; - refreshToken?: any; + accessToken?: string; + consumerKey?: string; + consumerSecret?: string; + refreshToken?: string; }; export type options = { @@ -123,6 +123,7 @@ export type payload = { autoChangeoverActive?: boolean; thermostatSetpoint?: number; unit?: string; + state?: string; }; // Location @@ -183,6 +184,12 @@ export type resideoDevice = { isRegistered: boolean; hasDeviceCheckedIn: boolean; isDeviceOffline: boolean; + deviceMac: string //Device MAC address + dataSyncInfo: dataSyncInfo; + lastCheckin: Date; //Last time data received from device + actuatorValve: actuatorValve; //Values specific to the valve operation + daylightSavingsInfo: daylightSavingsInfo //Daylight savings time config info + maintenance: maintenance //Maintenance settings }; export type T9groups = { @@ -406,7 +413,32 @@ export type Accessory = { detectMotion: boolean; }; -export interface AxiosRequestConfig { - params?: Record; - headers?: any; +export type dataSyncInfo = { + state: string; //'NotStarted' | 'Initiated' | 'Completed' | 'Failed' + transactionId: string; //Internal reference ID for the DataSync operation +} + +export type actuatorValve = { + commandSource: string;//'app' | 'wldFreeze' | 'wldLeak' | 'manual' | 'buildInLeak' | 'maintenance'; + runningTime: number; //Operation time + valveStatus: string //'unknown' | 'open' | 'close' | 'notOpen' | 'notClose' | 'opening' | 'closing' | 'antiScaleOpening' | 'antiScaleClosing'; + motorCycles: number; //Count of motor operations + motorCurrentAverage: number; + motorCurrentMax: number; + deviceTemperature: number; //Current temperature of device in Fahrenheit units + lastAntiScaleTime: Date; //Last time of anti - scale operation + leakStatus: string; //'ok' | 'leak' | 'na' | 'err' + timeValveChanged: Date; //Time of last valve change +} + +export type daylightSavingsInfo = { + isDaylightSaving: boolean //If device is currently using DST or not + nextOffsetChange: Date //Next scheduled DST changeover +} + +export type maintenance = { + antiScaleSettings: string; //Current anti - scale cycle: 'OncePerWeek' | 'OncePerTwoWeeks' | 'OncePerMonth' | 'OncePerTwoMonths' | 'Disabled' + antiScaleDOWSettings: string; //'Sunday' | 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday' + antiScaleDOMSettings: number; //If monthly anti - scale is used, day of the month. + antiScaleTimeSettings: string; //Time for anti - scale in 24 hrs format }