mirror of
https://github.com/koush/scrypted.git
synced 2026-05-04 21:30:30 +01:00
amcrest
This commit is contained in:
4
plugins/amcrest/.gitignore
vendored
Normal file
4
plugins/amcrest/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.DS_Store
|
||||
out/
|
||||
node_modules/
|
||||
dist/
|
||||
4
plugins/amcrest/.npmignore
Normal file
4
plugins/amcrest/.npmignore
Normal file
@@ -0,0 +1,4 @@
|
||||
.DS_Store
|
||||
out/
|
||||
node_modules/
|
||||
dist/*.map
|
||||
22
plugins/amcrest/.vscode/launch.json
vendored
Normal file
22
plugins/amcrest/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Scrypted Debugger",
|
||||
"address": "${config:scrypted.debugHost}",
|
||||
"port": 9091,
|
||||
"request": "attach",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"preLaunchTask": "scrypted: deploy+debug",
|
||||
"sourceMaps": true,
|
||||
"localRoot": "${workspaceFolder}/out",
|
||||
"remoteRoot": "/plugin/",
|
||||
"type": "pwa-node"
|
||||
}
|
||||
]
|
||||
}
|
||||
4
plugins/amcrest/.vscode/settings.json
vendored
Normal file
4
plugins/amcrest/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
{
|
||||
"scrypted.debugHost": "127.0.0.1",
|
||||
}
|
||||
20
plugins/amcrest/.vscode/tasks.json
vendored
Normal file
20
plugins/amcrest/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "scrypted: deploy+debug",
|
||||
"type": "shell",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "silent",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": true,
|
||||
"clear": false
|
||||
},
|
||||
"command": "npm run scrypted-vscode-launch ${config:scrypted.debugHost}",
|
||||
},
|
||||
]
|
||||
}
|
||||
15
plugins/amcrest/README.md
Normal file
15
plugins/amcrest/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Amcrest Plugin
|
||||
|
||||
## npm commands
|
||||
* npm run scrypted-webpack
|
||||
* npm run scrypted-deploy <ipaddress>
|
||||
* npm run scrypted-debug <ipaddress>
|
||||
|
||||
## scrypted distribution via npm
|
||||
1. Ensure package.json is set up properly for publishing on npm.
|
||||
2. npm publish
|
||||
|
||||
## Visual Studio Code configuration
|
||||
|
||||
* If using a remote server, edit [.vscode/settings.json](blob/master/.vscode/settings.json) to specify the IP Address of the Scrypted server.
|
||||
* Launch Scrypted Debugger from the launch menu.
|
||||
413
plugins/amcrest/package-lock.json
generated
Normal file
413
plugins/amcrest/package-lock.json
generated
Normal file
@@ -0,0 +1,413 @@
|
||||
{
|
||||
"name": "@scrypted/amcrest",
|
||||
"version": "0.0.16",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/amcrest",
|
||||
"version": "0.0.16",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"@mhoc/axios-digest-auth": "^0.7.0",
|
||||
"axios": "^0.21.1",
|
||||
"multiparty": "^4.2.2",
|
||||
"url-parse": "^1.4.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@scrypted/sdk": "file:../../sdk",
|
||||
"@types/multiparty": "^0.0.33",
|
||||
"@types/node": "^16.7.10"
|
||||
}
|
||||
},
|
||||
"../../sdk": {
|
||||
"name": "@scrypted/sdk",
|
||||
"version": "0.0.67",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.2.2",
|
||||
"@babel/plugin-proposal-class-properties": "^7.4.4",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
|
||||
"@babel/plugin-transform-typescript": "^7.15.0",
|
||||
"@babel/polyfill": "^7.2.5",
|
||||
"@babel/preset-env": "^7.2.3",
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"adm-zip": "^0.4.13",
|
||||
"axios": "^0.21.1",
|
||||
"babel-loader": "^8.0.4",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-template": "^6.26.0",
|
||||
"browserify-buffertools": "^1.0.2",
|
||||
"bytebuffer": "^5.0.1",
|
||||
"chalk": "^2.4.2",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"engine.io-client": "^3.3.2",
|
||||
"event-target-shim": "^5.0.1",
|
||||
"events": "^3.0.0",
|
||||
"long": "^4.0.0",
|
||||
"node-cmd": "^3.0.0",
|
||||
"node-ip": "^0.1.2",
|
||||
"raw-loader": "^1.0.0",
|
||||
"terser": "^3.14.1",
|
||||
"ts-loader": "^5.4.5",
|
||||
"tsconfig-paths-webpack-plugin": "^3.2.0",
|
||||
"typescript": "^4.3.5",
|
||||
"webpack": "^4.28.1",
|
||||
"webpack-cli": "^3.1.2",
|
||||
"webpack-inject-plugin": "^1.0.2"
|
||||
},
|
||||
"bin": {
|
||||
"scrypted-debug": "bin/scrypted-debug.js",
|
||||
"scrypted-deploy": "bin/scrypted-deploy.js",
|
||||
"scrypted-deploy-debug": "bin/scrypted-deploy-debug.js",
|
||||
"scrypted-package-json": "bin/scrypted-package-json.js",
|
||||
"scrypted-readme": "bin/scrypted-readme.js",
|
||||
"scrypted-webpack": "bin/scrypted-webpack.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.13.12",
|
||||
"@types/node": "^16.6.1",
|
||||
"babel-plugin-const-enum": "^1.1.0",
|
||||
"babel-plugin-minify-dead-code-elimination": "^0.5.1"
|
||||
}
|
||||
},
|
||||
"../sdk": {
|
||||
"extraneous": true
|
||||
},
|
||||
"node_modules/@mhoc/axios-digest-auth": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@mhoc/axios-digest-auth/-/axios-digest-auth-0.7.0.tgz",
|
||||
"integrity": "sha512-fDi8fNmuLmX86XEtqD6E59ytLROjmo3O9ZZAT5ndnFJpntOg1912sV/dA218GfQv6UviCFnpEogwuyWTnHmGng==",
|
||||
"dependencies": {
|
||||
"axios": "0.21.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@scrypted/sdk": {
|
||||
"resolved": "../../sdk",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@types/multiparty": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/multiparty/-/multiparty-0.0.33.tgz",
|
||||
"integrity": "sha512-Il6cJUpSqgojT7NxbVJUvXkCblm50/yEJYtblISDsNIeNYf4yMAhdizzidUk6h8pJ8yhwK/3Fkb+3Dwcgtwl8w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.7.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.10.tgz",
|
||||
"integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.14.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz",
|
||||
"integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz",
|
||||
"integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==",
|
||||
"dependencies": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/multiparty": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.2.tgz",
|
||||
"integrity": "sha512-NtZLjlvsjcoGrzojtwQwn/Tm90aWJ6XXtPppYF4WmOk/6ncdwMMKggFY2NlRRN9yiCEIVxpOfPWahVEG2HAG8Q==",
|
||||
"dependencies": {
|
||||
"http-errors": "~1.8.0",
|
||||
"safe-buffer": "5.2.1",
|
||||
"uid-safe": "2.1.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/querystringify": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
|
||||
"integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA=="
|
||||
},
|
||||
"node_modules/random-bytes": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
|
||||
"integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"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/setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/uid-safe": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
|
||||
"dependencies": {
|
||||
"random-bytes": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/url-parse": {
|
||||
"version": "1.4.7",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
|
||||
"integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
|
||||
"dependencies": {
|
||||
"querystringify": "^2.1.1",
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@mhoc/axios-digest-auth": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@mhoc/axios-digest-auth/-/axios-digest-auth-0.7.0.tgz",
|
||||
"integrity": "sha512-fDi8fNmuLmX86XEtqD6E59ytLROjmo3O9ZZAT5ndnFJpntOg1912sV/dA218GfQv6UviCFnpEogwuyWTnHmGng==",
|
||||
"requires": {
|
||||
"axios": "0.21.1"
|
||||
}
|
||||
},
|
||||
"@scrypted/sdk": {
|
||||
"version": "file:../../sdk",
|
||||
"requires": {
|
||||
"@babel/core": "^7.2.2",
|
||||
"@babel/plugin-proposal-class-properties": "^7.4.4",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.13.12",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
|
||||
"@babel/plugin-transform-typescript": "^7.15.0",
|
||||
"@babel/polyfill": "^7.2.5",
|
||||
"@babel/preset-env": "^7.2.3",
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"@types/node": "^16.6.1",
|
||||
"adm-zip": "^0.4.13",
|
||||
"axios": "^0.21.1",
|
||||
"babel-loader": "^8.0.4",
|
||||
"babel-plugin-const-enum": "^1.1.0",
|
||||
"babel-plugin-minify-dead-code-elimination": "^0.5.1",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-template": "^6.26.0",
|
||||
"browserify-buffertools": "^1.0.2",
|
||||
"bytebuffer": "^5.0.1",
|
||||
"chalk": "^2.4.2",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"engine.io-client": "^3.3.2",
|
||||
"event-target-shim": "^5.0.1",
|
||||
"events": "^3.0.0",
|
||||
"long": "^4.0.0",
|
||||
"node-cmd": "^3.0.0",
|
||||
"node-ip": "^0.1.2",
|
||||
"raw-loader": "^1.0.0",
|
||||
"terser": "^3.14.1",
|
||||
"ts-loader": "^5.4.5",
|
||||
"tsconfig-paths-webpack-plugin": "^3.2.0",
|
||||
"typescript": "^4.3.5",
|
||||
"webpack": "^4.28.1",
|
||||
"webpack-cli": "^3.1.2",
|
||||
"webpack-inject-plugin": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"@types/multiparty": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/multiparty/-/multiparty-0.0.33.tgz",
|
||||
"integrity": "sha512-Il6cJUpSqgojT7NxbVJUvXkCblm50/yEJYtblISDsNIeNYf4yMAhdizzidUk6h8pJ8yhwK/3Fkb+3Dwcgtwl8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.7.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.10.tgz",
|
||||
"integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==",
|
||||
"dev": true
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz",
|
||||
"integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA=="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz",
|
||||
"integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"multiparty": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.2.tgz",
|
||||
"integrity": "sha512-NtZLjlvsjcoGrzojtwQwn/Tm90aWJ6XXtPppYF4WmOk/6ncdwMMKggFY2NlRRN9yiCEIVxpOfPWahVEG2HAG8Q==",
|
||||
"requires": {
|
||||
"http-errors": "~1.8.0",
|
||||
"safe-buffer": "5.2.1",
|
||||
"uid-safe": "2.1.5"
|
||||
}
|
||||
},
|
||||
"querystringify": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
|
||||
"integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA=="
|
||||
},
|
||||
"random-bytes": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
|
||||
"integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
|
||||
},
|
||||
"requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"uid-safe": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
|
||||
"requires": {
|
||||
"random-bytes": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.4.7",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
|
||||
"integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
plugins/amcrest/package.json
Normal file
42
plugins/amcrest/package.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "@scrypted/amcrest",
|
||||
"version": "0.0.16",
|
||||
"description": "Amcrest Plugin for Scrypted",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache",
|
||||
"scripts": {
|
||||
"prepublishOnly": "NODE_ENV=production scrypted-webpack",
|
||||
"prescrypted-vscode-launch": "scrypted-webpack",
|
||||
"scrypted-vscode-launch": "scrypted-deploy-debug",
|
||||
"scrypted-deploy-debug": "scrypted-deploy-debug",
|
||||
"scrypted-debug": "scrypted-debug",
|
||||
"scrypted-deploy": "scrypted-deploy",
|
||||
"scrypted-readme": "scrypted-readme",
|
||||
"scrypted-package-json": "scrypted-package-json",
|
||||
"scrypted-webpack": "scrypted-webpack"
|
||||
},
|
||||
"keywords": [
|
||||
"scrypted",
|
||||
"plugin",
|
||||
"amcrest"
|
||||
],
|
||||
"scrypted": {
|
||||
"name": "Amcrest Camera Controller",
|
||||
"type": "DeviceProvider",
|
||||
"interfaces": [
|
||||
"DeviceProvider",
|
||||
"Settings"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@scrypted/sdk": "file:../../sdk",
|
||||
"@types/multiparty": "^0.0.33",
|
||||
"@types/node": "^16.7.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mhoc/axios-digest-auth": "^0.7.0",
|
||||
"axios": "^0.21.1",
|
||||
"multiparty": "^4.2.2",
|
||||
"url-parse": "^1.4.7"
|
||||
}
|
||||
}
|
||||
75
plugins/amcrest/src/amcrest-api.ts
Normal file
75
plugins/amcrest/src/amcrest-api.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import AxiosDigestAuth from '@mhoc/axios-digest-auth';
|
||||
import { Socket } from 'net';
|
||||
import { PassThrough, Readable, Stream } from 'stream';
|
||||
import {Form, Part} from 'multiparty';
|
||||
import { once } from 'events';
|
||||
|
||||
export enum AmcrestEvent {
|
||||
MotionStart = "MotionStart",
|
||||
MotionStop = "MotionStop",
|
||||
}
|
||||
|
||||
async function readEvent(readable: Readable): Promise<AmcrestEvent|void> {
|
||||
const pt = new PassThrough();
|
||||
readable.pipe(pt);
|
||||
const buffers: Buffer[] = [];
|
||||
for await (const buffer of pt) {
|
||||
buffers.push(buffer);
|
||||
const data = Buffer.concat(buffers).toString();
|
||||
if (data.indexOf('Code=VideoMotion;action=Stop') !== -1) {
|
||||
return AmcrestEvent.MotionStop;
|
||||
}
|
||||
else if (data.indexOf('Code=VideoMotion;action=Start') !== -1) {
|
||||
return AmcrestEvent.MotionStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class AmcrestCameraClient {
|
||||
digestAuth: AxiosDigestAuth;
|
||||
|
||||
constructor(public ip: string, public username: string, public password: string) {
|
||||
|
||||
this.digestAuth = new AxiosDigestAuth({
|
||||
username,
|
||||
password,
|
||||
});
|
||||
}
|
||||
|
||||
async jpegSnapshot(): Promise<Buffer> {
|
||||
const response = await this.digestAuth.request({
|
||||
method: "GET",
|
||||
responseType: 'arraybuffer',
|
||||
url: `http://${this.ip}/cgi-bin/snapshot.cgi`,
|
||||
});
|
||||
|
||||
return Buffer.from(response.data);
|
||||
}
|
||||
|
||||
async* listenForMotionEvents(): AsyncGenerator<AmcrestEvent> {
|
||||
const response = await this.digestAuth.request({
|
||||
method: "GET",
|
||||
responseType: 'stream',
|
||||
url: `http://${this.ip}/cgi-bin/eventManager.cgi?action=attach&codes=[VideoMotion]`,
|
||||
});
|
||||
|
||||
const stream = response.data;
|
||||
|
||||
const form = new Form();
|
||||
|
||||
try {
|
||||
// massage this so the parser doesn't fail on a bad content type
|
||||
stream.headers['content-type'] = stream.headers['content-type'].replace('multipart/x-mixed-replace', 'multipart/form-data');
|
||||
form.parse(stream);
|
||||
while (true) {
|
||||
const [part] = await once(form, 'part');
|
||||
const event = await readEvent(part);
|
||||
if (event)
|
||||
yield event;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stream.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
133
plugins/amcrest/src/main.ts
Normal file
133
plugins/amcrest/src/main.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import sdk, { ScryptedDeviceBase, DeviceProvider, Settings, Setting, ScryptedDeviceType, VideoCamera, MediaObject, VideoStreamOptions, Camera, ScryptedInterface } from "@scrypted/sdk";
|
||||
import { Stream } from "stream";
|
||||
import { AmcrestCameraClient, AmcrestEvent } from "./amcrest-api";
|
||||
const { log, deviceManager, mediaManager } = sdk;
|
||||
|
||||
class AmcrestCamera extends ScryptedDeviceBase implements VideoCamera, Camera, Settings {
|
||||
eventStream: Stream;
|
||||
|
||||
constructor(nativeId: string) {
|
||||
super(nativeId);
|
||||
|
||||
this.createMotionStream();
|
||||
}
|
||||
|
||||
async createMotionStream() {
|
||||
while (true) {
|
||||
try {
|
||||
this.motionDetected = false;
|
||||
|
||||
const api = new AmcrestCameraClient(this.storage.getItem('ip'), this.storage.getItem('username'), this.storage.getItem('password'));
|
||||
for await (const event of api.listenForMotionEvents()) {
|
||||
if (event === AmcrestEvent.MotionStart)
|
||||
this.motionDetected = true;
|
||||
else if (event === AmcrestEvent.MotionStop) {
|
||||
this.motionDetected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.error('event listener failure', e);
|
||||
await new Promise(resolve => setTimeout(resolve, 10000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createClient() {
|
||||
return new AmcrestCameraClient(this.storage.getItem('ip'), this.storage.getItem('username'), this.storage.getItem('password'));
|
||||
}
|
||||
|
||||
async takePicture(): Promise<MediaObject> {
|
||||
const api = new AmcrestCameraClient(this.storage.getItem('ip'), this.storage.getItem('username'), this.storage.getItem('password'));
|
||||
return mediaManager.createMediaObject(api.jpegSnapshot(), 'image/jpeg');
|
||||
}
|
||||
|
||||
async getVideoStreamOptions(): Promise<void | VideoStreamOptions[]> {
|
||||
}
|
||||
async getVideoStream(): Promise<MediaObject> {
|
||||
const ip = this.storage.getItem('ip');
|
||||
if (!ip) {
|
||||
return null;
|
||||
}
|
||||
const username = this.storage.getItem("username")
|
||||
const password = this.storage.getItem("password");
|
||||
const url = `rtsp://${username}:${password}@${ip}/cam/realmonitor?channel=1&subtype=0`;
|
||||
|
||||
return mediaManager.createFFmpegMediaObject({
|
||||
inputArguments: [
|
||||
"-i",
|
||||
url,
|
||||
'-analyzeduration', '15000000',
|
||||
'-probesize', '100000000',
|
||||
"-reorder_queue_size",
|
||||
"1024",
|
||||
"-max_delay",
|
||||
"20000000",
|
||||
]
|
||||
});
|
||||
}
|
||||
getSetting(key: string): string {
|
||||
return this.storage.getItem(key);
|
||||
}
|
||||
async getSettings(): Promise<Setting[]> {
|
||||
return [
|
||||
{
|
||||
key: 'ip',
|
||||
title: 'Amcrest Camera IP',
|
||||
placeholder: '192.168.1.100',
|
||||
value: this.getSetting('ip'),
|
||||
},
|
||||
{
|
||||
key: 'username',
|
||||
title: 'Username',
|
||||
value: this.getSetting('username'),
|
||||
},
|
||||
{
|
||||
key: 'password',
|
||||
title: 'Password',
|
||||
value: this.getSetting('password'),
|
||||
type: 'Password',
|
||||
}
|
||||
];
|
||||
}
|
||||
async putSetting(key: string, value: string | number) {
|
||||
this.storage.setItem(key, value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
class AmcrestProvider extends ScryptedDeviceBase implements DeviceProvider, Settings {
|
||||
async getSettings(): Promise<Setting[]> {
|
||||
return [
|
||||
{
|
||||
key: 'new-camera',
|
||||
title: 'Add Camera',
|
||||
placeholder: 'Camera name, e.g.: Back Yard Camera, Baby Camera, etc',
|
||||
}
|
||||
]
|
||||
}
|
||||
async putSetting(key: string, value: string | number) {
|
||||
// generate a random id
|
||||
var nativeId = Math.random().toString();
|
||||
var name = value.toString();
|
||||
|
||||
deviceManager.onDeviceDiscovered({
|
||||
nativeId,
|
||||
name: name,
|
||||
interfaces: [
|
||||
ScryptedInterface.VideoCamera,
|
||||
ScryptedInterface.Camera,
|
||||
ScryptedInterface.MotionSensor,
|
||||
ScryptedInterface.Settings,
|
||||
],
|
||||
type: ScryptedDeviceType.Camera,
|
||||
});
|
||||
}
|
||||
async discoverDevices(duration: number) {
|
||||
}
|
||||
|
||||
getDevice(nativeId: string): object {
|
||||
return new AmcrestCamera(nativeId);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AmcrestProvider();
|
||||
Reference in New Issue
Block a user