mirror of
https://github.com/koush/scrypted.git
synced 2026-02-03 22:23:27 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea628a7130 |
355
plugins/unifi-protect/package-lock.json
generated
355
plugins/unifi-protect/package-lock.json
generated
@@ -9,15 +9,18 @@
|
||||
"version": "0.0.164",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"@koush/unifi-protect": "file:../../external/unifi-protect",
|
||||
"@scrypted/common": "file:../../common",
|
||||
"@scrypted/sdk": "file:../../sdk",
|
||||
"axios": "^1.4.0",
|
||||
"ws": "^8.13.0"
|
||||
"axios": "^1.7.8",
|
||||
"unifi-protect": "^4.16.0",
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.4.2",
|
||||
"@types/ws": "^8.5.5"
|
||||
"@types/node": "^22.9.4",
|
||||
"@types/ws": "^8.5.13"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@adobe/fetch": "^4.1.9"
|
||||
}
|
||||
},
|
||||
"../../common": {
|
||||
@@ -26,58 +29,33 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@scrypted/sdk": "file:../sdk",
|
||||
"@scrypted/server": "file:../server",
|
||||
"http-auth-utils": "^5.0.1",
|
||||
"typescript": "^5.3.3"
|
||||
"typescript": "^5.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"monaco-editor": "^0.50.0",
|
||||
"ts-node": "^10.9.2"
|
||||
}
|
||||
},
|
||||
"../../external/unifi-protect": {
|
||||
"name": "@koush/unifi-protect",
|
||||
"version": "3.0.4",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"abort-controller": "^3.0.0",
|
||||
"domexception": "^4.0.0",
|
||||
"node-fetch": "^3.3.0",
|
||||
"util": "^0.12.4",
|
||||
"ws": "^8.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^17.0.18",
|
||||
"@types/ws": "^8.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.0",
|
||||
"@typescript-eslint/parser": "^5.12.0",
|
||||
"eslint": "^8.9.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"../../sdk": {
|
||||
"name": "@scrypted/sdk",
|
||||
"version": "0.3.31",
|
||||
"version": "0.3.88",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"adm-zip": "^0.4.13",
|
||||
"axios": "^1.6.5",
|
||||
"babel-loader": "^9.1.0",
|
||||
"babel-plugin-const-enum": "^1.1.0",
|
||||
"esbuild": "^0.15.9",
|
||||
"@babel/preset-typescript": "^7.26.0",
|
||||
"adm-zip": "^0.5.16",
|
||||
"axios": "^1.7.7",
|
||||
"babel-loader": "^9.2.1",
|
||||
"babel-plugin-const-enum": "^1.2.0",
|
||||
"ncp": "^2.0.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"tmp": "^0.2.1",
|
||||
"ts-loader": "^9.4.2",
|
||||
"typescript": "^4.9.4",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-bundle-analyzer": "^4.5.0"
|
||||
"rimraf": "^6.0.1",
|
||||
"tmp": "^0.2.3",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.5.4",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack-bundle-analyzer": "^4.10.2"
|
||||
},
|
||||
"bin": {
|
||||
"scrypted-changelog": "bin/scrypted-changelog.js",
|
||||
@@ -89,19 +67,28 @@
|
||||
"scrypted-webpack": "bin/scrypted-webpack.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/stringify-object": "^4.0.0",
|
||||
"@types/node": "^22.8.1",
|
||||
"@types/stringify-object": "^4.0.5",
|
||||
"stringify-object": "^3.3.0",
|
||||
"ts-node": "^10.4.0",
|
||||
"typedoc": "^0.23.21"
|
||||
"ts-node": "^10.9.2",
|
||||
"typedoc": "^0.26.10"
|
||||
}
|
||||
},
|
||||
"../sdk": {
|
||||
"extraneous": true
|
||||
},
|
||||
"node_modules/@koush/unifi-protect": {
|
||||
"resolved": "../../external/unifi-protect",
|
||||
"link": true
|
||||
"node_modules/@adobe/fetch": {
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@adobe/fetch/-/fetch-4.1.9.tgz",
|
||||
"integrity": "sha512-FWIzm4vvl1OtCarTBgWDW6otj4gxrNmMf/DdriqBUw7DjjmckjT3ZQA43b4HzBkzkuAHhajwMy91btp9fWgTEw==",
|
||||
"dependencies": {
|
||||
"debug": "4.3.7",
|
||||
"http-cache-semantics": "4.1.1",
|
||||
"lru-cache": "7.18.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
}
|
||||
},
|
||||
"node_modules/@scrypted/common": {
|
||||
"resolved": "../../common",
|
||||
@@ -112,15 +99,18 @@
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz",
|
||||
"integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==",
|
||||
"dev": true
|
||||
"version": "22.9.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.4.tgz",
|
||||
"integrity": "sha512-d9RWfoR7JC/87vj7n+PVTzGg9hDyuFjir3RxUHbjFSKNd9mpxbxwMEyaCim/ddCmy4IuW7HjTzF3g9p3EtWEOg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz",
|
||||
"integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==",
|
||||
"version": "8.5.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
|
||||
"integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
@@ -132,15 +122,28 @@
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||
"version": "1.7.8",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz",
|
||||
"integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bufferutil": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz",
|
||||
"integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
@@ -152,6 +155,22 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
@@ -161,9 +180,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -192,6 +211,19 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
|
||||
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "7.18.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
@@ -211,15 +243,55 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.8.4",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/unifi-protect": {
|
||||
"version": "4.16.0",
|
||||
"resolved": "https://registry.npmjs.org/unifi-protect/-/unifi-protect-4.16.0.tgz",
|
||||
"integrity": "sha512-M8/VUTKhPxlzagIQdpjvXbdUPp4a/3F051CghaLXWT9JfnVuJZGLYC3U1zYOXtKVIfqP+KcTmn6sSTawHTGADQ==",
|
||||
"dependencies": {
|
||||
"@adobe/fetch": "4.1.9",
|
||||
"ws": "8.18.0"
|
||||
},
|
||||
"bin": {
|
||||
"ufp": "dist/util/ufp.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bufferutil": "4.0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
||||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
@@ -238,68 +310,63 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@koush/unifi-protect": {
|
||||
"version": "file:../../external/unifi-protect",
|
||||
"@adobe/fetch": {
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@adobe/fetch/-/fetch-4.1.9.tgz",
|
||||
"integrity": "sha512-FWIzm4vvl1OtCarTBgWDW6otj4gxrNmMf/DdriqBUw7DjjmckjT3ZQA43b4HzBkzkuAHhajwMy91btp9fWgTEw==",
|
||||
"requires": {
|
||||
"@types/node": "^17.0.18",
|
||||
"@types/ws": "^8.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.0",
|
||||
"@typescript-eslint/parser": "^5.12.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"domexception": "^4.0.0",
|
||||
"eslint": "^8.9.0",
|
||||
"node-fetch": "^3.3.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^4.5.5",
|
||||
"util": "^0.12.4",
|
||||
"ws": "^8.5.0"
|
||||
"debug": "4.3.7",
|
||||
"http-cache-semantics": "4.1.1",
|
||||
"lru-cache": "7.18.3"
|
||||
}
|
||||
},
|
||||
"@scrypted/common": {
|
||||
"version": "file:../../common",
|
||||
"requires": {
|
||||
"@scrypted/sdk": "file:../sdk",
|
||||
"@scrypted/server": "file:../server",
|
||||
"@types/node": "^20.11.0",
|
||||
"http-auth-utils": "^5.0.1",
|
||||
"monaco-editor": "^0.50.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3"
|
||||
"typescript": "^5.5.3"
|
||||
}
|
||||
},
|
||||
"@scrypted/sdk": {
|
||||
"version": "file:../../sdk",
|
||||
"requires": {
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/stringify-object": "^4.0.0",
|
||||
"adm-zip": "^0.4.13",
|
||||
"axios": "^1.6.5",
|
||||
"babel-loader": "^9.1.0",
|
||||
"babel-plugin-const-enum": "^1.1.0",
|
||||
"esbuild": "^0.15.9",
|
||||
"@babel/preset-typescript": "^7.26.0",
|
||||
"@types/node": "^22.8.1",
|
||||
"@types/stringify-object": "^4.0.5",
|
||||
"adm-zip": "^0.5.16",
|
||||
"axios": "^1.7.7",
|
||||
"babel-loader": "^9.2.1",
|
||||
"babel-plugin-const-enum": "^1.2.0",
|
||||
"ncp": "^2.0.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"rimraf": "^6.0.1",
|
||||
"stringify-object": "^3.3.0",
|
||||
"tmp": "^0.2.1",
|
||||
"ts-loader": "^9.4.2",
|
||||
"ts-node": "^10.4.0",
|
||||
"typedoc": "^0.23.21",
|
||||
"typescript": "^4.9.4",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-bundle-analyzer": "^4.5.0"
|
||||
"tmp": "^0.2.3",
|
||||
"ts-loader": "^9.5.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typedoc": "^0.26.10",
|
||||
"typescript": "^5.5.4",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack-bundle-analyzer": "^4.10.2"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "20.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz",
|
||||
"integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==",
|
||||
"dev": true
|
||||
"version": "22.9.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.4.tgz",
|
||||
"integrity": "sha512-d9RWfoR7JC/87vj7n+PVTzGg9hDyuFjir3RxUHbjFSKNd9mpxbxwMEyaCim/ddCmy4IuW7HjTzF3g9p3EtWEOg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"undici-types": "~6.19.8"
|
||||
}
|
||||
},
|
||||
"@types/ws": {
|
||||
"version": "8.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz",
|
||||
"integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==",
|
||||
"version": "8.5.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
|
||||
"integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
@@ -311,15 +378,24 @@
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||
"version": "1.7.8",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz",
|
||||
"integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"bufferutil": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz",
|
||||
"integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
@@ -328,15 +404,23 @@
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"requires": {
|
||||
"ms": "^2.1.3"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
@@ -348,6 +432,16 @@
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"http-cache-semantics": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
|
||||
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "7.18.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
@@ -361,15 +455,42 @@
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node-gyp-build": {
|
||||
"version": "4.8.4",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||
"optional": true
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"dev": true
|
||||
},
|
||||
"unifi-protect": {
|
||||
"version": "4.16.0",
|
||||
"resolved": "https://registry.npmjs.org/unifi-protect/-/unifi-protect-4.16.0.tgz",
|
||||
"integrity": "sha512-M8/VUTKhPxlzagIQdpjvXbdUPp4a/3F051CghaLXWT9JfnVuJZGLYC3U1zYOXtKVIfqP+KcTmn6sSTawHTGADQ==",
|
||||
"requires": {
|
||||
"@adobe/fetch": "4.1.9",
|
||||
"bufferutil": "4.0.8",
|
||||
"ws": "8.18.0"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
||||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"type": "module",
|
||||
"version": "0.0.164",
|
||||
"description": "Unifi Protect Plugin for Scrypted",
|
||||
"author": "Scrypted",
|
||||
@@ -28,20 +29,22 @@
|
||||
"DeviceProvider",
|
||||
"Settings"
|
||||
],
|
||||
"babel": true,
|
||||
"pluginDependencies": [
|
||||
"@scrypted/prebuffer-mixin"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.4.2",
|
||||
"@types/ws": "^8.5.5"
|
||||
"@types/node": "^22.9.4",
|
||||
"@types/ws": "^8.5.13"
|
||||
},
|
||||
"dependencies": {
|
||||
"@koush/unifi-protect": "file:../../external/unifi-protect",
|
||||
"@scrypted/common": "file:../../common",
|
||||
"@scrypted/sdk": "file:../../sdk",
|
||||
"axios": "^1.4.0",
|
||||
"ws": "^8.13.0"
|
||||
"axios": "^1.7.8",
|
||||
"unifi-protect": "^4.16.0",
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@adobe/fetch": "^4.1.9"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,16 +96,16 @@ export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Interco
|
||||
}
|
||||
});
|
||||
|
||||
const camera = this.findCamera() as any;
|
||||
const camera = this.findCamera();
|
||||
|
||||
await this.protect.api.updateCamera(camera, {
|
||||
await this.protect.api.updateDevice(camera, {
|
||||
privacyZones,
|
||||
} as any);
|
||||
}
|
||||
|
||||
async ptzCommand(command: PanTiltZoomCommand): Promise<void> {
|
||||
const camera = this.findCamera() as any;
|
||||
await this.protect.api.updateCamera(camera, {
|
||||
const camera = this.findCamera();
|
||||
await this.protect.api.updateDevice(camera, {
|
||||
ispSettings: {
|
||||
zoomPosition: Math.abs(command.zoom * 100),
|
||||
}
|
||||
@@ -113,8 +113,8 @@ export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Interco
|
||||
}
|
||||
|
||||
async setStatusLight(on: boolean) {
|
||||
const camera = this.findCamera() as any;
|
||||
await this.protect.api.updateCamera(camera, {
|
||||
const camera = this.findCamera();
|
||||
await this.protect.api.updateDevice(camera, {
|
||||
ledSettings: {
|
||||
isEnabled: on,
|
||||
}
|
||||
@@ -170,8 +170,9 @@ export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Interco
|
||||
const ffmpegInput = JSON.parse(buffer.toString()) as FFmpegInput;
|
||||
|
||||
const camera = this.findCamera();
|
||||
const params = new URLSearchParams({ camera: camera.id });
|
||||
const response = await this.protect.loginFetch(this.protect.api.wsUrl() + "/talkback?" + params.toString());
|
||||
const endpoint = new URL(this.protect.api.getApiEndpoint("talkback"));
|
||||
endpoint.searchParams.set('camera', camera.id);
|
||||
const response = await this.protect.loginFetch(endpoint.toString());
|
||||
const tb = response.data as Record<string, string>;
|
||||
|
||||
// Adjust the URL for our address.
|
||||
@@ -375,7 +376,7 @@ export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Interco
|
||||
}
|
||||
findCamera() {
|
||||
const id = this.protect.findId(this.nativeId);
|
||||
return this.protect.api.cameras.find(camera => camera.id === id);
|
||||
return this.protect.api.bootstrap.cameras.find(camera => camera.id === id);
|
||||
}
|
||||
async getVideoStream(options?: MediaStreamOptions): Promise<MediaObject> {
|
||||
const camera = this.findCamera();
|
||||
@@ -441,7 +442,9 @@ export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Interco
|
||||
const sanitizedBitrate = Math.min(channel.maxBitrate, Math.max(channel.minBitrate, bitrate));
|
||||
this.console.log(channel.name, 'bitrate change requested', bitrate, 'clamped to', sanitizedBitrate);
|
||||
channel.bitrate = sanitizedBitrate;
|
||||
const cameraResult = await this.protect.api.updateCameraChannels(camera);
|
||||
const cameraResult = await this.protect.api.updateDevice(camera, {
|
||||
channels: camera.channels,
|
||||
});
|
||||
if (!cameraResult) {
|
||||
throw new Error("setVideoStreamOptions failed")
|
||||
}
|
||||
@@ -458,7 +461,7 @@ export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Interco
|
||||
|
||||
setMotionDetected(motionDetected: boolean) {
|
||||
this.motionDetected = motionDetected;
|
||||
if ((this.findCamera().featureFlags as any as FeatureFlagsShim).hasPackageCamera) {
|
||||
if (this.findCamera().featureFlags.hasPackageCamera) {
|
||||
if (deviceManager.getNativeIds().includes(this.packageCameraNativeId)) {
|
||||
this.ensurePackageCamera();
|
||||
this.packageCamera.motionDetected = motionDetected;
|
||||
@@ -480,7 +483,7 @@ export class UnifiCamera extends ScryptedDeviceBase implements Notifier, Interco
|
||||
text: title.substring(0, 30),
|
||||
type: 'CUSTOM_MESSAGE',
|
||||
};
|
||||
this.protect.api.updateCamera(this.findCamera(), {
|
||||
this.protect.api.updateDevice(this.findCamera(), {
|
||||
lcdMessage: payload,
|
||||
})
|
||||
|
||||
|
||||
@@ -14,23 +14,23 @@ export class UnifiLight extends ScryptedDeviceBase implements OnOff, Brightness,
|
||||
this.console.log(protectLight);
|
||||
}
|
||||
async turnOff(): Promise<void> {
|
||||
const result = await this.protect.api.updateLight(this.findLight(), { lightOnSettings: { isLedForceOn: false } });
|
||||
const result = await this.protect.api.updateDevice(this.findLight(), { lightOnSettings: { isLedForceOn: false } });
|
||||
if (!result)
|
||||
this.console.error('turnOff failed.');
|
||||
}
|
||||
async turnOn(): Promise<void> {
|
||||
const result = await this.protect.api.updateLight(this.findLight(), { lightOnSettings: { isLedForceOn: true } });
|
||||
const result = await this.protect.api.updateDevice(this.findLight(), { lightOnSettings: { isLedForceOn: true } });
|
||||
if (!result)
|
||||
this.console.error('turnOn failed.');
|
||||
}
|
||||
async setBrightness(brightness: number): Promise<void> {
|
||||
const ledLevel = Math.round(((brightness as number) / 20) + 1);
|
||||
this.protect.api.updateLight(this.findLight(), { lightDeviceSettings: { ledLevel } });
|
||||
this.protect.api.updateDevice(this.findLight(), { lightDeviceSettings: { ledLevel } });
|
||||
}
|
||||
|
||||
findLight() {
|
||||
const id = this.protect.findId(this.nativeId);
|
||||
return this.protect.api.lights.find(light => light.id === id);
|
||||
return this.protect.api.bootstrap.lights.find(light => light.id === id);
|
||||
}
|
||||
|
||||
updateState(light?: Readonly<ProtectLightConfig>) {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { Lock, LockState, ScryptedDeviceBase } from "@scrypted/sdk";
|
||||
import { UnifiProtect } from "./main";
|
||||
import { ProtectDoorLockConfig } from "./unifi-protect";
|
||||
|
||||
export class UnifiLock extends ScryptedDeviceBase implements Lock {
|
||||
constructor(public protect: UnifiProtect, nativeId: string, protectLock: Readonly<ProtectDoorLockConfig>) {
|
||||
constructor(public protect: UnifiProtect, nativeId: string, protectLock: any) {
|
||||
super(nativeId);
|
||||
|
||||
this.updateState(protectLock);
|
||||
@@ -11,23 +10,23 @@ export class UnifiLock extends ScryptedDeviceBase implements Lock {
|
||||
}
|
||||
|
||||
async lock(): Promise<void> {
|
||||
await this.protect.loginFetch(this.protect.api.doorlocksUrl() + `/${this.findLock().id}/close`, {
|
||||
await this.protect.loginFetch(this.protect.api.getApiEndpoint('doorlocks') + `/${this.findLock().id}/close`, {
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
|
||||
async unlock(): Promise<void> {
|
||||
await this.protect.loginFetch(this.protect.api.doorlocksUrl() + `/${this.findLock().id}/open`, {
|
||||
await this.protect.loginFetch(this.protect.api.getApiEndpoint('doorlocks') + `/${this.findLock().id}/open`, {
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
|
||||
findLock() {
|
||||
const id = this.protect.findId(this.nativeId);
|
||||
return this.protect.api.doorlocks.find(doorlock => doorlock.id === id);
|
||||
return (this.protect.api.bootstrap.doorlocks as any).find(doorlock => doorlock.id === id);
|
||||
}
|
||||
|
||||
updateState(lock?: Readonly<ProtectDoorLockConfig>) {
|
||||
updateState(lock?: any) {
|
||||
lock = lock || this.findLock();
|
||||
if (!lock)
|
||||
return;
|
||||
|
||||
@@ -4,12 +4,12 @@ import sdk, { Device, DeviceProvider, ObjectDetectionResult, ObjectsDetected, Sc
|
||||
import { StorageSettings } from "@scrypted/sdk/storage-settings";
|
||||
import axios from "axios";
|
||||
import { UnifiCamera } from "./camera";
|
||||
import { debounceFingerprintDetected, debounceMotionDetected } from "./camera-sensors";
|
||||
import { UnifiLight } from "./light";
|
||||
import { UnifiLock } from "./lock";
|
||||
import { debounceFingerprintDetected, debounceMotionDetected } from "./camera-sensors";
|
||||
import { UnifiSensor } from "./sensor";
|
||||
import { FeatureFlagsShim, LastSeenShim } from "./shim";
|
||||
import { ProtectApi, ProtectApiUpdates, ProtectNvrUpdatePayloadCameraUpdate, ProtectNvrUpdatePayloadEventAdd } from "./unifi-protect";
|
||||
import { FeatureFlagsShim } from "./shim";
|
||||
import { ProtectApi, ProtectCameraConfigInterface, ProtectEventAddInterface, ProtectEventPacket } from "./unifi-protect";
|
||||
|
||||
const { deviceManager } = sdk;
|
||||
|
||||
@@ -54,10 +54,10 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
return;
|
||||
}
|
||||
|
||||
const device = this.api.cameras?.find(c => c.id === packet.action.id)
|
||||
|| this.api.lights?.find(c => c.id === packet.action.id)
|
||||
|| this.api.doorlocks?.find(c => c.id === packet.action.id)
|
||||
|| this.api.sensors?.find(c => c.id === packet.action.id);
|
||||
const device = this.api.bootstrap.cameras?.find(c => c.id === packet.action.id)
|
||||
|| this.api.bootstrap.lights?.find(c => c.id === packet.action.id)
|
||||
|| (this.api.bootstrap.doorlocks as any)?.find(c => c.id === packet.action.id)
|
||||
|| this.api.bootstrap.sensors?.find(c => c.id === packet.action.id);
|
||||
|
||||
if (!device) {
|
||||
return;
|
||||
@@ -100,8 +100,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
})
|
||||
}
|
||||
|
||||
listener(event: Buffer) {
|
||||
const updatePacket = ProtectApiUpdates.decodeUpdatePacket(this.console, event);
|
||||
listener(updatePacket: ProtectEventPacket) {
|
||||
if (!updatePacket)
|
||||
return;
|
||||
|
||||
@@ -109,27 +108,27 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
|
||||
const unifiDevice = this.handleUpdatePacket(updatePacket);
|
||||
|
||||
switch (updatePacket.action.modelKey) {
|
||||
switch (updatePacket.header.modelKey) {
|
||||
case "sensor":
|
||||
case "doorlock":
|
||||
case "light":
|
||||
case "camera": {
|
||||
if (!unifiDevice) {
|
||||
this.console.log('unknown device, sync needed?', updatePacket.action.id);
|
||||
this.console.log('unknown device, sync needed?', updatePacket.header.id);
|
||||
return;
|
||||
}
|
||||
if (updatePacket.action.action !== "update") {
|
||||
unifiDevice.console.log('non update', updatePacket.action.action);
|
||||
if (updatePacket.header.action !== "update") {
|
||||
unifiDevice.console.log('non update', updatePacket.header.action);
|
||||
return;
|
||||
}
|
||||
unifiDevice.updateState();
|
||||
|
||||
if (updatePacket.action.modelKey === "doorlock")
|
||||
if (updatePacket.header.modelKey === "doorlock")
|
||||
return;
|
||||
|
||||
const payload = updatePacket.payload as any as ProtectNvrUpdatePayloadCameraUpdate & LastSeenShim;
|
||||
const payload = updatePacket.payload as ProtectCameraConfigInterface;
|
||||
|
||||
if (updatePacket.action.modelKey !== "camera")
|
||||
if (updatePacket.header.modelKey !== "camera")
|
||||
return;
|
||||
|
||||
const unifiCamera = unifiDevice as UnifiCamera;
|
||||
@@ -142,19 +141,19 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
break;
|
||||
}
|
||||
case "event": {
|
||||
if (updatePacket.action.action !== "add") {
|
||||
if ((updatePacket?.payload as any)?.end && updatePacket.action.id) {
|
||||
const payload = updatePacket.payload as ProtectEventAddInterface;
|
||||
if (updatePacket.header.action !== "add") {
|
||||
if (payload.end && updatePacket.header.id) {
|
||||
// unifi reports the event ended but it seems to take a moment before the snapshot
|
||||
// is actually ready.
|
||||
setTimeout(() => {
|
||||
const running = this.runningEvents.get(updatePacket.action.id);
|
||||
const running = this.runningEvents.get(updatePacket.header.id);
|
||||
running?.resolve?.(undefined)
|
||||
}, 2000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = updatePacket.payload as ProtectNvrUpdatePayloadEventAdd;
|
||||
if (!payload.camera)
|
||||
return;
|
||||
const nativeId = this.getNativeId({ id: payload.camera }, false);
|
||||
@@ -166,7 +165,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
}
|
||||
|
||||
const detectionId = payload.id;
|
||||
const actionId = updatePacket.action.id;
|
||||
const actionId = updatePacket.header.id;
|
||||
|
||||
let resolve: (value: unknown) => void;
|
||||
const promise = new Promise(r => resolve = r);
|
||||
@@ -249,7 +248,26 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
this.console.log(message, ...parameters);
|
||||
}
|
||||
|
||||
|
||||
reconnecting = false;
|
||||
wsTimeout: NodeJS.Timeout;
|
||||
reconnect(reason: string) {
|
||||
return async () => {
|
||||
if (this.reconnecting)
|
||||
return;
|
||||
this.reconnecting = true;
|
||||
this.api?.reset();
|
||||
this.console.error('Event Listener reconnecting in 10 seconds:', reason);
|
||||
await sleep(10000);
|
||||
this.discoverDevices(0);
|
||||
}
|
||||
}
|
||||
|
||||
async discoverDevices(duration: number) {
|
||||
this.api?.reset();
|
||||
this.reconnecting = false;
|
||||
clearTimeout(this.wsTimeout);
|
||||
|
||||
const ip = this.getSetting('ip');
|
||||
const username = this.getSetting('username');
|
||||
const password = this.getSetting('password');
|
||||
@@ -271,10 +289,8 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
return
|
||||
}
|
||||
|
||||
this.api?.eventsWs?.removeAllListeners();
|
||||
this.api?.eventsWs?.close();
|
||||
if (!this.api) {
|
||||
this.api = new ProtectApi(ip, username, password, {
|
||||
this.api = new ProtectApi({
|
||||
debug() { },
|
||||
error: (...args) => {
|
||||
this.console.error(...args);
|
||||
@@ -284,48 +300,37 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
});
|
||||
}
|
||||
|
||||
let reconnecting = false;
|
||||
const reconnect = (reason: string) => {
|
||||
return async () => {
|
||||
if (reconnecting)
|
||||
return;
|
||||
reconnecting = true;
|
||||
this.api?.eventsWs?.close();
|
||||
this.api?.eventsWs?.emit('close');
|
||||
this.api?.eventsWs?.removeAllListeners();
|
||||
if (this.api.eventsWs) {
|
||||
this.console.warn('Event Listener failed to close. Requesting plugin restart.');
|
||||
deviceManager.requestRestart();
|
||||
}
|
||||
this.console.error('Event Listener reconnecting in 10 seconds:', reason);
|
||||
await sleep(10000);
|
||||
this.discoverDevices(0);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (!await this.api.refreshDevices()) {
|
||||
reconnect('refresh failed')();
|
||||
const loginResult = await this.api.login(ip, username, password);
|
||||
if (!loginResult) {
|
||||
this.log.a('Login failed. Check credentials.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await this.api.getBootstrap()) {
|
||||
this.reconnect('refresh failed')();
|
||||
return;
|
||||
}
|
||||
|
||||
let wsTimeout: NodeJS.Timeout;
|
||||
const resetWsTimeout = () => {
|
||||
clearTimeout(wsTimeout);
|
||||
wsTimeout = setTimeout(reconnect('timeout'), 5 * 60 * 1000);
|
||||
clearTimeout(this.wsTimeout);
|
||||
this.wsTimeout = setTimeout(() => this.reconnect('timeout'), 5 * 60 * 1000);
|
||||
};
|
||||
resetWsTimeout();
|
||||
|
||||
this.api.eventsWs?.on('message', (data) => {
|
||||
this.api.on('message', message => {
|
||||
resetWsTimeout();
|
||||
this.listener(data as Buffer);
|
||||
});
|
||||
this.api.eventsWs?.on('close', reconnect('close'));
|
||||
this.api.eventsWs?.on('error', reconnect('error'));
|
||||
this.listener(message);
|
||||
})
|
||||
|
||||
const devices: Device[] = [];
|
||||
|
||||
for (let camera of this.api.cameras || []) {
|
||||
if (!this.api.bootstrap.cameras.length) {
|
||||
this.console.warn('no cameras found. is this an admin account? cancelling sync.');
|
||||
return;
|
||||
}
|
||||
|
||||
for (let camera of this.api.bootstrap.cameras || []) {
|
||||
if (camera.isAdoptedByOther) {
|
||||
this.console.log('skipping camera that is adopted by another nvr', camera.id, camera.name);
|
||||
continue;
|
||||
@@ -347,7 +352,9 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
}
|
||||
|
||||
if (needUpdate) {
|
||||
camera = await this.api.updateCameraChannels(camera);
|
||||
camera = await this.api.updateDevice(camera, {
|
||||
channels: camera.channels,
|
||||
});
|
||||
if (!camera) {
|
||||
this.log.a('Unable to enable RTSP and IDR interval on camera. Is this an admin account?');
|
||||
continue;
|
||||
@@ -392,7 +399,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
if (camera.featureFlags.hasLcdScreen) {
|
||||
d.interfaces.push(ScryptedInterface.Notifier);
|
||||
}
|
||||
if ((camera.featureFlags as any as FeatureFlagsShim).hasPackageCamera) {
|
||||
if (camera.featureFlags.hasPackageCamera) {
|
||||
d.interfaces.push(ScryptedInterface.DeviceProvider);
|
||||
}
|
||||
if (camera.featureFlags.hasLedStatus) {
|
||||
@@ -405,7 +412,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
devices.push(d);
|
||||
}
|
||||
|
||||
for (const sensor of this.api.sensors || []) {
|
||||
for (const sensor of this.api.bootstrap.sensors || []) {
|
||||
const d: Device = {
|
||||
providerNativeId: this.nativeId,
|
||||
name: sensor.name,
|
||||
@@ -413,7 +420,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
info: {
|
||||
manufacturer: 'Ubiquiti',
|
||||
model: sensor.type,
|
||||
ip: sensor.host,
|
||||
ip: (sensor as any).host,
|
||||
firmware: sensor.firmwareVersion,
|
||||
version: sensor.hardwareRevision,
|
||||
serialNumber: sensor.id,
|
||||
@@ -433,7 +440,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
devices.push(d);
|
||||
}
|
||||
|
||||
for (const light of this.api.lights || []) {
|
||||
for (const light of this.api.bootstrap.lights || []) {
|
||||
const d: Device = {
|
||||
providerNativeId: this.nativeId,
|
||||
name: light.name,
|
||||
@@ -458,7 +465,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
devices.push(d);
|
||||
}
|
||||
|
||||
for (const lock of this.api.doorlocks || []) {
|
||||
for (const lock of (this.api.bootstrap.doorlocks as any) || []) {
|
||||
const d: Device = {
|
||||
providerNativeId: this.nativeId,
|
||||
name: lock.name,
|
||||
@@ -490,12 +497,12 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
}
|
||||
|
||||
// handle package cameras as a sub device
|
||||
for (const camera of this.api.cameras) {
|
||||
for (const camera of this.api.bootstrap.cameras) {
|
||||
const devices: Device[] = [];
|
||||
|
||||
const providerNativeId = this.getNativeId(camera, true);
|
||||
|
||||
if ((camera.featureFlags as any as FeatureFlagsShim).hasPackageCamera) {
|
||||
if (camera.featureFlags.hasPackageCamera) {
|
||||
const nativeId = providerNativeId + '-packageCamera';
|
||||
const d: Device = {
|
||||
providerNativeId,
|
||||
@@ -569,25 +576,25 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
return this.locks.get(nativeId);
|
||||
|
||||
const id = this.findId(nativeId);
|
||||
const camera = this.api.cameras.find(camera => camera.id === id);
|
||||
const camera = this.api.bootstrap.cameras.find(camera => camera.id === id);
|
||||
if (camera) {
|
||||
const ret = new UnifiCamera(this, nativeId, camera);
|
||||
this.cameras.set(nativeId, ret);
|
||||
return ret;
|
||||
}
|
||||
const sensor = this.api.sensors.find(sensor => sensor.id === id);
|
||||
const sensor = this.api.bootstrap.sensors.find(sensor => sensor.id === id);
|
||||
if (sensor) {
|
||||
const ret = new UnifiSensor(this, nativeId, sensor);
|
||||
this.sensors.set(nativeId, ret);
|
||||
return ret;
|
||||
}
|
||||
const light = this.api.lights.find(light => light.id === id);
|
||||
const light = this.api.bootstrap.lights.find(light => light.id === id);
|
||||
if (light) {
|
||||
const ret = new UnifiLight(this, nativeId, light);
|
||||
this.lights.set(nativeId, ret);
|
||||
return ret;
|
||||
}
|
||||
const lock = this.api.doorlocks?.find(lock => lock.id === id);
|
||||
const lock = (this.api.bootstrap.doorlocks as any)?.find(lock => lock.id === id);
|
||||
if (lock) {
|
||||
const ret = new UnifiLock(this, nativeId, lock);
|
||||
this.locks.set(nativeId, ret);
|
||||
|
||||
@@ -15,7 +15,7 @@ export class UnifiSensor extends ScryptedDeviceBase implements Thermometer, Humi
|
||||
|
||||
findSensor() {
|
||||
const id = this.protect.findId(this.nativeId);
|
||||
return this.protect.api.sensors.find(sensor => sensor.id === id);
|
||||
return this.protect.api.bootstrap.sensors.find(sensor => sensor.id === id);
|
||||
}
|
||||
|
||||
async setTemperatureUnit(temperatureUnit: TemperatureUnit): Promise<void> {
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
|
||||
export interface FeatureFlagsShim {
|
||||
hasPackageCamera: boolean;
|
||||
hasFingerprintSensor: boolean;
|
||||
}
|
||||
|
||||
export interface LastSeenShim {
|
||||
lastSeen: number;
|
||||
}
|
||||
|
||||
export interface PrivacyZone {
|
||||
id: number;
|
||||
name: string;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// export * from '@koush/unifi-protect'
|
||||
export * from '@koush/unifi-protect/src/index'
|
||||
export * from 'unifi-protect'
|
||||
// export * from '../../../external/unifi-protect/src/index'
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "Node16",
|
||||
"module": "es2022",
|
||||
"target": "ES2021",
|
||||
"resolveJsonModule": true,
|
||||
"moduleResolution": "Node16",
|
||||
"moduleResolution": "bundler",
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user